Things I've Learnt

Adding React Fast Refresh to Your Create React App Project

January 12, 2020

React Fast Refresh is the successor to React Hot Loader, a configuration option that lets you enjoy a (much) better development experience, by doing the following:

It listens to changes within your source files and sends them, and only them, to the browser (or mobile device, for React Native). When those changes arrive at the browser, the code segment that has changed is being “injected” into its module, replacing the previous code. If that module is able to accept said changes without having to reload the page, then your app gets updated without losing its state.

In other words, when you hit Save, instead of refreshing the page, React Fast Refresh will only reload the components affected by the change.

Dan Abramov (and others) have recently re-wrote this feature, renaming it React Fast Refresh. It was initially out for React Native, while React developers were promised a similar experience. Finally, it seems like the days of waiting are over1 and, while it’s still in development, you can now try it out in your Create React App (without even ejecting).

Trying React Fast Refresh

Create React App, out of the box, does not yet support Fast Refresh (as it’s still under development and may still contain some bugs). That means we either have to eject and modify Create React App’s config files or use a little magical tool called react-app-rewired.

React-app-rewired lets you:

Override create-react-app webpack configs without ejecting

That’s it. It’s pretty cool since you can do some useful things with it, like including component names when using styled components, adding a webpack.DefinePlugin block to your config, and many more.

It’s important to take into account that react-app-rewired is “lightly” maintained (mostly by the community), or as Dan Abramov somewhat officially tweeted: “Stuff can break”.

So with that, let’s add it to our project!

Adding React App Rewired

In order to add react-app-rewired to our project, we start by installing it:

$ npm install react-app-rewired --save-dev

We then create a config-overrides.js file, next to our package.json:

/* config-overrides.js */

module.exports = function override(config, env) {
  // do stuff with the webpack config...
  return config
}

And finally, modify the scripts section of our package.json:

"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test --env=jsdom",
  "eject": "react-scripts eject"
}

That’s it for react-app-rewired. We are now ready to enable React Fast Refresh.

Enabling React Fast Refresh

To do that, we’ll install two packages:

  • customize-cra, which is a set of utility functions that help modify config objects. It exposes functions like addBabelPlugin and addWebpackPlugin which are necessary for our second package to work,
  • customize-cra-react-refresh, this is the one that makes the necessary changes to Create React App’s config files in order to get React Fast Refresh to work.

We’ll install both of them:

$ npm install -D customize-cra customize-cra-react-refresh

Leaving us with the last and final step of modifying the config-overrides.js file we created above:

/* config-overrides.js */

const { override } = require('customize-cra')
const { addReactRefresh } = require('customize-cra-react-refresh')

module.exports = override(addReactRefresh({ disableRefreshCheck: true }))

And we’re done! We can now restart our development server and enjoy a greatly improved feedback loop and overall developer experience within our Create React App.

Disclaimer: I haven’t thoroughly tested React Fast Refresh yet, I was very excited to find that it’s ready to test out and wanted to share it. I will probably update this post in the coming days, adding the caveats I’ll find along the way.

1 If you don’t mind a few hiccups here and there…