A beginner’s step-by-step guide to Code Splitting with Webpack 2 and React Router

In this guide we’ll create an application with code splitting based on routes using Webpack, React Router, and React. You can either follow along step-by-step or you can see the completed example at https://github.com/brotzky/code-splitting.

There is a live demo at http://brotzky.co/code-splitting.

The goal is to setup Webpack and React Router to split up our React application based on the routes.

Step 1. Initializing and installing dependencies

We’ll get started by creating a new directory in our system and installing all the dependencies. For this example we’ll be using Webpack 2, React Router v3, React latest and Babel latest.

Create and initialize the project

Now that we have all the dependencies out of the way let’s create the folders and files we’ll want to use in the next steps. Our project will mainly consist of two folders, /src and /webpack. /src will contain our components, router configuration, and index files. /webpack will contain all the configuration for our Webpack dev server and Webpack itself. We’ll also need to create a .babelrc file in the root to let Babel know what presets we’d like to use.

Don’t worry too much about the folder structure – the point is to create something simple for this guide. If your personal project or production app at work are different that’s fine.

Create the folders and files to work with


Step 2. Getting the app to run locally

To get our first Hello World to show up in the browser we’ll need to create an index.html file that serves as a mounting point for our React application. Lastly, to get our React project to run we’ll bundle it together with Webpack.

First, create the contents of the src/index.html file.

Second, create the simplest React app possible at src/index.js

Great, we’ve now made an index.html file that our React application can mount into. Now we need to setup our local development server with webpack-dev-server. We’re going to pass our WebpackDevServer a (yet to be made) Webpack config object and a devServerConfig object. These two objects will let WebpackDevServer know how it should be running.

Get the webpack/webpack-dev-server.js server setup

/webpack/webpack.config.js is where we tell Webpack what to do. For example, we will configure details like where to start looking, where to output files, how to chunk them together and how to preprocess our JavaScript.

In this case, we’re going to have two entry files so we can split up our application and vendor code. The output files that get built will have hashes ([name].[hash].js) to help with cache busting. Since we’re using ES6 and JSX in our codebase we have to let Webpack know how to preprocess those files so they are understandable for all browsers. To preprocess our app files we have to use the babel-loader that we installed at the very beginning of this guide.

Finally, we’re using Webpack’s CommonsChunkPlugin and a HtmlWebpackPlugin. If you don’t know what these do that’s fine for this guide. CommonsChunkPlugin is what will split out our vendor code we specified above and HtmlWebpackPlugin allows us to dynamically load scripts into the index.html file we have. HtmlWebpackPlugin makes it simple to serve hashed file names since we can’t hardcode that.

Webpack config file found at webpack/webpack.config.js 👌

Lastly. Go to the .babelrc file and put in our Babel preset options.

Setting up babel with .babelrc

After that, go to package.json and create a script we can use as a shortcut for starting our app. This will save us from having to type node webpack/webpack-dev-server every single time.

Your package.json should look something like this:

Let’s recap what we’ve done

  • Created a new project
  • Installed all our dependencies
  • Created a basic index.html
  • Created the simplest React app in index.js
  • Created and configured our WebpackDevServer
  • Created a webpack.config.js file
  • Setup .babelrc to use React and latest
  • Created a start script to run our app

Great, everything is setup properly and now we can run our app!

Go to http://localhost:3000/ in your browser after running yarn start
React hello world running

Inspect element shows that HTMLWebpackPlugin is working.

Webpack HTML Loader working


Step 3. Code Splitting with React Router 😎

Now that the app is running locally we can start building more components to showcase how code splitting works. To do that, we’ll have to create a few more files.

Creating the final component files

The last of the files have been created. Jump into src/components/Core.js and build out the component to have the navigation and ability to render child components passed through it.

src/components/Core.js handles the children and navigation

Now we have to create the individual components. These will be as simple as possible.

src/components/Home.js

src/components/About.js

src/components/Users.js

We now have all our React components created but how will we render them? This is where React Router comes into play. We want to render specific components at specific routes. Furthermore, we only want to load JavaScript that is needed for each route instead of a single monolithic file.

Luckily, React Router makes this possible.

Where the magic happens with React Router /src/routes.js

Only a few more steps to go! The routes are now created and they’re loading our components but we still need to use the routes somehow. To do that, we’re going to edit src/root.js to create our final component. This is where we create our highest level component that will handle our routing thanks to React Router.

Completing /src/root.js to use our new routes.

Remember that app <h1>Hello world</h1> app we created in the beginning? We want to replace that with the new <Root /> component we created.

Update src/index.js to use the new <Root /> component

Another recap

  • Created new component files
  • Edit Core.js to handle children and navigation
  • Created 3 basic components: <Home />, <About />, <Users />.
  • Used React Router to render those components asynchronously
  • Built <Root />, where we load our new routes into Router
  • Replaced <h1>Hello world</h1> with <Root />

That’s it. Start our new app and check the network as you update the route.

react code splitting working example

react router code splitting


Step 4. Build the application to be able to deploy

We have to update webpack/webpack.config.js and package.json to complete the build process. I won’t go into too much detail, but feel free to check the final version here: https://github.com/brotzky/code-splitting.

webpack/webpack.config.js updated to build handle production

package.json updated to have a build script

Run the new build script

webpack 2 code splitting build results


Conclusion

Code splitting is a great feature to incorporate into your application and luckily we have great tools like Webpack and React Router that make it possible. In the future I want to create a tutorial on how to incorporate a service worker using sw-precache to really take advantage of the code splitting and all the cache capabilities it comes with. I am also looking into React Router V4 and how it plays with code splitting.

If you’re a beginner and found this difficult to follow you should know I was in the same place not too long ago. I spent a lot of hours trying to get Webpack and React Router to work properly to get code splitting to work. Having code splitting in your app should not be your focus if you’re just starting out. Learn how Webpack and React Router work individually and then try to get code splitting to work.

Lastly, if you have any suggestions or improvements please let me know. This is how I’ve learned to do it and there may be other ways that are easier or more effective. I wrote this step-by-step guide because when I was learning code splitting with Webpack and React Router I found a few abstract resources that were difficult to fully understand without the right context.

Thanks for reading, Dennis 👋

Github Repository
Live Demo
Say hello on Twitter

*The live demo fails if you refresh on a nested route. This is due to my apache settings that I’ve yet to update. Sorry!