You might not need CRA

CRA is fantastic to get up and running in a jiffy, if you don’t care about the bloat. But what if you do?

Lee Machin
LGTM
4 min readMay 26, 2018

--

Really zero-configuration bundling.

I’ve used Create React App a few times, and I’ve really enjoyed getting down to the code without having to jump through all of the hoops with Webpack and Babel to get my build running in an optimal way. Despite how valuable these tools are to the modern JS developer, doing this back in the days of Babel 5 and Webpack 1 was quite tedious.

I’ve recently been putting together a library (another imaginatively named implementation of a data table) that I’ve decided should be open source even though it’s super opinionated about what it does. I also decided it should be written in Typescript, which felt like it would complicated the build somewhat.

The thing is, there’s not much use publishing a React component if you’ve not got a realistic demo of how it works, and Github Pages is a quick and easy to get something like that in place in lieu of having your own website.

My first approach was to make a new orphan branch (git checkout --orphan demo) and run create-react-app inside it so that I could pull in my component through NPM and build it that way. This was incredibly painful as it required that I publish my code in order to update the demo, and because it was in a different branch I couldn’t work on the demo and library at the same time.

I didn’t want to push a fully-ejected CRA setup to my master branch either, because it would be much harder for someone browsing the repo to find the actual library code along side all of the Webpack config, server side rendering config, demo code, environment config and so on, while also inflating the burden of dependencies in the codebase. There was nothing lightweight about any of it, especially as I wanted to add Typescript into the mix too.

Of course, the clue is in the name and CRA is for creating React applications, not libraries. Most of this stuff is shaken out for a production build which is what matters more than anything when deploying your masterpiece, and the overhead of downloading tens or hundreds of megabytes of code for your dev environment isn’t so significant given the quality of life improvements offered by the system.

Enter Parcel

I heard about Parcel a short while ago and was eager to try it out. People joke and complain about the high level of churn in the JS ecosystem but what you’re really looking for the most part is a passion for innovation. Parcel claims to bundle up your code without any configuration at all, which in some ways feels like the Rails approach to building software. It knows about Typescript, JS, ES6, and other assets you might use like images and CSS. It has a dev server with hot code reloading built in so that’s covered too.

After feeling uneasy about commiting my ejected CRA setup I decided to give it a proper shot, so I shoved my demo code into a new folder and added a minimal index.html for the entry point. It pulled in the Typescript file from my src folder so I could work on both the library and the demo at the same time, and visually check out the changes. The only configuration I had to change was my tsconfig.json, which had to ignore my demo folder now.

It was practically flawless and made the previous attempts to get this done look stupid. I could push to github pages without issue and I could make changes to my component on the fly, and I didn’t need the few hundred lines of configuration and the dozens of extra dependencies in my repo to make that happen. Of course, Parcel hides the dependencies just the same as an unejected CRA app does, but the flexibility of structuring my repo in a way that made sense to me easily won out.

Missing pieces

While Parcel is zero configuration, it doesn’t solve every problem. When it comes to server-side rendering, service workers, or stronger build optimisation you’re going to have to integrate that yourself, because there is no baked in support for those things so far.

Your bundle size will be larger than with Webpack, for example, because there is no support for dead code elimination (or tree shaking as it’s otherwise known). In this case, you’ll probably want to add Rollup to your pipeline to do that for you.

For server side rendering you have next.js, and for the progressive web app stuff you can probably adapt the ejected service worker code from CRA.

Is it right for you?

Nobody else can answer that, but I don’t advocate for switching everything over to the new hotness just because it’s new and hot. There are plenty of valid reasons to depend on CRA (or its ejected form): it has an opinion on structure and layout of your codebase and you can easily build conventions around that and it’s very easy to go from zero to hello-world in just a couple of commands. If you’re happy with this then there’s little reason to throw it out; similarly so if you value the power and control that webpack offers.

If you’re looking to do something like I needed—building a library and deploying demo code independently of each other in the same branch with minimal scripting—then it might be worth giving this approach a shot.

--

--