React : Babel + Webpack + Sass boilerplate application 1


Introduction

In this tutorial we’ll see how to build from scratch a React application with Webpack, Babel and Sass.

The main requirement for this tutorial is to have a node installation with npm for your platform/OS.

The tutorial is structured in several parts:

  • Create an initial project directory
  • Webpack setup
  • Babel setup
  • React
  • Add support for Sass styles

Initial project

The first step is to create an initial empty project. For that purpose will create an empty directory for the project and run the following command:

This command will set up a new package.json file containing metadata for an empty project.

Relevant parts of the generated package.json should be updated to match those of the project, this is the contents of the file after the initial modifications:

Webpack 4 support

Webpack setup

Next step is to add support for Webpack.

The previous command will add Webpack development dependencies to our package.json. The first three are strictly Webpack related, if you’ve worked with Webpack in other projects probably you’ll already have them installed as global dependencies.  For our purposes, and to support different versions of Webpack, we’ll install them as local development dependencies.

The other two dependencies (html-webpack-plugin, html-loader) will be used to minimize html and to be able to reference the bundled Javascript for our application.

After running the command, a new section will be created in our package.json with the new "devDependencies".

Webpack configuration

The first step is to create some source content that Webpack will process. We create a new directory for our sources (src) and add a new index.html file in this directory with the following content:

For Webpack (4) to work we are going to need a new webpack configuration file. We must create an empty webpack.config.js in the project’s root directory and add the following content:

In the first section we add the script requirements and declare two constants (SRC_DIR, DIST_DIR) for the source and distribution directories.

Next we declare a new module using the index.html file we created in the earlier step as the entry point. The output files for the module will be generated in a directory named ./dist. When the project is built a minimized index.html file and a bundle.js will be generated in this directory.

In the rules section we are going to add our first loader. In this case we are going to use the html-loader to preprocess all of the html files located in the src directory.

Next we define the resolve extensions. This configuration for extensions allows us to import resources using only the filename, so when importing a component in our code (import Component from ./feature/Component') Webpack will look for the component source file in  ./feature/Component./feature/Component.js and ./feature/Component.jsx.

In the plugins section we are going to add Webpack’s HotModuleReplacementPlugin which exchanges, adds or removes modules while the application is running without the need for a full reload whenever a change is made to the source code (hot reloading).

We are also going to add HtmlWebpackPlugin which will add our bundled javascript in the index.html file we created earlier.

FInally we are defining a devServer to serve our module using hot reloading in port 9000.

package.json webpack scripts

The final step to setup Webpack 4 is to add some scripts to package.json file so that the application can be built and served:

The first script (npm run build) will build the application in our dist directory generating two files: index.html and bundle.js. These files could be deployed and served by a web server without further configurations.

The second script (npm start) will launch a development server with the compiled module and will listen for changes. When invoked, we could open our browser and point to http://localhost:9000 where the application should now be available. Any change to any of the source files should trigger a reload in the browser and changes should be displayed.

A particularity for these scripts is that they are triggering local webpack client installation (./node_modules/.bin/webpack) instead of the maybe globally available webpack client (webpack). This will allow us to run a specific version of webpack in our project, controlled at devDependencies section of package.json.

Babel support

Babel setup

Next step is to add support for Babel. Babel will be in charge of transpiling JSX and Javascript to ES5 compatible Javascript. React recommends writing code using JSX syntax as it provides an easy way to mix HTML code with regular Javascript.

The previous command will add all Babel development dependencies to our package.json. babel-core package will add basic support for Babel.  babel-loader will enable running Babel from webpack, babel-preset-env will add support to transpile Javascript > ES5 files. babel-preset-react will add support to transpile JSX files.

Babel configuration

Next we must configure Babel to use both presets we installed in the previous step. We must create a .babelrc file with the following content:

Now we have to configure webpack to use the Babel loader and preprocess jsx and js files before packaging them. To do so we’ll add the following rule to the module rules section in webpack.config.js:

From this point whenever any of the defined Webpack scripts is triggered, Babel will run and transpile js/jsx using the presets defined in .babelrc.

React

React setup

In order to be able to use React in the project we must add two additional packages:

The previous command will add React dependencies to our package.json.

Application entrypoint

Next we are going to create the entry point for our demo React application. For this purpose we’ll create an index.jsx file under the src directory with the following content:

This file will render <p>Hello world</p> inside the <div  id="root"... tag in the index.html file we created in the previous step.

As of now, we could already launch our application using npm start command and load our application pointing our browser to http://localhost:9000/

React Hello World in browser

Hot Module Replacement

Our application includes Webpack’s Hot Module Replacement plugin (HMR). This plugin exchanges, adds or removes modules from an application while it’s running without the need of triggering a full reload. This improves performance and development productivity because changes in the source code are reflected almost instantly without the need to completely redeploy the application.

Any change to a source file will trigger an automatic page reload in the browser and changes will be reflected instantly.

The only drawback to HMR is that it doesn’t preserve application state. In a future post we’ll see how we can use React Hot Loader to speed up even more application development by preserving application state.

React App Component

In order to keep code structured, we are going to add our first component to the application and nest it inside our main index.jsx. We’ll create an app.jsx file with the following content:

Next we’ll import the new component in index.jsx (import App from "./app";) and add the new component:

SCSS support

Although React offers several ways to style components and there are plenty of styling libraries available, I still find it useful to use plain old school CSS or Sass style sheets to style the application. The main reasons are that Sass allows me to share variables, media queries, partials, mixins… efficiently throughout the application and even between different code bases with different frameworks (I can share a same SCSS library between a site built with React, Angular, Hugo…).

SCSS Setup

In order to preprocess SCSS files we’ll need to add a couple of loaders to webpack and the Sass preprocessor  LibSass bindings for node (node-sass):

mini-css-extract-plugin will be in charge of extracting all of our generated css into a single file. css-loader will be in charge of our css modules (explained later on) and of resolving styles within our React components. sass-loader and node-sass will be responsible for SCSS preprocessing and compiling Sass into regular CSS.

Next we add a new rule to the module rules section of our webpack.config.js to invoke the loaders we just added:

Here we are referencing the 3 loaders we just installed. For css-loader we add a special configuration to support CSS modules (explained in the CSS modules section).

We also need to add a reference and configuration for MiniCssExtractPlugin in the plugins section (Please review full webpack.config.js file to check imports and constant declarations):

In these lines we define MiniCssExtractPlugin plugin configuration and how is our CSS file going to be generated.

Global SCSS

For our global styles we’ll create the following structure:

main.scss file contains imports for the partials files. As an example we’ve included three Sass partials files: _variables.scss to declare variables for colors, fonts, etc.; _mixins.scss which includes an example mixin to make a box resizeable; and _base.scss which includes the basic styles for the application.

In order to enable these global styles in the application we need to import the main.scss styles in our app.jsx, this is as simple as adding the following line to the imports section: import styles from './styles/main.scss';. Webpack will automatically resolve and add the imports during transpilation using the module rule and loader we added in the previous step.

CSS Modules: component styling

In the previous section we saw how to declare the global styles for our application, in this section we’ll see how to use CSS modules to enable per component SCSS styles to React.

In webpack.config.js we declared a rule for SCSS processing and the configuration for css-loader. To enable CSS modules we declared css-loader with several options: modules: true and localIdentName which configures the way class names will be extended. What we are doing here is basically enabling the css modular approach and appending a hash to classes defined in each file.

To show how this works we are going to create two components (Button and FancyButton), both of them having the same code and style class names, but that will render differently thanks to the modular approach.

For each component we are going to add a jsx file with the component definition:

Both buttons have the same code, only difference is the class name. In order to reference the class name from the component SCSS we will use {styles.button}, where styles is the reference to the SCSS file and button is the name of the class defined within this file.

We will also add a SCSS file with the styles for each button component:

Again, for both components, the structure and class names are the same for both buttons, only difference are the inner style definitions.

Finally we add both buttons to our App component:

When the page is rendered we can see that although both components share the same class name, each of them is rendered with the styles defined in its own SCSS file.

If we inspect the class names for each button, both will have the same class name (button) but with a different suffix added by the css-loader:

Conclusion

This post is a tutorial to create a basic React application with support for Sass styles, Babel and Webpack 4. The tutorial shows how to install all dependencies and how to setup Webpack and Babel to transpile React jsx files into regular Javascript. In the last section there are instructions to add support for Sass using global styles and per component styles using CSS modules. The post is meant as a guide to create boiler-plate configuration whenever starting a new React project.

The full source code for this post can be found at Github.

You can also check the source code for isotope mail client which is using these techniques for the front-end component build. And here an introductory post for the application and

react webpack babel sass mn


Leave a comment

Your email address will not be published. Required fields are marked *

One thought on “React : Babel + Webpack + Sass boilerplate application

  • Sunny

    Thanks for this valuable article and its really fixed my problem. I was looking for solution but finally your valuable article help me to configured it.
    once again many many thanks