Setting up Webpack, Babel and React from scratch - Part 2

Part two

Update: Part two is pretty much done. Part three will cover redux and production builds.

Other parts:

  • Part 1 - Webpack, Babel, React, Router, ESLint
  • Part 2 - SASS, More ES6 goodness (Static props, decorators, deconstruction...)
  • Part 3 - Where to go from here

Adding SASS

We will use SASS loader for webpack, so let's install it together with node-sass compiler, css and style loaders

npm install --save-dev style-loader css-loader sass-loader node-sass

Create scss folder in the app folder, and main app.scss file in it. This file will include all of the other scss files.

Now we need to add a loader to webpack config file.

...
{
  test: /\.scss$/,
  loader: 'style!css!sass'
}
...

This will handle importing SCSS files in our JavaScript code. So we need to import app.scss manually in the JavaScript code. You'll need to add only one line to your app.js.

import '../scss/app.scss';

This includes your styles by calling loaders we defined in the webpack config.

Restart your webpack, and voala, now we have styles and hot reloading for them. Try changing your styles to check it.

Source maps

To enable source maps, we'll pass the sourceMap option to the sass and the css loaders. Enable devtool, and update the loader

...
  devtool: 'inline-source-map', // or 'source-map'

  module: {
    loaders: [
      ...
      {
        test: /\.scss$/,
        loader: 'style!css?sourceMap!sass?sourceMap',
      }
    ]
  }
...

If you want to read more, here's link to the official documentation

Autoprefixer

Always use autoprefixer - I can't stress this enough.

We'll need postcss loader, precss and autoprefixer

npm install --save-dev postcss-loader precss autoprefixer

At the top of our webpack config, require precss and autoprefixer

const precss = require('precss');
const autoprefixer = require('autoprefixer');

Update our sass loader config and and postcss config

...
  module: {
    loaders: [
      ...
      {
        test: /\.scss$/,
        loader: 'style!css?sourceMap!postcss!sass?sourceMap',
      }
    ]
  },

  postcss() {
    return [autoprefixer, precss];
  },
...

Restart webpack, and you should have autoprefixing in place. Try adding display: flex to one of the elements to check if autoprefixer added -ms-display: flex and -webkit-display: flex.

Again here's link to the official documentation

Method shorthand

Note that

{
  ...
  postcss() {
    return [autoprefixer, precss];
  }
}

is the same as

{
  ...
  postcss: function () {
    return [autoprefixer, precss];
  }
}

but only using method shorthand. ES6 rules!

More ES6 stuff

To be able to use deconstruction (...object), static class properties and decorators (@connect) we need to add a couple of Babel plugins.

Install them using following command

npm i --save-dev babel-plugin-syntax-decorators babel-plugin-transform-class-properties babel-plugin-transform-decorators-legacy babel-preset-stage-0

Few links to read more about this plugins:

Now we need to add it to our Babel configuration. Open your .babelrc file and add them.

Add these to the "plugins" array

"syntax-decorators"
"transform-decorators-legacy"
"transform-class-properties"

And "stage-0" to the "presets" array

Your .babelrc should be looking something like this

{
  "plugins": [
    "syntax-decorators",
    "transform-decorators-legacy",
    "transform-class-properties"
  ],
  "presets": [
    "es2015",
    "react",
    "stage-0"
  ]
}

Comments (4)

Vladislav
27. Jan 2017, 15:11

Really cool posts, however as you said in 3-rd post that js world is moving too fast, your posts really helped me out! Because I did not worked before with react stack and it was hard to jump right to webpack2, for instance, which is now released as there are not too much examples yet, and a lot of boilerplates looked like total overkill for learning project, so thank you a lot!

Stanko
06. Apr 2017, 11:09

Hello Vladislav,

Yeah, javascript development sure can be a bumpy road. I'm really glad it helped you!

Tommy C
12. Nov 2017, 19:58

Hello! These are wonderful tutorials; really digging them and learning a lot about the 'magic' behind boilerplates.

As of 11/12/2017 using

{
  test: /\.scss$/,
  loader: 'style!css!sass'
}

will result in the application failing to compile (at least it did for me anyway) and in order to fix it I had to add -loader to the 'loaders'

ex:

 {
  test: /\.scss$/,
  loader: 'style-loader!css-loader!sass-loader'
} 

Again, thanks for taking the time for these greate tutorials

Tommy C
12. Nov 2017, 20:32

Yo!

I was having trouble with postcss and it was causing compilation errors (11/12/2017): after some stackoverflowing I was able to find a fix that worked for me:

requiring webpack at the top of my webpack.config.js

const webpack = require('webpack');

and then inside of the plugins: [] block, I put a new webpack.LoaderOptionsPlugin:

Ex:

plugins: [
    new HtmlWebpackPlugin({
    template: path.join(paths.SRC, 'index.html'),
  }),
  new ExtractTextPlugin('style.bundle.css'),
  new webpack.LoaderOptionsPlugin({
      options: {
        context: __dirname,
      postcss: [
          autoprefixer, precss
      ]
    }
  })
],