<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by conor hastings on Medium]]></title>
        <description><![CDATA[Stories by conor hastings on Medium]]></description>
        <link>https://medium.com/@stillconor?source=rss-a7c5f6af5983------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*-wGsrX9nBT1J0HjwCYWfIQ.jpeg</url>
            <title>Stories by conor hastings on Medium</title>
            <link>https://medium.com/@stillconor?source=rss-a7c5f6af5983------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 23 Jun 2026 17:09:39 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@stillconor/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Colocating Side Effects With Actions Using useReducer]]></title>
            <link>https://codeburst.io/colocating-side-effects-with-actions-using-usereducer-490368c96f77?source=rss-a7c5f6af5983------2</link>
            <guid isPermaLink="false">https://medium.com/p/490368c96f77</guid>
            <category><![CDATA[reason]]></category>
            <category><![CDATA[usereducer]]></category>
            <category><![CDATA[side-effects]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[react-hook]]></category>
            <dc:creator><![CDATA[conor hastings]]></dc:creator>
            <pubDate>Mon, 24 Jun 2019 04:29:59 GMT</pubDate>
            <atom:updated>2019-06-25T13:59:47.686Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*F-34sJTbZn5m547K_Ym96A.png" /></figure><p>The word colocation gets thrown around a lot these days.</p><p>*Styles* in my mind being the biggest example There seems to be a near constant conversation revolving around *colocating* styles with components, the argument often being that styles are **part** of the component and without them it would not be what it is. Putting the two together allows one to reason in a single place about what will appear on the page.</p><p>I won’t get into that here because I wish to spend most of my time *not* arguing about styles on twitter.</p><p>What I’ll talk about instead is React hooks, I believe they have introduced a place where we have an astonishing chance for colocation in data fetching and data flow in general.</p><p>I didn’t randomly choose to put bread and cheese emojis in the header image because those just so happened to be the two things currently on my mind, I see them as a great example of things that are commonly *colocated* in this real world everyone keeps telling me about (but I don’t get MTV I respond to rapturous laughter).</p><p>As hooks gain more and more popularity, specifically **useReducer** we often begin to see it paired with **useEffect** in many different sorts of ad hoc ways in fetching data. Something like this contrived example below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nP16S_5Qd4F8Kto-D9u7AA.png" /></figure><p>This code, barring mistakes I almost definitely made, should work, but the thought of slogging through this every time I’m doing something like loading an avatar is a nightmare. But I still love the **useReducer** pattern so whatttttt am I to do.</p><p>I believe **ReasonReact** has already solved for this with the <a href="https://github.com/reasonml/reason-react/blob/master/docs/state-actions-reducer.md">reducerComponent</a></p><p>**ReasonReact** provides the functions *Update*, *UpdateWithSideEffect*, *SideEffect*, and *NoUpdate* which are than used to wrap the value returned from the reducer allowing not so much the colocating of side effects with the reducer (which we still want to keep pure) but the colocation of the **INTENT** of side effects that will follow.</p><p>We can take this idea and bring it over to the world of React hooks to give us a somewhat similar experience, remove excessive code like that seen above, and provide a common pattern for teams to execute actions that lead to side effects. Hopefully causing easier understanding of the code, easier to review pull requests, and the actual important reason, less bugs reaching the end user.</p><p>Here’s what the above code might look like in that world.</p><p>We can take this idea and bring it over to the world of React hooks to give us a somewhat similar experience, remove code like that seen above, and provide a common pattern for teams to execute actions that lead to side effects leading to easier understanding of the code and easier to review pull requests.</p><p>Here’s what the above might look like in that world.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bQgW097jE0_deBCY07b_Ag.png" /></figure><p>We’re now able to colocate the fetching of the avatar with our declaration of intent to fetch the avatar, allowing us to follow in one section of code exactly what is happening.</p><p>I believe **ReasonReact** got this **super duper extremely correct** and am excited to use this pattern with React hooks as I develop new features.</p><p>You can see a library implementing this pattern <a href="https://github.com/conorhastings/use-reducer-with-side-effects">here</a> and to be honest it’s not all that difficult to do this or something similar on your own.</p><p>If you’re interested in hearing more on the topic and are the SF Bay Area I’ll be speaking on the topic at the <a href="https://www.meetup.com/ReactJS-San-Francisco/events/255322421/">July React Meetup</a></p><p>Looking forward to hearing what everyone thinks!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=490368c96f77" width="1" height="1" alt=""><hr><p><a href="https://codeburst.io/colocating-side-effects-with-actions-using-usereducer-490368c96f77">Colocating Side Effects With Actions Using useReducer</a> was originally published in <a href="https://codeburst.io">codeburst</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[RouteQL — GraphQL without the GraphQL]]></title>
            <link>https://codeburst.io/routeql-graphql-without-the-graphql-e5a9803ab706?source=rss-a7c5f6af5983------2</link>
            <guid isPermaLink="false">https://medium.com/p/e5a9803ab706</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[routeql]]></category>
            <category><![CDATA[frontend]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[graphql]]></category>
            <dc:creator><![CDATA[conor hastings]]></dc:creator>
            <pubDate>Mon, 30 Jul 2018 07:17:13 GMT</pubDate>
            <atom:updated>2018-07-30T18:04:33.868Z</atom:updated>
            <content:encoded><![CDATA[<p>GraphQL represents a paradigm shift in the way that we think about requesting data on the frontend.</p><p>Previously (and mostly still) we make opaque calls to a backend REST API AND we kind of know what we’re getting back because we read some hopefully up to date swagger documentation or we talked to the backend engineer who sits next to us or however we got into this inner circle of API knowledge.</p><p>This doesn’t account for a lot of things though. Someone else may take over development of the application, all they see is a request, maybe that request returns a ton of information that isn’t used and that person wonders why. They’ll crawl through some code and eventually figure out how the API works and go about their day because that’s a not all that difficult thing to do.</p><p>The paradigm shift that GraphQL brings — and I’m sure this has been said in hundreds if not thousands of previous blog posts — is that that opaqueness is removed, what you see is what you get.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/656/1*2tJoI70N6eLaobJ528bnVQ.png" /></figure><p>Here we can see we’re saying i want the hero, his friends, and his friends names. We know our frontends will get this data, or at the very least an object in this shape with some null fields.</p><p>For a long time I’ve thought about where the value in GraphQL lies, and there is no doubt in my mind that the type system and guarantees it provides are immensely powerful and endlessly helpful for API development and development on the front end, you know not only the shape but type of data you are getting.</p><p>Are there compromises we can make though? We have some APIs that are years old, some companies that are unwilling to invest in GraphQL as a technology, and a million other reasons we may not have a GraphQL server we can hit.</p><p>Should this rob us of our ability to have an expressive frontend development experience in which we can clearly see our components data needs colocated with the component itself? I don’t think so.</p><p>This is a problem that has kept me up at night for a very long time, and while this project is in its infancy I felt it would be better to share early and get feedback so maybe this silly idea in my head can become a real option as a middle ground between going all in on GraphQL and having opaque front end data handling. My goal is to use the expressive front end of the GraphQL query language while hitting any arbitrary backend, to have a new developer look at a component and say hey this is the data that’s supposed to come here and it’s not, now I can ask an informed question. I think I’ve made some really great strides in making this a real possibility.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nTOq4qMTsryoCiPNmgpMeQ.png" /><figcaption>A RouteQL Query that will hit 3 rest endpoints</figcaption></figure><p>If you look at the above code it really doesn’t look all that different from an <a href="https://www.apollographql.com/">Apollo</a> HOC query. the difference is here there is no backing GraphQL server, the query data is being translated into calls to arbitrary API endpoints using the GraphQL parser on the string and then traversing the AST in order to gather the relevant information to make the calls. The paradigm here essentially calls for the top level items (person, post, todos) to be routes available on the apiPrefix (or root of your server if apiPrefix is not provided)</p><p>From there we gather up relevant route parameters or query parameters and simply call the apis, gathering the data together into a single object, and passing it down into the wrapped component as props similar to what something like Apollo would do.</p><p>This essentially means that we can use GraphQL style querying on any route that we can hit, whether it is in our control or not. You can see an example of this in action <a href="https://example-iwcszelmgp.now.sh/">here</a>.</p><p>We make some tradeoffs, giving up some of the great benefits that come with a true GraphQL api including but not limited to types, better control over resolution, constructing the picked objects on the server instead of the client, and probably many more things that I don’t even know about.</p><p>In my probably biased opinion though this gives us easier access to the greatest thing GraphQL brought to frontend development. Expressive components with their data needs colocated right alongside. We shouldn’t be prevented from using this paradigm because we don’t have a GraphQL backend, we should be encouraging this style of component development wherever we can, and the nice thing is if you ever did move to a GraphQl backend the rewrite from this becomes vastly simpler then just constructed ad hoc API calls.</p><p>The work here is far from done and I’m positive there are many cases I have not yet covered but I’m convinced that I’ve stumbled upon something that could be great, and any feedback you have would be greatly appreciated (seriously any feedback, tell me I’m completely wrong). As I’ve said throughout this post and I’ll reiterate now I think GraphQL fundamentally changed the way we work with data on the frontend, if you can have an app backed by a GraphQL server I think you should, but I don’t think we should be limited by this and I think this project can make big strides in removing that limitation.</p><p>The code is on github <a href="https://github.com/conorhastings/routeql">here</a> if you would like to look at it. If nothing else I hope this post makes you think about what we can do to make our frontends and their increasingly complex data flows easier to reason about. In my opinion that’s colocated GraphQL or GraphQL style queries but if there’s something better I would love to here that too.</p><p>✌️</p><figure><a href="http://bit.ly/codeburst"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i3hPOj27LTt0ZPn5TQuhZg.png" /></a></figure><blockquote>✉️ <em>Subscribe to </em>CodeBurst’s<em> once-weekly </em><a href="http://bit.ly/codeburst-email"><strong><em>Email Blast</em></strong></a><strong><em>, </em></strong>🐦 <em>Follow </em>CodeBurst<em> on </em><a href="http://bit.ly/codeburst-twitter"><strong><em>Twitter</em></strong></a><em>, view </em>🗺️ <a href="http://bit.ly/2018-web-dev-roadmap"><strong><em>The 2018 Web Developer Roadmap</em></strong></a><em>, and </em>🕸️ <a href="http://bit.ly/learn-web-dev-codeburst"><strong><em>Learn Full Stack Web Development</em></strong></a><em>.</em></blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e5a9803ab706" width="1" height="1" alt=""><hr><p><a href="https://codeburst.io/routeql-graphql-without-the-graphql-e5a9803ab706">RouteQL — GraphQL without the GraphQL</a> was originally published in <a href="https://codeburst.io">codeburst</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[testing the schema compliance of an applications graphql queries — why not do it automatically?]]></title>
            <link>https://codeburst.io/testing-the-schema-compliance-of-an-applications-graphql-queries-why-not-do-it-automatically-bf31d1b8dc35?source=rss-a7c5f6af5983------2</link>
            <guid isPermaLink="false">https://medium.com/p/bf31d1b8dc35</guid>
            <category><![CDATA[apollostack]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[graphql]]></category>
            <category><![CDATA[apollo]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[conor hastings]]></dc:creator>
            <pubDate>Mon, 25 Sep 2017 02:40:35 GMT</pubDate>
            <atom:updated>2017-09-25T23:11:20.675Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/847/1*ho701rJiO1_z4mD-SyZd1g.gif" /><figcaption>medium recommends an image to capture the audiences attention, i’d like to think my audience is smarter than that, but i think medium is smarter than me since i’m just an idiot who refuses to use uppercase letters and is in the middle of writing a terrible run on sentence to describe a picture of text and not even really to describe just to make fun of what is probably a helpful tip from medium.</figcaption></figure><p>let me just get this right out of the way, i love graphql, it clicked for me as soon i read the first blog post about it.</p><p>at the time, i was primarily working on the front end of a large application, and the idea that i could have query syntax in the client with the ability to specify the exact shape of the data i was going to get back was amazing to me. and even better the schema on the server was typed so i wasn’t only going to know the shape of the data i was getting back, i was also going to be able to know the types 😍.</p><p>eventually i got the chance to use graphql on a project and it was everything i hoped for, using <a href="http://dev.apollodata.com/">apollo</a> on the client it was very clear what data every component needed at a glance, i no longer had to dig through internal api docs to find out what i was or wasn’t going to get back.</p><p>if everything was always rainbows and butterflies (shout out to adam levine) though i probably wouldn’t be writing this blog post. with multiple developers working on a project it can sometimes be impossible to keep track of everything. it’s very easy to change the schema on the server without making sure the schema change won’t cause errors to any of the queries on the client. i think someone said something once about humans making errors and it makes you human or something, i don’t know, graphql prevents a lot of those errors but it can’t really prevent the situation described above.</p><p>my coworker<a href="https://github.com/katherinethompson"> katherine thompson</a> and i have been exploring how we can prevent the situations above and have come up with some solutions that i think are interesting enough to share with the larger community as they have definitely helped us deploy our applications safely and continuously.</p><p>the root of the issue is simple, when we deploy (or when we commit, or at 1:19 am on a sunday night when something is just eating away at us because it doesn’t feel quite right and we probably have others issues but right now we’re just thinking about graphql schema so get off our back ok) we want to be able to know that every query in our client app can be validly resolved against our server schema. to that end we’ve created a collection of packages that can either recurse over nested directories of graphql queries in .graphql files or over directories containing javascript files with inline queries written using the <a href="https://github.com/apollographql/graphql-tag">graphql-tag</a> library (it will extract these queries first using a small utility library we’ve written —<a href="https://github.com/socialtables/gql-extract"> gql-extract </a>— to first parse out the queries from the tagged template strings) and then auto generate tests for these queries against a provided application schema.</p><p>we’re providing this tooling in a package that allows for use as either a javascript api or a command line interface and you can find it here:<a href="https://github.com/socialtables/graphql-test-generator"> graphql-test-generator</a>.</p><p>we personally utilize this in a pre-test step to generate tests that are then immediately run in npm test stage. this gives us the comfort of being able to deploy knowing all the queries our application could potentially attempt are schema safe. here’s an excerpt from a package.json file illustrating our use:</p><pre>{<br>  &quot;pretest&quot;: &quot;gqlTestExtraction -e ./src -o ./test -s    ../server/schema&quot;,    <br>  &quot;test&quot;: &quot;npm run lint &amp;&amp; tape test/*.js&quot;<br>}</pre><p>and here is an example generated tests:</p><pre>const { parse } = require(&quot;graphql/language&quot;);<br>const { validate } = require(&quot;graphql/validation&quot;);<br>const schema = require(&quot;../../tests/schema&quot;);<br>const query = `<br>    query getUserId {<br>        user {<br>            id<br>        }<br>    }<br>`;<br>const queryAST = parse(query);<br>const errors = validate(schema, queryAST);<br>const isValid = !errors.length;<br>const test = require(&quot;tape&quot;);<br>test(&quot;getUserId query adheres to application schema&quot;, assert =&gt; {<br> assert.ok(isValid, &quot;getUserId contains no schema errors&quot;);<br> assert.end();<br>});;</pre><p>by default a test using the <a href="https://github.com/substack/tape">tape</a> library is generated but you can use an optional parameter to point to your own test generation function, an example of that can be found here — <a href="https://github.com/socialtables/graphql-test-generator/blob/master/tests/test-for-failure.js">https://github.com/socialtables/graphql-test-generator/blob/master/tests/test-for-failure.js</a> — in which we are testing that a query is not valid in order to try to provide some proof that the library avoids false positives. in the future if there’s an interest we may provide defaults for several frameworks instead of forcing the admittedly clunky interface for generating a custom test.</p><p>graphql and apollo have been extremely productive for us as a company (and me an individual) and i’m hopeful these tools can offer as much help for others as they have for my team.</p><p>the library definitely still has some warts and edge cases so i’d be super appreciative if you submitted any issues you found here: <a href="https://github.com/socialtables/graphql-test-generator/issues">https://github.com/socialtables/graphql-test-generator/issues</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bf31d1b8dc35" width="1" height="1" alt=""><hr><p><a href="https://codeburst.io/testing-the-schema-compliance-of-an-applications-graphql-queries-why-not-do-it-automatically-bf31d1b8dc35">testing the schema compliance of an applications graphql queries — why not do it automatically?</a> was originally published in <a href="https://codeburst.io">codeburst</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[using babel(and webpack) to make ahead of time render decisions for branched components at build…]]></title>
            <link>https://codeburst.io/using-babel-and-webpack-for-ahead-of-time-decision-making-for-branched-components-6f675ec87db1?source=rss-a7c5f6af5983------2</link>
            <guid isPermaLink="false">https://medium.com/p/6f675ec87db1</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[webpack]]></category>
            <category><![CDATA[babel]]></category>
            <dc:creator><![CDATA[conor hastings]]></dc:creator>
            <pubDate>Sun, 23 Jul 2017 15:20:36 GMT</pubDate>
            <atom:updated>2017-07-23T15:54:17.316Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>using babel(and webpack) to make ahead of time render decisions for branched components at build time</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/858/1*pn8H6DcixhlxypbmmhPOUw.gif" /><figcaption>medium loves images</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/596/1*9JMMEiB9JmS-m_ihL9dIew.gif" /><figcaption>so here’s two</figcaption></figure><p>wow, that title is long, and i’m not even sure if it’s accurate. i read a lot of words and some of them i know, i hope i know the ones i used in the title.</p><p>anyway, moving on, as i explored in a <a href="https://codeburst.io/how-babel-helped-to-save-710kb-from-a-production-bundle-and-how-its-so-much-more-than-esnext-e3ff82a5b447">previous post</a>, we can use babel as more than just an esnext =&gt; espresent? compiler. here we’ll take a look at how we can use babel to make certain decisions for us at build time that would normally be deferred to runtime in order to hopefully speed up our applications.</p><p>imagine(or at least please try like really hard) that you have some sort of user permission system in your application that restricts access to some parts of your user interface based on permissions, you might wrap that ui in a component like this that restricts access to only those who can edit and shows some other component or nothing to those who can not.</p><pre>&lt;RequiredPermissions<br>  required={[“can_edit”]}<br>  permissions={this.props.permissions}<br>  notAllowedElement={&lt;Error /&gt;}<br>&gt;<br>  &lt;textarea onChange={() =&gt; {}}&gt;<br>    {this.props.content}<br>  &lt;/textarea&gt;<br>&lt;/RequiredPermissions&gt;</pre><p>a lot of applications will have relatively few variants of these permission sets, you might have administrators, editors, and viewers for example. in cases like these, we can just build three separate bundles at build time that would move these run time decisions to build time decisions by injecting certain permission sets and using babel to replace the <strong>RequiredPermissions </strong>component with in this case, either children or notAllowedElement by doing something like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fea53900625c72597d364825df2a5ce0/href">https://medium.com/media/fea53900625c72597d364825df2a5ce0/href</a></iframe><p>Then in our .babelrc</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c25bc8636309026ebf9aeca047e0f80a/href">https://medium.com/media/c25bc8636309026ebf9aeca047e0f80a/href</a></iframe><p>this will allow us to set the permissions for a particular permissions set on process.env.PERMISSIONS and than simply choose the branch and put that directly into the final compiled file instead of the <strong>RequiredPermissions</strong> component which will need to make the decision on whether or not the user can see something every time at run time.</p><p>this does force us to put some tooling around our build system and i haven’t come up with a great idea for that just yet but something like this <em>should</em> work:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8964cfd8d40d51ff3808c649ce550f8e/href">https://medium.com/media/8964cfd8d40d51ff3808c649ce550f8e/href</a></iframe><p>the next step in the process would be removing the import everywhere where we were actually able to pre choose a branch but i haven’t quite gotten to that point yet. let me know if you have any ideas or other feedback, thanks for reading and i hope it was least semi interesting or informative.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6f675ec87db1" width="1" height="1" alt=""><hr><p><a href="https://codeburst.io/using-babel-and-webpack-for-ahead-of-time-decision-making-for-branched-components-6f675ec87db1">using babel(and webpack) to make ahead of time render decisions for branched components at build…</a> was originally published in <a href="https://codeburst.io">codeburst</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How Babel helped to save 710kb from a production bundle and how it’s so much more than esnext…]]></title>
            <link>https://codeburst.io/how-babel-helped-to-save-710kb-from-a-production-bundle-and-how-its-so-much-more-than-esnext-e3ff82a5b447?source=rss-a7c5f6af5983------2</link>
            <guid isPermaLink="false">https://medium.com/p/e3ff82a5b447</guid>
            <category><![CDATA[babel]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[webpack]]></category>
            <category><![CDATA[ast]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[conor hastings]]></dc:creator>
            <pubDate>Sun, 25 Jun 2017 03:50:50 GMT</pubDate>
            <atom:updated>2017-06-25T12:26:13.156Z</atom:updated>
            <content:encoded><![CDATA[<h3>How Babel helped to save 710kb from a production bundle and how it’s so much more than esnext compiler</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/833/1*wmLa8rx1MKZy1bQVfwIAEw.gif" /><figcaption>medium recommends using an image to grab your attention, i think this one does. i don’t know if it’s high resolution like they said it should be but i like it.</figcaption></figure><p>I’ll start this off by saying the client side bundles at my company are way too big, like really big, like upsettingly big.</p><p>I make myself feel better knowing they used to be way bigger, our apps are mostly used in modern browsers on ~modernish computers, and whatever other excuse I can come up with to not feel like I’m failing every moment of the day.</p><p>A lot of the performance talk on the internet (at least the stuff I run into) focuses on big sweeping changes, where we take a 7mb monolithic app and code split it into and walk outside and a stranger hands us a hundred dollars on the street, but my world doesn’t work this day. I like to focus on making the smallest changes that can make the biggest immediate improvements, sometimes you make the sweeping changes but usually time just doesn’t permit it.</p><p>We use a lot of svg icons in our React applications, and a lot of them are shared between applications, so we’ve wrapped some up in a shared library that is used by ~5 applications. You might imagine that `application a` is using 40 of these, `application b` is using 15 of these, and so on and so forth, you get the point, or maybe you don’t, usually it takes me a long time to get to no point at all.</p><p>Anyway, back to the svgs, since we’re not distributing esmodules right now, i noticed that although our apps were importing the icons like this:</p><pre>import { Chair } from &quot;@socialtables/icon-svg&quot;;</pre><p>We would end up bundling all 226 (and growing) icons in the library. My first idea was just to push people towards doing direct imports as follows:</p><pre>import Chair from &quot;@socialtables/icon-svg/dist/chair&quot;;</pre><p>but in that case all it takes is one person messing it up to end up bloating the bundle.</p><p>Webpack 2 is getting better here with warnings for bundle size but we still need to address the root issue, where I want to use syntax one but end up with the output of syntax two going into to my bundle.</p><p>To achieve this I wrote a babel plugin to find imports using syntax 1 and convert to syntax 2 style imports.</p><pre>const componentToFileMapping = require(&quot;./component-mapping&quot;);</pre><pre>module.exports = function replace() {<br>  const visitor = {<br>    Program(path) {<br>      const file = path.hub.file;<br>      const imports = file.metadata.modules.imports;<br>      imports.forEach(imp =&gt; {<br>        if (imp.source === &quot;<a href="http://twitter.com/socialtables/icon-svg">@socialtables/icon-svg</a>&quot;) {<br>          imp.specifiers.forEach(spec =&gt; {<br>              const imported = spec.imported;<br>              const local = spec.local;<br>              const binding = file.scope.getBinding(local);<br>              binding.referencePaths.forEach(refPath =&gt; {<br>                const type = refPath.node.type;<br>                if (imported &amp;&amp; imported !== &quot;default&quot;) {<br>                  const fileName = componentToFileMapping[imported];<br>                  const name = refPath.hub.file.addImport(<br>                      `<a href="http://twitter.com/socialtables/icon-svg">@socialtables/icon-svg</a>/dist/icon-components/${fileName}`,<br>                      &quot;default&quot;,<br>                      imported<br>                  ).name;<br>                  refPath.replaceWith({ type, name });<br>                }<br>              });<br>          });<br>        }<br>      });<br>    },<br>    ImportDeclaration(path) {<br>      if (path.node.source.value === &quot;<a href="http://twitter.com/socialtables/icon-svg">@socialtables/icon-svg</a>&quot;) {<br>        path.remove();<br>      }<br>    }<br>  }<br>  return { visitor };<br>}</pre><p>I’m sure I’ve made mistakes here and would love feedback if you see some but at the heart of it we simply search the program ast for non default imports of icon-svg components and replace them with default imports to the specific component file (a lot of inspiration for this came from <a href="https://github.com/lodash/babel-plugin-lodash/">babel-plugin-lodash</a>). This helps us save on bundle size without having to change developer workflow, and not allowing one “mistake” to shoot us in the foot. (Quick note, I super duper wish I knew about <a href="http://astexplorer.net">astexplorer.net</a> when I made this so uhh, definitely use that if you’re going to do something similar.</p><p>In one of our applications this improved the bundle size by 710kb. The bundle is still oversized and needs a lot of work, but the ultimate point I think I’m trying to make is people think of babel as an esnext =&gt; current javascript compiler when it can really be so much more.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/698/1*aGo0dssucTsm_y1ksfu3_w.png" /><figcaption>without babel plugin</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/888/1*2jIR0kF3YmhPZHXc5WUPSQ.png" /><figcaption>with babel plugin</figcaption></figure><p>I’ve recently been experimenting with using babel to turn runtime decision making in branched React components into build time decisions generating different bundles, and hope to write about this soon.</p><p>If you read this far, thank you, because I don’t think I would have 🌟🆒✌🏻</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e3ff82a5b447" width="1" height="1" alt=""><hr><p><a href="https://codeburst.io/how-babel-helped-to-save-710kb-from-a-production-bundle-and-how-its-so-much-more-than-esnext-e3ff82a5b447">How Babel helped to save 710kb from a production bundle and how it’s so much more than esnext…</a> was originally published in <a href="https://codeburst.io">codeburst</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[2 Poems I wrote in the Second Grade.]]></title>
            <link>https://medium.com/@stillconor/2-poems-i-wrote-in-the-second-grade-529f2b6a61b2?source=rss-a7c5f6af5983------2</link>
            <guid isPermaLink="false">https://medium.com/p/529f2b6a61b2</guid>
            <category><![CDATA[second-grade]]></category>
            <category><![CDATA[horses]]></category>
            <category><![CDATA[poetry]]></category>
            <dc:creator><![CDATA[conor hastings]]></dc:creator>
            <pubDate>Sun, 25 Oct 2015 16:12:25 GMT</pubDate>
            <atom:updated>2015-10-25T16:32:12.158Z</atom:updated>
            <content:encoded><![CDATA[<p>Another excerpt from my second grade journal, this time some beautiful poetry, presented <em>unedited</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KC6S7IwPa8rCU8ZijTubJA.jpeg" /><figcaption>Where animals Live</figcaption></figure><h4>Where Animals Live</h4><p>Squerels live in trees,</p><p>birds live in nests,</p><p>bears live in caves,</p><p>some run wild in the woods,</p><p>some live in the zoo,</p><p>and thats where some animals live.</p><h4>Wild Horse</h4><p>The wild wind rumbles thrue</p><p>the night like a wild horse in my sight</p><p>the wild horse runs runs until i cetch him</p><p>out of this world into the wonderful world next door</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*55h4owdvQsC5L3BNJOepkA.jpeg" /><figcaption>Wild Horse</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=529f2b6a61b2" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Basketball Game]]></title>
            <link>https://medium.com/@stillconor/the-basketball-game-79bc5581b81f?source=rss-a7c5f6af5983------2</link>
            <guid isPermaLink="false">https://medium.com/p/79bc5581b81f</guid>
            <category><![CDATA[second-grade]]></category>
            <category><![CDATA[sports]]></category>
            <category><![CDATA[basketball]]></category>
            <dc:creator><![CDATA[conor hastings]]></dc:creator>
            <pubDate>Wed, 21 Oct 2015 00:14:51 GMT</pubDate>
            <atom:updated>2015-10-21T00:34:42.650Z</atom:updated>
            <content:encoded><![CDATA[<p>Republished from me Conor Hastings a second grader, written some time during the 1995–1996 school year. I think this story provides a message that we can all understand. Ghosts aren’t real. Without further ado…</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*M6AAthTrwzHW-Eb4I-Inrw.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/1*F9BLLNJ1diWxgURMv6bg6w.jpeg" /><figcaption>the basketball game, the story in all its glory.</figcaption></figure><p>There were two kids, their names were Anthony and Steven. They both love basketball but it’s just that they weren’t too good at it. They practiced every day but they still weren’t too good. But they didn’t give up<br>The next day they had a game. All the kids made fun of them because they each had only 2 points and 1 rebound.</p><p>After the game Anthony and Steven walked home together. Steven was going to a wedding. He wouldn’t be back until one o’clock. Anthony was sad he had no one to play with. When Steven got back from the wedding Anthony was so happy. He asked Steven if he wanted to play basketball. He said okay. At first they were doing the same old thing, just missing every shot. Then suddenly out of nowhere came the ghost of basketball.<br>“Hello kids! I won’t scare you. I’m going to teach you how to play basketball! Okay now come on let’s play! Okay first I’m going to teach you how to shoot. First put one hand in the middle and one hand on the side then bend and shoot. Good! I’ve got to go to some other houses. Keep trying and I’ll be at your game Sunday.”</p><p>On sunday everyone made fun of them again because the next game they still didn’t do so well. Only Steven had 3 points but the three points still had them down by two. Anthony hit a three pointer at the buzzer to win the game. Everyone cheered for him. He had won the game. Everyone picked him up over their shoulders .</p><p>Now they had confidence and they had friends and that’s all that matters.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=79bc5581b81f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Social Tables Ultimate Developer Institute]]></title>
            <link>https://medium.com/social-tables-tech/social-tables-ultimate-developer-institute-beb3b6bc63db?source=rss-a7c5f6af5983------2</link>
            <guid isPermaLink="false">https://medium.com/p/beb3b6bc63db</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[tech]]></category>
            <category><![CDATA[development]]></category>
            <dc:creator><![CDATA[conor hastings]]></dc:creator>
            <pubDate>Fri, 03 Apr 2015 13:49:37 GMT</pubDate>
            <atom:updated>2020-02-11T22:17:40.853Z</atom:updated>
            <content:encoded><![CDATA[<h2>lol</h2><p>nah</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=beb3b6bc63db" width="1" height="1" alt=""><hr><p><a href="https://medium.com/social-tables-tech/social-tables-ultimate-developer-institute-beb3b6bc63db">Social Tables Ultimate Developer Institute</a> was originally published in <a href="https://medium.com/social-tables-tech">Social Tables Tech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>