Adding decorator support to Create React App projects using react-app-rewired

Read this post on my blog for syntax highlighting.

Any experienced frontend developer should be familiar with the number one complaint about frontend development in recent years: it’s too difficult to get started. You’ve heard of this thing called React and so you install it and give it a try; only to find that it doesn’t “just work” and requires Babel, Webpack, npm and Node just to get started.

To help people conquer that cliff, Facebook developer and Redux author Dan Abramov created Create React App, which handles most of the difficult configuration work without you ever having to even see it and lets you get right down to work. It’s an elegant solution that works well even for larger applications that get deployed to production environments: at my workplace we’ve been developing two applications with it for over two years now.

Of course, there’s a flipside to the magic of “it just works”, which is that if something doesn’t work, it “just doesn’t work”. By handling the bundling configuration under the hood it’s impossible to make even small adjustments, such as adding new Babel plugins.

It’s at that point where I found myself recently, working on one of those production applications and wanting to use the proposed decorator syntax. While CRA does let you “eject” the config files so you can edit them, this also means you basically stop using CRA; it’s a one-way operation that adds a ton of complicated files to your project, which now you have to maintain forever. Even as an experienced frontend developer, I’d rather not.

Fortunately, there is a way to make small changes to the bundling setup without having to give up the convenience of zero-config. To do so, we need to swap out the core scripting component of CRA with react-app-rewired, which is an alternative that allows config overrides. Together with the convenience functions provided by customize-cra you can add almost any feature you like with just a few lines.

Here’s a step by step guide to add decorators (although you can use any of the other plugins described in the customize-cra readme file after this):

The following steps will work with any existing app as long as you’re using CRA 2.0 or up — check that your version of react-scripts is above 2.0.0 in your package.json file to verify this.

Since we’re adding decorators, we’ll also add the @babel/plugin-proposal-decorators package.

The eject script stays the way it is, since react-app-rewired becomes unnecessary the moment you run it.

This is where we’ll define our modifications. For now, add the following:

And that’s it; we’re done. Not a second spent digging through Babel or Webpack documentation.

Now let’s run yarn start to boot up the dev server and give it a try. If you want a quick example to copypaste to see if it's working, try this:

If all went well, this component should evaluate to <div>Hello world!</div>.

There’s one obvious caveat to this whole setup: the currently supported version of decorators is legacy and will eventually go away. The proposed new version will change how they work on a fundamental level and the syntax will be subtly different. For example, future decorators will need to come after the export keyword, whereas legacy decorators can appear before it.

However, the intent is for future decorators to be fundamentally compatible with the widely used legacy ones, and one of the spec design goals is to allow upgrading to the new syntax automatically via a codemod.

Keep yourself apprised by following the decorator proposal Github repo.

Update 2019–04–23: just yesterday, the Create React App team released their long awaited new major version 3.0.0. I’ve only done a quick test so far, but it seems everything still works as before. You can set the react-scripts peer dependency to 3.0.0 and still use the latest react-app-rewired and customize-cra packages like normal. I was able to add decorators and also Less support and both of them worked without a hitch. If problems do crop up later, I will update this post.

I’m a remote developer from Rotterdam, The Netherlands. I’ve been programming professionally since 2005 and am currently working for Syft as frontend developer, and I don’t talk about myself in the third person.
Follow me on Twitter at
@michielsikma.

Programmer and graphic designer based in the Netherlands. 日本語もちょっと話せます。以前1年ほど東京に住んでいました。

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store