Setting up webpack for react project doesnt have to be scary

May 8, 2019

10 mins read


If you would have asked me few days weeks ago, to setup a complete build and boiler system for new react project, i would have handed you a C.R.A. So if your response is the same, this blog post is for you.

All the headings point to git commits, so you can browse the project at that title/step state in Github.

Prepare new project

Add package json

Start with an empty folder and run yarn init. This will ask you bunch of questions and make file such as package.json for you. You can fill in your project name and other details.

Install react libraries

Install React and its dom library

yarn add react react-dom

Install webpack

Install core webpack package as *devDependencies and along with that lets also add another two webpack packages; webpack cli, which will be required if we are to run webpack with command line or via npm scripts and webpack-dev-server, this packages gets us up and running our local dev environment without too much hassle of making our own server.

yarn add --dev webpack webpack-cli webpack-dev-server

* devDependencies : are those packages which you would not like to include in the app, but only while building or developing them.

Install prettier

Prettier provides beautifully code formatting. As this has nothing to do with the production code, we are only going to use it while developing code, So install this as devDependency too.

yarn add prettier --dev --exact

There are lots of configurations available to suite your preferences. Head over to docs to configure. Make a new file with name prettier.config.js in your root and Add this just two configuration to it. Feel free to add your own later.

module.exports = {
  trailingComma: 'all',
  semi: false,
}

Write some react code

Create a folder named src in your root and add files index.js to it. Index.js will be starting point of src. Currently the file is simple, it can be extended later. Follow here to lean how to write react code.

import React from 'react'
import { render } from 'react-dom'

const App = () => (
  <div>
    <h1>React scaffolding kit</h1>
    <strong>An opiniated but customizable react starter kit</strong>
  </div>
)

render(<App />, document.getElementById('REACT_ROOT'))

Run the app

Lets make use of webpack-dev-server we installed earlier to run the app. Its a good idea to have a start script in package.json for easy start up. Add the start script in package.json.

"scripts": {
    "start":"node_modules/.bin/webpack-dev-server",
  },

Now app can start with a simple command in terminal

yarn start

You might see webpack related content appearing in your terminal and finally ending with an error. If error is something on the lines of You may need an appropriate loader to handle this file type or related. Then don’t worry you have followed instructions correctly. Lets tackle that error in next section. Go drink a glass of water. On side note, You might have noticed that webpack was able to identify the code you wrote in src/index.js without you having to provide it with any configuration. Thats because webpack now provides lots of default to get you going soon. Hence placing index.js file under src was the default entry point for webpack.

Transpiling Javascript code

The error we stumbled, means our server wasn’t able to understand the code we wrote. It was not compatible with what usually browsers understand. To be able to make it understand we transpile our code to much better browser understanding code with Babeljs.

Install babeljs

yarn add --dev @babel/core

Babel core installs the core functionality of the babel library. In order to make webpack aware of babel and say hey! webpack i want babel to transpile my code before you can do your stuff, we will add another package

yarn add --dev babel-loader

Connecting babel and webpack

By adding the package, webpack still wont be aware of babel. To do that lets add in a configuration file for webpack, and name it webpack.dev.config.js. Why dev in the name ? thats because we would like to keep our production and dev webpack configuration seperate.

module.exports = {
  module: {
    rules: [{ test: /\.js$/, exclude: /node_modules/, use: 'babel-loader' }],
  },
}

With the above we are saying that we would first like to run babel-loader on all js file except the ones in node_modules

Configuring babel

Ok, now you’ve configured Babel but you haven’t made it actually do anything. Lets create babel.config.js in our root. Babel depends on many plugins to do its job. These plugin contains instruction on how to parse the code to more compatible one. Lets add few plugins that we require. To start, add env preset, which enables transforms for ES2015+ and react preset, which contains most common plugin used along with React. You are free to add and include others. Presets are just a bunch of plugins grouped together.

module.exports = function(api) {
  if (api) {
    //   https://babeljs.io/docs/en/config-files#apicache
    api.cache.using(() => process.env.NODE_ENV)
  }

  const presets = ['@babel/preset-env', '@babel/preset-react']

  const plugins = []

  return {
    presets,
    plugins,
  }
}

Start the app again

Lets run the start command we ran previously. Just a slight modification before we start, we need to tell webpack dev server to read config from the new webpack.dev.config.js file we created earlier.

"start": "node_modules/.bin/webpack-dev-server --config webpack.dev.config.js",

Now you must be seeing that our terminal didn’t threw any error when we starter the server. You may now go to the localhost which is mentioned there. Dont be disappointed if you see just bunch of folders over in your website, we havent configured the app to output HTML yet so its just showing us the content of the website instead.

Make app spit html

Webpack contains ecosystem of plugins and loaders. To enable webpack to output html, we are going to add in HTML webpack plugin.

yarn add --dev html-webpack-plugin

Create an html file, which will be served by our app in src folder and add just the simple HTML5 supporting content. Remember we asked react to find element id REACT_ROOT, include that too so that our react apps renders on that element tree.

<!DOCTYPE html>
<html>
  <head>
    <title>React scaffolding kit</title>
  </head>

  <body>
    <div id="REACT_ROOT"></div>
  </body>
</html>

Now we need to configure webpack and ask it to take our html as template and output that instead. All webpack configurations are done in webpack config file. Add a new key plugins for webpack object and import our newly added plugin. The plugin can now be added to plugins array. We will ask it to use the html we just created by providing template option.

const htmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  module: {
    rules: [{ test: /\.js$/, exclude: /node_modules/, use: 'babel-loader' }],
  },
  plugins: [
    new htmlWebpackPlugin({
      template: './src/index.html',
    }),
  ],
}

Once its done, you can restart the app from start script. Now the app should greet you with React scaffolding kit written big in H1 tags.

Add styling

The app looks rather bland, lets now add the ability to add styles. I am going to add SCSS support because i feel thats the best way to write CSS. Create a new file inside src directory and name it index.scss.

h1 {
  color: blue;
}

Include the styles in your index.js by importing them.

import './index.scss'

But as you have noticed, styling doesnt seems to be picked up by the app. Reason for that there is only so much webpack can do on its own. We will have to provide a way for webpack to include the styling in the app, here comes webpack loaders to rescue.

yarn add --dev style-loader css-loader sass-loader node-sass

Lets look at what those are by adding them in the configuration. Add a new object inside your modeuls/rules in webpack config.

{
    test: /\.scss$/,
    use: [
        "style-loader",
        "css-loader",
        "sass-loader",
    ],
},

Here we are telling webpack to take all our scss files, convert them from scss to css (via sass-loader), resolve css syntax such as import or url (via css-loader) and then take the compiled css and load it up inside <style> under our html’s head tag (via style-loader). We have also include node-sass as its required to internal working of sass-loader.

Recap

Congratulations you have now a minimal react app bootstrapped with webpack up and running. If you have come till here, you deserve an applause.

Lets see what have we done till now

  • Installed required libraries such as react , webpack etc.
  • Setup prettier for code formatting
  • Added webpack and a basic configuration
  • Configured Babel and connected it to webpack
  • Attached plugin to render HTML from webpack
  • Styled app with scss and styling loaders

More setup

Communities around react, webpack etc are huge, as such we have some very powerful support libraries, plugins to work with. Let see what more we could do with the above setup

The configuration and build one uses for production varies from application to application.

This blog post purpose was to get you familiar with setting up a tiny, less configuration webpack setup for you next react project.