Modify Create React App's Babel Configuration Without Ejecting
I love using Create React App to spin up an application swiftly, but one annoyance I continuously run into is the lack of ability to modify the Babel configuration. Why would you want to do this? Perhaps you want to use some of the latest ES.next features before they’re approved and merged into Create React App. In this case, you may eject the app, but there are several reasons why you don’t want to do that.
For this article, we’re going to add both the nullish coalescing operator and optional chaining syntax babel plugins. These plugins are both excluded from Create React App at the time of writing.
Begin by firing up your terminal and installing Create React App with the following command:
npx create-react-app my-app
cd my-app
The first step may take a while to complete depending on your internet
connection. If you do not have npx
installed, run npm install --global npx
or yarn global add npx
and then try the previous step again. We need two
separate packages to override the configuration, customize-cra
and
react-app-rewired
. We’re not calling react-app-rewired
directly, but it’s a
required dependency of customize-cra
.
npm i -D customize-cra react-app-rewired
Open package.json
in your editor of choice and replace all references to
react-scripts
under the scripts
property with react-app-rewired
. Once
complete, your scripts
should look like this:
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test"
}
Create a new file called config-overrides.js
in the project root directory.
touch config-overrides.js
customize-cra
has various utility functions you can use to configure virtually
all aspects of the babel and Webpack config. In our case, addBabelPlugins
is
what we need to add both plugins.
Open config-overrides.js
and add the following:
const { override, addBabelPlugins } = require("customize-cra");
module.exports = override(
addBabelPlugins(
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-syntax-optional-chaining",
),
);
For both of the plugins to work correctly, we’ll need to install the packages.
npm i -D @babel/plugin-proposal-nullish-coalescing-operator @babel/plugin-syntax-optional-chaining
You can now test this all works by running npm start
in your terminal. Open
src/App.js
, remove all the boilerplate code and add an expression to verify
babel is transpiling the bundle correctly.
import React from "react";
export default function App() {
const obj = {};
const prop = obj.foo?.bar?.() ?? "foo bar";
return <div className="App">{prop}</div>;
}
In this example, you should have no errors in the Webpack output, and foo bar
is rendered on the screen.