TutorialsCourses

Customize Create React App without Ejecting

Introduction

Create React app has become the defacto standard for building React applications. With a standard comes inflexibility. The ecosystem of the JavaScript world has expanded greatly and sometimes you want to build upon the standard.

Create React App gives you options to override but it generally requires modifying heavily complex webpack configurations. Thankfully 2 packages came along to make our life a little easier. First was react-app-rewired, it provides all the low level manipulations for the Create React App webpack config. Then customize-cra utilizes it to provide high level, easier to use functions.

Install Dependencies

Once you have your Create React App project all setup we'll need to install our 2 dependencies.

npm install customize-cra react-app-rewired --dev
//or
yarn add customize-cra react-app-rewired --dev

Once installed we need to reconfigure our package.json, the typical Create React App script section looks like this. It runs the react-scripts commands. However we need it to hook into react-app-rewired to actually redefine our configurations.

"scripts": {
   "start": "react-scripts start",
   "build": "react-scripts build",
   "test": "react-scripts test",
}

Thankfully all you need to do is swap react-scripts out for react-app-rewired.

"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
}

Creating a Customization

Now create a config.override.js in the root directory, and react-app-rewired calls it webpack configuration for Create React App.

With this config we can now run helper functions from customize-cra. There are a TON of helpers functions you can find here https://github.com/arackaf/customize-cra/blob/master/api.md.

The one we will use is called useBabelRc. This will allow us to tell Create React App and have Babel also utilize the .babelrc configuration you setup.

One such use case for me was adding the preset @emotion/babel-preset-css-prop. This allows us to tag any element with css={{}} and the babel preset will swap out the JSX pragma to use emotion.

So now create a .babelrc and it would look like this, (after installing yarn add @emotion/babel-preset-css-prop --dev).

{
  "presets": ["@emotion/babel-preset-css-prop"]
}

Then create a config.override.js and fill it with this. The override function takes all of the plugins you call it with and sequentially calls each one with the new configs. This builds out the final config that Create React App will use.

const { useBabelRc, override } = require("customize-cra");
module.exports = override(useBabelRc());

For us we only are using a singular plugin from customize-cra but if you wanted to use multiple just add them as arguments to the override function call.

const {
  useBabelRc,
  removeModuleScopePlugin,
  override,
} = require("customize-cra");
module.exports = override(useBabelRc(), removeModuleScopePlugin());

Ending

Now you can keep all the benefits that Create React App provides while customizing to your specific needs without having to eject. As Create React App changes and react-scripts evolves the customize-cra and react-app-rewired libraries could break your build and not work. So just be warned, although it has been stable for many years.