Customize Create React App (CRA) without ejecting using react-app-rewired

Dave Ceddia
InstructorDave Ceddia
Share this video with your friends

Social Share Links

Send Tweet

Create React App is great, but it's hard to customize. If you want to add support for SASS/SCSS, react-intl, or any custom Webpack plugins, there's no official way to do that without ejecting.

This lesson shows you how to use the react-app-rewired library to customize CRA and its Webpack config without ejecting. Learn how to set up your rewire config and add the sass-loader so that your create-react-app project will support SCSS.

Instructor: [00:00] We're starting here with a fresh app created with Create React App. The dev server is already running. The app is running over here. I'm just going to switch over to a new terminal. We're going to run yarn add react-app-rewired.

[00:18] Next, we need to create a file called config-overrides.js. That needs to be in the root of the project. Make sure not to put it under the source directory. Let's call it config-overrides.js. This file is going to use module.exports to export a single function. We'll call it override.

[00:38] It'll take two arguments, the current webpack config and the environment. Then, it needs to return the new webpack config. For now, we'll just return the config as is.

[00:49] Let's also add a console.log here. We'll say override so that we know this is working. After we save that, we can go over to package.json. We need change it to use react-app-rewired instead of this react-scripts package here.

[01:06] We're not going to replace react-scripts entirely. That still create react-app-core, and we'll leave that in place. We'll select all these, change these to react-app-rewired, and save. Then we can go back over to our running server here, stop it and restart it. If you watch closely, you'll see override gets printed right as it starts. We know that our config-overrides script is getting called.

[01:34] Now that the override is set up, we can try adding Sass support for SCSS files. We'll open up our app.js file. Notice how we have a div with class name app, and another one called app-intro inside it. This will give us something to target with Sass nesting.

[01:54] Where in CSS, you might write .app.app-intro and then style it here, we can instead nest the app-intro class inside of app, just as it appears in our component tree, and put our styles here. In this case, we'll change the text color to red, save. Over in app.js, we need to import our new app.scss file.

[02:22] We save. We notice the app has not changed. We don't have any red text here yet, because SCSS is not an extension that Create React App understands. Let's go about adding that to our overridden webpack config with config-overrides.

[02:37] To make the Sass loader work, we're going to need to install a couple more packages. With yarn, add sass-loader and node-sass. Then, we need to know how to customize the webpack config in order to add the sass-loader. To do that, we need to know the structure of the existing config. We can find that in the react-scripts package, which is the core of Create React App.

[03:03] If we go into node_modules, scroll all the way down to react-scripts. Then in the config directory, we'll find the div and production webpack configs. We'll start by looking at the development config.

[03:19] If you're not familiar with webpack, this file might be a little intimidating, but it's one of the best-commented webpack configs that I've seen. If we scroll down, we can see that the config exports a single object. Then if we scroll a little further down, we can find this module key. Underneath module is rules.

[03:37] In rules, there's an array containing the objects that each deal with a specific file type. This first one, for instance, runs on JS, JSX, and MJS files, and it runs the eslint-loader.

[03:51] After this first rule, there's another object containing this one-off key, which is an array of more loaders to run after eslint. Here's one that deals with images. Here's the one that passes JS through Babel, which gives us good stuff like JSX and ES6. Here's CSS.

[04:10] This last one is file-loader, and since the loaders in this array are run in order, this is the last to run and it's the fallback. It handles everything that isn't already handled.

[04:23] Down here is an important comment that says, "If you're adding a new loader, you have to add it before the file-loader. What we want to do here is insert our sass-loader right in this position here, right above file but after everything else.

[04:38] If we go back up to the top, we need to modify config.module.rules, second element .one-off, and then we need to insert something second to last.

[04:55] Let's go over to config-overrides. We can see how to do that. First, let's access the list of loaders, which we figured out was config.module.rules, second element, .one-off, and then into that list of loaders, we need to splice that loaders.length-1, which will insert this second to last. We don't want to replace any elements, so we'll pass 0as the second arg here.

[05:21] Then, our new loader is an object that will use test to look for files ending in .scss. Once we find those files, we will use the list of loaders, which will be style-loader, css-loader, and sass-loader. Webpack uses these in reverse order, it'll actually run sass, then css, then style-loader.

[05:42] Let's save this and try it out. We go back to the terminal where we have the running app, stop it and restart it. Now the text is red, which means that our app.scss file is being correctly passed through our new loader inside config-overrides.