Maintaining a fork of create-react-app as an alternative to ejecting

Step-by-step example and a working repo

Denis Zhbankov
Jul 8, 2017 · 4 min read

I started using create-react-app instead of configuring build tools (webpack, babel, etc.) by myself a while ago and it saved me a lot of time and frustration. Thanks, Facebook! But..

A problem

Sometimes you really need an X feature which is not supported. Sometimes it could be turned on with a ridiculously small modification, like setting just one configuration flag from false to true. People open an issue or create a pull request, but get officially rejected:

“I don’t think we want to support this. I would actually like to turn this feature off. … I would accept a PR that forbids extra features if possible.”. © Dan Abramov

No doubt, such a unified tool must conform with very strict standards. You either accept and steer your workflow, or search for other options.

Solution #1: eject

One possible solution is the official and documented one: to eject. It means you get current configs and may tweak them as you like, but you can never return to the regular work flow to have any updates.

Note: this is a one-way operation. Once you eject, you can’t go back! … At this point you’re on your own. © Docs.

Example medium article trying to address the issue:

How to Use CSS Modules with Create React App
Short answer: you can’t. You gotta ⏏ © Ned Schwartz

Solution #2: fork

There’s one still not documented option: creating a custom fork of create-react-app. You can basically fork it, alter any configuration and merge any upcoming changes from the upstream, even automatically! But it took me some time to wrap my head around, and I’m going to share that knowledge with you, providing a step-by-step example.

How everything works

Facebook’s create-react-app is a multi-package repository, powered by Lerna.

Lerna is a tool that optimizes the workflow around managing multi-package repositories with git and npm. © Docs.

So create-react-app is just a shell storing all its packages in a /packages folder. After you install it, it runs a postinstall command from the main package.json, which in turn runs Lerna’s bootstrap script, which does some magic: basically moves or symlinks nested packages into your main node_modules folder allowing to require or import them as usual.

The only package you need to bother about is located in /packages/react-scripts. It exposes all the configuration and scripts your own project (if it was generated by create-react-app), uses to start, build, etc. Have a look at scripts section of your project’s package.json.

Moreover, react-scripts is the only dependency left in your package.json after create-react-app have initialised. So, you’ve understood it right: we need to create our own, custom-react-scripts.

No time to read, just give me any solution!

Lucky you, Mr. Kitze have already used the discussed approach and created a very useful fork with kinda expected name: custom-react-scripts.

Features: decorators, babel-preset-stage-0, LESS, SASS, CSS modules. The features are optional and can be turned on/off individually. © Docs.

You can read more about it on Medium: one, two.

Even more flexibility, example repo

Unfortunately, I wasn’t satisfied enough with the latter module. I needed a feature which was implemented in newer version of original create-react-app, than the one was merged in custom-react-scripts. And at the same time I needed to use custom PostCSS configuration instead of LESS/SASS, so a pull request wouldn’t help me either. So I decided to create my own fork (a scoped package to not pollute NPM’s global namespace).

Just replace the original package with the tweaked one:

yarn remove react-scripts
yarn add --dev @uqee/react-scripts

and you’re good to go, no more changes! It enables: CSS modules, /src folder as an import source, decorators, class properties and some PostCSS plugins.

Your own configs, step-by-step

Finally, time to create your own build! You need a github account (ghname) and an NPM account (npmname).

Congratulations! You have created your own build config, which will receive updates from the official create-react-app repo! You can now attach it to any project by simply doing yarn add --dev @npmname/react-scripts.

P. S. For security reasons NPM forbids publishing the same name and version pair even if you have previously done a forced unpublish, so for testing purposes I recommend using Yarn’s ability to install packages from a local folder (until you’re satisfied with the new config and ready to publish). I mean, instead of yarn add --dev @npmname/react-scripts you can do yarn add --dev file:path/to/your/custom/react-scripts.

Happy hacking!

Denis Zhbankov

Written by

JS developer, entrepreneur, casual trader

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade