Porting enterprise React app to create-react-app

How frontend works

So I’ve been writing React apps for a year now. I’ve had the honor of being one of the maintainers of react-boilerplate. If you’re a React developer, you know how it is- You get the mock-ups, you get the API endpoints and then you write the components. Easy-peasy. But over the period of time it becomes mundane. I never had a chance to work at the architectural level of live applications.

A couple of weeks ago, I was given a great opportunity to port one of our React applications to create-react-app. The short term goal was to see how difficult it is to move the legacy code to CRA; the long term goal being bringing all of our applications under CRA’s fold.

The reason for choosing CRA over any other boilerplate is that CRA is truly unopinionated which makes it ideal for porting legacy React applications. (It’s funny how 2-year old React apps have quickly become “legacy” apps!) Moving the source code wasn’t going to be difficult. All I had to do was copy and paste the src folder. But little did I know that I was far from porting the application. Once I started moving code, I realized that the only way to get to the other side was by having painstaking attention to detail. I had a lot of things to take care of. Some of them being-

  1. Migrating tests from karma/chai to Jest.
  2. Supporting less styles and svg files.
  3. Using file-loaderfor requiring images. (Earlier we had a gulp task to copy assets straight to the build directory ahead of time.)
  4. Replacing all instances of require.ensureto new es6 import()syntax.
  5. Some find/replace problems like dropping React.PropTypesin favor of new prop-typespackage.
  6. Removing all relative imports like
    import * as actions from '../../../actions/MyActions' 
    with module-like imports 
    import * as actions from 'actions/MyActions'
  7. And finally write a new build process on our build server since CRA recommends using Yarn.

That meant, a decision was to be made!

We were debating over ejecting the create-react-app setup Vs. using custom react-scripts. Initially, I was in favor of ejecting because it gives you total control. But then I realized that ejecting would make it nearly impossible to keep up with the daily updates of CRA, which meant that custom react scripts was the best way to go. I want to thank Shubheksha and Kitze for their awesome articles. Really helped understand the pros and cons of ejecting!

We forked CRA, modified the webpack and jest config to our taste and hosted xoxo-react-scriptsin our private npm registry. I cannot stress enough how cool it is to have custom scripts. Now we just have to pull changes from upstream, resolve conflicts (if any at all) and republish the scripts! We were moving in the right direction. Things were looking good.

I’m not going to go in the implementation details of migration, but the purpose of my post is to let others know that it is absolutely possible to port your app to CRA no matter how weird your legacy app setup is.

With the power of CRA + custom react scripts, we now TRULY have a zero configuration tool in our tool-belt. From now on, to migrate/create the next app, all we need to do is create-react-app my-app --scripts-version xoxo-react-scriptsand we’re off and running!

Things to keep in mind

To my disappointment, CRA does not come with react-hot-loader. However, it comes with raw HMR. But not to worry! You can use react-hot-loader with minor changes in your app-entry.

Install react-hot-loader@next as a dev-dependency. And something like this in your app-entry should do the trick!

To make your custom react-scripts work, you have to have a package published either in npm registry or private registry. Before publishing your package, make sure you change the references of original “react-scripts” in your package.json.

For these npm scripts to work, you need to change the binproperty ofxoxo-react-scripts package.json

Publish xoxo-react-scripts. Run npm i xoxo-react-scripts -Din your project. And then run npm start!

During development, you’ll often need to modify custom react scripts. There’s a cool way to test packages without having to publish and install. You can use npm link for that. Follow this guide to know more

Overall Experience

We chose create react app because it has a robust support in the community and its decoupled nature lets you create a great tool for scaffolding out boilerplates for new projects. Another major advantage of having CRA is that you no longer need to worry about updating webpack and babel plugins and presets and what not. It lets you focus on what’s important. Thank your Dan Abramov and entire CRA team for this tool. We’re finally going to have a unified DX (Developer eXperience) in all of our apps.