Setting up Webpack, Babel and React from scratch, revisited

Last summer I wrote this post which quickly became my most popular one to day. With webpack 2 and 3 it got outdated, so I decided to write a new one.

Before we start

I'll assume you have a basic knowledge of unix terminal, npm and JavaScript. You did some React, but now you want to level up and learn how setup React projects from scratch.

This is detailed step-by-step guide, as I'll try to explain the whole process. If you just want code to play with, check this repository I created for this tutorial.

Every time I talk about changing a source file, I'll paste complete file's content beneath it. You can look for ADDED IN THIS STEP comments which point out specific things that changed.

Please note that this tutorial is written on macOS using node 8.5.0, but it should work on Linux and Windows without any major issues. If you find something that is not working, please provide a correction in the comments below.

What are we trying to build?

Simple development setup for React applications using Webpack and Babel. But my main goal is for people to better understand these tools and how to use them.

Setup that we are going to create is minimal, but it follows the best practices and gives you a solid ground to start from.

Who am I and why should you listen to me?

Well, I'm a principal developer at Work&Co. I have a lot of experience on production level React projects, for clients like Twitter, Mastercard, Aeromexico, Hampton Creek... Marvin boilerplate (We have big plans for Marvin in the near future.) is my creation as well, and what I'm trying to teach you is directly based on my experience on these projects.

Init

Create a new folder, and package.json file in it, with the following content:

{
  "name": "webpack-babel-react-revisited"
}

Of course you can replace "webpack-babel-react-revisited" with your project name.

Webpack

We'll start with installing webpack for module bundling. It will transpile and bundle our JavaScript files, compile SASS or PostCSS, optimize images... and a bunch of other nifty things.

npm install --save-dev webpack

Then we need some modules. We'll keep our source files in src folder, so we need to create it. Then create js folder in the src folder you just created, and app.js file in it.

Add a simple console.log('Hello world!'); to app.js;

Now we can run webpack from the terminal for the first time:

./node_modules/webpack/bin/webpack.js ./src/js/app.js --output-filename ./dist/app.bundle.js

If you open generated app.bundle.js you'll see webpack's module handling code at the top, and at the end you'll find our modest console.log. Webpack's code does all the work with modules

  • connecting them together while keeping them in separate scopes. At this point we are not leveraging that (yet).

This command runs webpack using our app.js as entry and outputs the result to the dist folder. As it already looks complicated we'll start moving webpack configuration to a file.

Let's create webpack.config.js in our project's root. We need to add config we just used - only entry and output paths. (Plus paths constant. I like to keep paths in the constant object, as it makes things easier to read.)

// We are using node's native package 'path'
// https://nodejs.org/api/path.html
const path = require('path');

// Constant with our paths
const paths = {
  DIST: path.resolve(__dirname, 'dist'),
  JS: path.resolve(__dirname, 'src/js'),
};

// Webpack configuration
module.exports = {
  entry: path.join(paths.JS, 'app.js'),
  output: {
    path: paths.DIST,
    filename: 'app.bundle.js'
  },
};

You'll see that we added our app.js as entry and for the output we selected dist folder and app.bundle.js as the filename.

Now we can run webpack without inline configuration. By default webpack looks for webpack.config.js and reads config from it.

./node_modules/webpack/bin/webpack.js

This command has the exact same result as the first one. Now let's try to make it even nicer.

Open package.json which at this point should look like this:

{
  "name": "webpack-babel-react-revisited",
  "devDependencies": {
    "webpack": "^3.6.0"
  }
}

We'll add script section. In this sections, let's add build task with only one command - webpack.

{
  "name": "webpack-babel-react-revisited",
  "devDependencies": {
    "webpack": "^3.6.0"
  },
  "scripts": {
    "build": "webpack"
  }
}

Now we can run it using:

npm run build

Npm tasks allow us not to type full path to the package binary every time. It searches for locally installed packages in the project's node_modules folder.

Again, it has the same result like the previous command, but it is cleaner as it uses npm tasks instead of bare terminal commands.

Now we have our simple build process, so we can proceed with development setup.

Webpack dev server

To be able to open our application in a browser, we'll need a server. Webpack already provides us with a dev server. It will server our files during development (obviosly), but also enable us to use hot module reload (not covered by this post).

Let's install it:

npm install --save-dev webpack-dev-server

Let's update package.json right away to make it easier to run dev server.

{
  "name": "webpack-babel-react-revisited",
  "devDependencies": {
    "webpack": "^3.6.0",
    "webpack-dev-server": "^2.9.1"
  },
  "scripts": {
    "dev": "webpack-dev-server",
    "build": "webpack"
  }
}

We added only one line: "dev": "webpack-dev-server",.

Now if you run

npm run dev

it will fire up our development server, and it is going to be available at http://localhost:8080. Now it will just list our project's files.

So let's create a simple index.html in the src folder

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">

    <title>Webpack Babel React revisited</title>
  </head>
  <body>
  </body>
</html>

and update webpack.config.js to use src as a content base.

// We are using node's native package 'path'
// https://nodejs.org/api/path.html
const path = require('path');

// Constant with our paths
const paths = {
  DIST: path.resolve(__dirname, 'dist'),
  SRC: path.resolve(__dirname, 'src'), // source folder path -> ADDED IN THIS STEP
  JS: path.resolve(__dirname, 'src/js'),
};

// Webpack configuration
module.exports = {
  entry: path.join(paths.JS, 'app.js'),
  output: {
    path: paths.DIST,
    filename: 'app.bundle.js',
  },
  // Dev server configuration -> ADDED IN THIS STEP
  // Now it uses our "src" folder as a starting point
  devServer: {
    contentBase: paths.SRC,
  },
};

Every time you change webpack config you need to restart webpack (or webpack dev server).

Restart npm run dev and visit http://localhost:8080, it will just show a blank page. No signs of our JavaScript. To automatically inject <script> tags with our bundled application we'll use html-webpack-plugin.

HTML Webpack Plugin

This plugin simplifies creation of HTML files to serve your webpack bundles. Let's install it:

npm install --save-dev html-webpack-plugin

Once installed we need to activate it in webpack.config.js. Require it and add it to the plugins section of the config: (We don't need contentBase: paths.SRC anymore as it will be handled by html plugin. So we'll remove whole devServer configuration object for now.)

// We are using node's native package 'path'
// https://nodejs.org/api/path.html
const path = require('path');

const HtmlWebpackPlugin = require('html-webpack-plugin'); // Import our plugin -> ADDED IN THIS STEP

// Constant with our paths
const paths = {
  DIST: path.resolve(__dirname, 'dist'),
  SRC: path.resolve(__dirname, 'src'),
  JS: path.resolve(__dirname, 'src/js'),
};

// Webpack configuration
module.exports = {
  entry: path.join(paths.JS, 'app.js'),
  output: {
    path: paths.DIST,
    filename: 'app.bundle.js',
  },
  // Tell webpack to use html plugin -> ADDED IN THIS STEP
  // index.html is used as a template in which it'll inject bundled app.
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(paths.SRC, 'index.html'),
    }),
  ],
  // Dev server configuration -> REMOVED IN THIS STEP
  // devServer: {
  //   contentBase: paths.SRC,
  // },
};

When we restart dev task, we'll be able to see Hello world! in the console. Now we are talking! We can start adding some modern JavaScript.

Babel

To be able to use ES2015 and beyond we'll need to provide a transpiler. Our choice is Babel. Babel takes modern JavaScript and transpiles it - converts it to the old version of JavaScript that can be executed in the browsers that don't support modern JavaScript standards.

We need this for two reasons (and you probably know both already):

  • React and JSX heavily rely on modern JavaScript features
  • You should use modern JavaScript - it makes things easier and helps you write better code

Let's continue by installing four packages:

  • Babel core package
  • Babel webpack loader
  • Babel env preset (babel-preset-env is successor of babel-preset-es2015 and it has couple of big advantages which may be covered in another post. You can read more about using it in this post)
  • Babel React preset
npm install --save-dev babel-core babel-loader babel-preset-env babel-preset-react

Babel also has default config file which is .babelrc, so let's create it in our project's root:

{
  "presets": ["env", "react"]
}

This will tell Babel to use two presets we just installed.

Now we need to update webpack.config.js to use Babel loader for .js and .jsx files. We also added some sugar, so you can import those files without specifying file extension.

// We are using node's native package 'path'
// https://nodejs.org/api/path.html
const path = require('path');

const HtmlWebpackPlugin = require('html-webpack-plugin');

// Constant with our paths
const paths = {
  DIST: path.resolve(__dirname, 'dist'),
  SRC: path.resolve(__dirname, 'src'),
  JS: path.resolve(__dirname, 'src/js'),
};

// Webpack configuration
module.exports = {
  entry: path.join(paths.JS, 'app.js'),
  output: {
    path: paths.DIST,
    filename: 'app.bundle.js',
  },
  // Tell webpack to use html plugin
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(paths.SRC, 'index.html'),
    }),
  ],
  // Loaders configuration -> ADDED IN THIS STEP
  // We are telling webpack to use "babel-loader" for .js and .jsx files
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: [
          'babel-loader',
        ],
      },
    ],
  },
  // Enable importing JS files without specifying their's extenstion -> ADDED IN THIS STEP
  //
  // So we can write:
  // import MyComponent from './my-component';
  //
  // Instead of:
  // import MyComponent from './my-component.jsx';
  resolve: {
    extensions: ['.js', '.jsx'],
  },
};

Restart npm run dev once again. Nothing really changed, but our JavaScript is now transpiled, and if you used any of the modern JavaScript features, those would be transpiled to ES5 synthax.

Finally let's add React.

React

This is probably the main reason you are reading this, so I'll assume you are already familiar with React.

Install it (this time as a regular dependency):

npm install --save react react-dom

Let's add div with id app to index.html, in which we'll render our React app.

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">

    <title>Webpack Babel React revisited</title>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

Finally replace console.log in our app.js with a real React component.

import React, { Component } from 'react';
import { render } from 'react-dom';

export default class Hello extends Component {
  render() {
    return (
      <div>
        Hello from react
      </div>
    );
  }
}

render(<Hello />, document.getElementById('app'));

Restart dev server one more time, and voala, we have our React app running!

This is minimal working setup

At this point, you have bare bones setup for making React apps using Webpack and Babel. You can start exploring on your own, add more stuff and modify it to fit your needs. However in this post I'll cover two more things - CSS and assets loaders.

CSS

Every web application needs CSS. So let's add a way of getting CSS into ours. Create src/css folder and a simple style.css in it.

body {
  background: #f9fafb;
  font-family: Helvetica, Arial, sans-serif;
  font-size: 16px;
  margin: 0;
  padding: 30px;
}

To add this CSS file to the app, we'll use css-loader.

CSS loader needs to write loaded CSS code to either style tag in the head or external stylesheet file. If you want to write it to the style tag you should use style-loader.

But for now, we'll extract it to the external file by using extract-text-webpack-plugin. HTML webpack plugin, that we already set, will add css file to index.html for us.

Again, start by installing packages:

Update, April 2018: Please note, if you are using webpack v4.x you'll need to install extract-text-webpack-plugin@next which is webpack 4 compatible.

npm install --save-dev css-loader extract-text-webpack-plugin

We'll need to do two more things:

  • import our CSS in app.js:
import React, { Component } from 'react';
import { render } from 'react-dom';

import '../css/style.css'; // Import CSS -> ADDED IN THIS STEP

export default class Hello extends Component {
  render() {
    return (
      <div>
        Hello from react
      </div>
    );
  }
}

render(<Hello />, document.getElementById('app'));
  • and update webpack config to use css-loader for CSS files:
// We are using node's native package 'path'
// https://nodejs.org/api/path.html
const path = require('path');

const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin'); //  -> ADDED IN THIS STEP

// Constant with our paths
const paths = {
  DIST: path.resolve(__dirname, 'dist'),
  SRC: path.resolve(__dirname, 'src'),
  JS: path.resolve(__dirname, 'src/js'),
};

// Webpack configuration
module.exports = {
  entry: path.join(paths.JS, 'app.js'),
  output: {
    path: paths.DIST,
    filename: 'app.bundle.js',
  },
  // Tell webpack to use html plugin
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(paths.SRC, 'index.html'),
    }),
    new ExtractTextPlugin('style.bundle.css'), // CSS will be extracted to this bundle file -> ADDED IN THIS STEP
  ],
  // Loaders configuration
  // We are telling webpack to use "babel-loader" for .js and .jsx files
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: [
          'babel-loader',
        ],
      },
      // CSS loader to CSS files -> ADDED IN THIS STEP
      // Files will get handled by css loader and then passed to the extract text plugin
      // which will write it to the file we defined above
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract({
          use: 'css-loader',
        }),
      }
    ],
  },
  // Enable importing JS files without specifying their's extenstion
  //
  // So we can write:
  // import MyComponent from './my-component';
  //
  // Instead of:
  // import MyComponent from './my-component.jsx';
  resolve: {
    extensions: ['.js', '.jsx'],
  },
};

This might seem very complicated to get one CSS file to the page, but it is very useful when you have multiple stylesheet files and pre-processing (or post-processing).

Restart npm run dev, and you'll see that five lines of our beautiful CSS are applied on the page.

And if we run npm run build you'll see style.bundle.css (I use .bundle postfix so you can easier differentiate webpack bundles from the source files.) created in the dist folder, next to js and html files.

Assets

For the end, we'll add file-loader. As it's name suggests it handles files - images, SVGs, fonts, videos or anything else you need.

Let's create /src/assets/ folder and add Commander Keen image (I still love Commander Keen games.) in it.

Follow the same flow as with CSS files

  • install loader
npm install --save-dev file-loader
  • import image in app.js and render it
import React, { Component } from 'react';
import { render } from 'react-dom';

import '../css/style.css';

import keenImage from '../assets/keen.png'; // Importing image -> ADDED IN THIS STEP

export default class Hello extends Component {
  render() {
    return (
      <div>
        Hello from react

        {/* ADDED IN THIS STEP */}
        <img src={ keenImage } alt='Commander Keen' />
      </div>
    );
  }
}

render(<Hello />, document.getElementById('app'));
  • update webpack config to handle image assets
// We are using node's native package 'path'
// https://nodejs.org/api/path.html
const path = require('path');

const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

// Constant with our paths
const paths = {
  DIST: path.resolve(__dirname, 'dist'),
  SRC: path.resolve(__dirname, 'src'),
  JS: path.resolve(__dirname, 'src/js'),
};

// Webpack configuration
module.exports = {
  entry: path.join(paths.JS, 'app.js'),
  output: {
    path: paths.DIST,
    filename: 'app.bundle.js',
  },
  // Tell webpack to use html plugin
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(paths.SRC, 'index.html'),
    }),
    new ExtractTextPlugin('style.bundle.css'), // CSS will be extracted to this bundle file -> ADDED IN THIS STEP
  ],
  // Loaders configuration
  // We are telling webpack to use "babel-loader" for .js and .jsx files
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: [
          'babel-loader',
        ],
      },
      // CSS loader for CSS files
      // Files will get handled by css loader and then passed to the extract text plugin
      // which will write it to the file we defined above
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract({
          use: 'css-loader',
        }),
      },
      // File loader for image assets -> ADDED IN THIS STEP
      // We'll add only image extensions, but you can things like svgs, fonts and videos
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          'file-loader',
        ],
      },
    ],
  },
  // Enable importing JS files without specifying their's extenstion
  //
  // So we can write:
  // import MyComponent from './my-component';
  //
  // Instead of:
  // import MyComponent from './my-component.jsx';
  resolve: {
    extensions: ['.js', '.jsx'],
  },
};

Restart npm run dev and refresh the browser to see the image. npm run build will create image in the dist folder.

That was quite a ride

And all that to create a very simple application, that should look something like this:

Example app running in the browser

Hopefully, you now understand webpack better and are able to create new apps from scratch.

If you enjoyed this tutorial, please share it, and help me improving it by pointing out things that are not clear enough or could be written better.

Complete code is available in this repository.

But I want more!

Don't worry, I will cover more in posts to come. But it might take a while, as creating a meaningful tutorial is really time consuming. So please, bear with me.

This new tutorial series is closely related to Marvin's future. So there will posts about development of Marvin and setting up React applications using React.

React router, redux, hot module reload, thunks, sagas, SASS, PostCSS, universal rendering are some of the themes that I want to write about.

Cheers!

Comments (79)

RL Glover
08. Oct 2017, 02:45

Powerful tutorial obviously created by an exceptional visionary. Highly recommended for the consummate professional.

Yassine
08. Oct 2017, 07:19

Great to find an updated Tutorial.

Abhirup Kundu
08. Oct 2017, 13:03

Excellent tutorial. Very well written and explained. Helped me a lot.

Daniel Lo Nigro
09. Oct 2017, 04:55

A minor note: Instead of running ./node_modules/webpack/bin/webpack.js

you can run ./node_modules/.bin/webpack

It's a little bit shorter :)

Marko Stankovic
09. Oct 2017, 07:35

Very good post, completely understandable and has good comments. Keep it up Stanko!

Stanko
09. Oct 2017, 07:55

Thank you all!

@Daniel Lo Nigro I wasn't aware of that, thank you for the tip. I just found more info about it in the official documentation https://docs.npmjs.com/files/folders

Paul
10. Oct 2017, 23:17

Thanks! I found this very helpful and great to have a tutorial using WebPack 2 from scratch.

Pouya
11. Oct 2017, 13:43

Thank you. Really useful tutorial.

gbarkhatov
12. Oct 2017, 06:34

Hey man. Waiting for the new things from you. Is there a way to subscribe to your blog? Maybe rss or kinda

Stanko
12. Oct 2017, 07:01

Thanks everyone!

@gbarkhatov, RSS feed is available in the main menu, but here is direct link to it.

Rafael Rinaldi
13. Oct 2017, 17:15

It's great to see an up to date and battle tested perspective on the subject. Very helpful, thank you.

Josh Habdas
13. Oct 2017, 19:41

Don't reinvent the wheel. The best boilerplates have already been invented and are listed right here: https://habd.as/awesome-react-boilerplates/

P.s. Nice design on this site.

Josh Habdas
13. Oct 2017, 19:43

I do hope you'll post my comment, as I'm shilling but it's good for the community to know about. You should be more open with your comment policy.

Stanko
13. Oct 2017, 19:54

Thanks guys!

@Josh thanks for sharing. But intended point of this post is learning, and explaining how these tools work. With boilerplates there is a lot of “magic” and things hidden under the hood (as an author of one I can say that with confidence).

As for the comment policy, I just filter out spam.

Cheers!

Avinash Thakur
13. Oct 2017, 20:48

That was a good tutorial for beginners...

Ivan
14. Oct 2017, 16:15

Excellent tutorial, Stanko

Mathew Cohen
14. Oct 2017, 22:32

So... uh...

D:__MyCodingProjects__TestingGround\WebackAndBabel>./node_modules/webpack/bin/webpack.js ./src/js/app.js --output-filename ./dist/app.bundle.js '.' is not recognized as an internal or external command, operable program or batch file.

Rahmat Budiharso
14. Oct 2017, 23:10

Thank you for the post, it's just what I needed. I'm constantly battling with webpack configuration and those "boilerplate" got too much magic for me to understand which part doing what, hope to see another post just like this.

Stanko
14. Oct 2017, 23:12

Hey Mathew, It seems you are running it on Windows, that is a Unix command that fails. Unfortunately, I don't have access to a Windows machine. Without one, it is hard for me to help you, but you can try this.

From you your project's folder add node_modules to the Windows PATH by running:

set -x PATH ./node_modules/.bin $PATH

Then instead of whole /node_modules/webpack/bin/webpack.js [arguments] thing, you can just run webpack [arguments].

Note that if you close your cmd, you'll need to add it to the path again. But don't worry, you'll probably need this only once (tutorial switches to using npm run commands in the next step).

If any of you Windows folks is familiar with this, please share more elegant solution, so I can update the post.

Thanks guys!

Joseph
15. Oct 2017, 08:16

Great tutorial, can't wait for examples of this with Redux. I would also like to know how to make this SEO friendly. If you look at the HTML since the content is rendered on the client side the SEO robots can't see the text and they index the pages incorrectly. What solution do you have for this?

Stanko
15. Oct 2017, 08:48

Hey Joseph,

Making a single page application SEO friendly is not an easy task.

The best solution is server side rendering (which I also plan to cover later on). It means having the same React application execute on a server (in node environment) when web request comes to it. Then it returns rendered HTML to a client (and search engine crawlers).

Once loaded on the client side, same React app loads in the browser and takes over. So the first render happens on the server and then it continues to work as a regular single page app.

Other, simpler, but uglier solution is to make a simple crawler which will go through your app and cache all of the responses. Then it would recognize search engine robots and serve them these static pages rather then your app.

My advice would be to go with server side rendering, it is harder, but it is cleaner solution. And you don't have to worry about invalidating the static pages cache.

Thanks!

Timothy
15. Oct 2017, 11:32

Thanks for a great tutorial! Really helps to take some of the magic and head-scratching out.

No need to post this in your comments, but there is a typo in the "update webpack config to handle image assets" code: Line 6 has the "// -> ADDED IN THIS STEP" comment when it was actually added in a previous step.

Stanko
15. Oct 2017, 12:04

Thank you Timothy! I made a correction.

Gareth Elms
15. Oct 2017, 13:45

I'm concerned about the final bundle size.

When I use webpack -p my app.bundle.js file is 115KB. Is this the base bundle size for any React app?

I'm using v16.0 of React which has optimized the React and React Dom bundle size :

https://reactjs.org/blog/2017/09/26/react-v16.0.html#reduced-file-size

Beyond using webpack -p, is my only option here gzip? Are there any other ways to get a lower bundle size on a base React app?

Thanks

Mario Terron
15. Oct 2017, 17:29

Excellent tutorial, waiting for more.

Daniel
15. Oct 2017, 19:22

The article is large. Takes time to read it and go through it. You should add anchor permalinks on different steps, so that a reader can come back to a certain step later.

Petar
16. Oct 2017, 07:50

Great article. It might be useful to add links to parts of the page with a content at the beginning so people can jump to certain parts, also safari seems to have a weird bug when scrolling up and down on this page :p (I use it to test stuff, sue me). Keep it up :)

Jennie
16. Oct 2017, 21:42

Great tutorial, thanks a lot!

Gerson
17. Oct 2017, 03:59

Thanks, it is so clear. Awesome!

Anthony
17. Oct 2017, 17:35

Awesome tutorial. Hard to find a clear and easy to follow breakdown of how to setup a React/ES2015 project with Babel. How would you incorporate using SASS into the webpack config?

Nahuel José
17. Oct 2017, 21:14

Awesome! I needed this. Just one thing you should fix. The "build" script should be "webpack -p", this way we get the production version of React!

nannigan
17. Oct 2017, 22:35

nicely done, thank you!

Tuhaj
18. Oct 2017, 12:58

Hey! Very nice tutorial, I appreciate your work Stanko. For all who are interested in using existing boilerplates I had a presentation at WarsawJS it where I compared the features them, so you can have a look if you want https://youtu.be/E7hbVm9Fh9w

James
18. Oct 2017, 14:16

@Anthony:

The basics of adding SASS are pretty easy. First npm i -D node-sass sass-loader, and then update the CSS module loader rule to this:

{
    test: /\.scss$/,
    loader: ExtractTextPlugin.extract({
        // Loader chaining works from right to left
        use: ['css-loader', 'sass-loader']
    })
} 

Once you rename your style.css file to style.scss and update the import reference in app.js, you should be good to go!

Elizabeth Reiher
19. Oct 2017, 18:37

I started receiving this error after we added 'index.html' and installed package with 'npm install --save-dev html-webpa-plugin'.

Error: Cannot find module '../lib/polyfills' And so my 'npm run dev' would not work after that.

Evgeniy Kutischev
19. Oct 2017, 20:28

Great tutorial @Stanko. Thanks for your work!

To make it a bit more Windows users friendly I suggest to replace this command: ./node_modules/webpack/bin/webpack.js ./src/js/app.js --output-filename ./dist/app.bundle.js

with this: ./node_modules/.bin/webpack ./src/js/app.js --output-filename ./dist/app.bundle.js

Because in Windows' terminal the first command instead of launching webpack will open webpack.js file in user's default app for *.js files. Looks like it happens because Windows is not familiar with "shebang" sequence. The second variant will work on Windows fine and I'm pretty sure that it should work well on Mac OS and Linux.

bill
21. Oct 2017, 07:09

Thank you so much for this tutorial, I'm new to ReactJS and found so many articles with old webpack setup, but your tutorial is awesome, easy for me to understand.

Stanko
21. Oct 2017, 18:47

Thanks everyone for suggestions and kind words.

@Anthony SASS will be covered in one of the posts to come.

@Elizabeth I can't really debug with the info you gave me. Check the repo that goes with this post, it might help.

Cheers!

Larry
22. Oct 2017, 14:42

Awesome stuff! Thank you.

Christian
22. Oct 2017, 20:37

Hey nice setup you got here especially it supports the latest Webpack and React. Can you use GULP for building all this stuffs in the future? Thank you!

Jon M
25. Oct 2017, 03:36

Great work.

Steven
29. Oct 2017, 04:02

thanks for sharing!

David
29. Oct 2017, 23:06

Thank you for this amazing tutorial.

Minor correction: in the Assets section you forgot to remove the "ADDED IN THIS STEP" comment from the line new ExtractTextPlugin('style.bundle.css'),

Matteo
31. Oct 2017, 12:35

Thank you very much for this awesome tutorial!

Koyot
01. Nov 2017, 20:29

Wait, do I really have to use Babel to utilize es2015 features? I thought it's already a standard and adding Babel will unnecessarily bloat the code

PJ
04. Nov 2017, 01:08

Thanks a lot Stanko! I can't wait to read the following posts you plan to write: hot-reload and server-side rendering configuration in particular. I've used MERN so far, but it's getting somehow outdated now, without maintenance... I'll probably migrate to Marvin soon or at least get some inpiration, but I fear the task of doing so!

Anurag
06. Nov 2017, 11:41

Nicely explained! Thanks. Can you also create a similar post for MERN setup with webpack?

Stanko
06. Nov 2017, 12:11

Again, thank you guys!

@Christian well Gulp is solving a little bit different problem, and it is just additional layer on webpack setup. I think it is worth it to invest time to learn webpack and switch to it.

@David good catch, thank you!

@Koyot depending on the ES2016 features you are after, some are supported in the modern browsers, some are not. But still you need to transpile everything for older browsers.

@Anurag I have no experience with MERN, which advantages it has over webpack?

Matunga
09. Nov 2017, 14:41

Awesome tutorial! Thanks a lot!

Lanil
17. Nov 2017, 16:49

Very good tutorial. Helped me a lot. Can you please do some more tutorials on stuff like ESLint, Unit Testing etc.

Laurynas
19. Nov 2017, 19:32

Excellent tutorial! Thanks a lot!

Lam
27. Nov 2017, 08:58

Very helpful article and very clear explanation. Thank you very much

aldhonie
01. Dec 2017, 13:53

Awesome, Thanks a lot stanko. Youre doing a good job!

Joey
04. Dec 2017, 10:43

Great tutorial. Now how do I transpile my scss files into this thing?

Stanko
05. Dec 2017, 10:21

Hey Joey, SCSS might be the part of the next post in the series. Meantime you can use marvin boilerplate, which has SCSS support out of the box.

yinfan
05. Dec 2017, 11:55

Thank you very much, Great tutorial!

Jarno
09. Dec 2017, 13:18

Thank you, great tutorial.. Cant wait for the SASS post :)

Chris
10. Dec 2017, 16:49

This was a great help, thank you.

swhp
13. Dec 2017, 00:58

Thank you very much for this article sir, it's really help me to started and understanding with my React project. I prefer know how to rather than using a template (I'm not quite fan of magic to be honest)

Sergiu Lucaci
13. Dec 2017, 12:28

Though I work with both React and Webpack 1 for some time, this article helped gave me a clearer image about how Webpack actually works.

GG Stanko!

Joisak
28. Dec 2017, 13:45

A very good article! I wonder how to add a new component? Think that I need to do changes in the webpack.config file, right?

Thanks!

Claudomiro jr.
28. Dec 2017, 17:50

Thanks for helping this old developer here getting up to speed with all these cool shiny new things!

Stanko
29. Dec 2017, 10:49

Thanks everyone!

@Joisak, there is no need to alter webpack.config, just start making your components in src/js/ folder.

Dana Yudelevich
03. Jan 2018, 19:45

Great tutorial @stanko! Adding SASS would definitely be a good step to add.

Jason
04. Jan 2018, 23:44

When I'm changing css styles, I need reloading browser by manual. How do it automatically, the same as in app.js ?

Robert
09. Jan 2018, 03:19

Very helpful post. Many thanks!

madushan
22. Jan 2018, 11:46

really nice one thanks for the effort. looking forward to having some example of redux

larr
22. Jan 2018, 20:40

Awesome tutorial! How would I go about deploying this application to Heroku?

Patrick
24. Jan 2018, 10:47

Hey Stanko, Could you provide us with an example of how to load and use Mocha with webpack? Should I do a different webpack config files just for Mocha? My aim is to run mocha tests in the browser with React, using webpack. Thanks!

Stanko
24. Jan 2018, 10:53

Thanks everyone!

For things like Redux, PostCSS and hot module reload check Marvin, my production ready React boilerplate.

@larr, I have never used heroku, sorry can't help you there.

@Patrick, same here, I don't use Mocha, but this might help.

Cheers!

Joseph
25. Jan 2018, 00:10

Nice work!! thank you so much!!

Rahul
06. Feb 2018, 11:47

Thank you for this wonderful tutorial. It helped me understand a lot of basic things and gave me a good idea about how to put things together and how things work under the hood.

Roberto
05. Apr 2018, 15:07

Hi, great tutorial thank you. I encountered an error due to the version of "extract-text-webpack-plugin", and i solved it by installing extract-text-webpack-plugin@next instead, which points to the beta branch.

Stanko
05. Apr 2018, 15:14

Hey Roberto, That is correct, that error happens when using Webpack v4 and this blog post was written for Webpack v3. I'll add a note there, thank you!

Cheers!

Olatunji Yusuf
08. Apr 2018, 20:00

Excellent Stuff!

@friday
11. Jul 2018, 16:05

You are the best. This is the best tutorial I have read for a while been really struggling with this not until now. You Really did great and kill it Wow!!! Nothing but to say thanks alot.

SomeDevRevisiting
22. Aug 2018, 08:05

Awesome tutorial! Explanations are not that long but contains the important stuff!

Kumar Gaurav
05. Jun 2019, 13:21

Hey, Do you have any post specific to VueJS setup with Webpack 4 ??

Stanko
05. Jun 2019, 15:29

Hi Kumar, Unfortunately I have no production experience with Vue.js

Cheers!