This post shows the steps to set up a React project using webpack from scratch.

Install webpack

After:

1
npm init

There are two options to install webpack:

1
npm install --save-dev webpack

or:

1
npm install -g webpack

Create webpack configuration file

Almost all the configurations are done in the webpack.config.js, the simplest one may look like this:

1
2
3
4
5
6
7
module.exports = {
entry: './src/app.js',
output: {
path: './bin',
filename: 'app.bundle.js'
}
};

Now create src folder and bin folder. src folder is the place you place all the source file, and bin folder is the place where all webpack puts the generated bundle files.

According to the above configuration file, the entry point is app.js and the generated bundle file is app.bundle.js.

If you edit something in app.js, type:

1
webpack

in the shell, and you would see app.bundle.js shown in bin folder.

Add ES6 and React support

webpack can only recognize JavaScript, but many people prefer ES6, JSX, etc. All these can be used in webpack just through some transformer, namely so-called loaders.

To support ES6 and React, babel is needed:

1
2
npm install --save-dev babel-core babel-preset-es2015 \
babel-preset-react react react-dom

and also create the babel rc file:

1
{ "presets": [ "es2015", "react" ] }

babel-loader loader use babel to transform the js file into pure JavaScript which webpack can understand:

1
npm install --save-dev babel-loader

And add loader configuration in webpack.config.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.exports = {
entry: './src/app.js',
output: {
path: './bin',
filename: 'app.bundle.js',
},
module: {
loaders: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
}]
}
}

The node_modules folder is skipped to accelerate the compilation.

If you want to make ES6 API available in older browsers, install babel-polyfill and import it in your code first:

1
npm install --save jquery babel-polyfill

and in src/app.js:

1
import 'babel-polyfill';

now strike the execiting command:

1
webpack

and import the bundle file in your html file (here, index.html):

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script src="bin/app.bundle.js" charset="utf-8"></script>
</body>
</html>

Open the index.html in your browser, you can see that all your code works well.

Add plugins

Maybe you wish to minify your generated js file, webpack provides UglifyJsPlugin to achieve that:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const webpack = require('webpack');
module.exports = {
entry: './src/app.js',
output: {
...
},
module: {
...
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
},
output: {
comments: false,
},
}),
]
}

Also, if you want to use the production version of react, you can define your plugin to set the NODE_ENV:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module.exports = {
entry: './src/app.js',
output: {
...
},
module: {
...
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
...
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
})
]
};

The project structure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
./react-starter
├── package.json
├── index.html
├── src
│   ├── app.js
│ └── ...
├── bin
│   └── app.bundle.js
├── node_modules
│   ├── babel-core
│   ├── babel-loader
│   ├── babel-polyfill
│   ├── babel-preset-es2015
│   ├── babel-preset-react
│   ├── react
│   ├── react-dom
│   ├── webpack
│   └── ...
├── webpack.config.js
└── .babelrc

One more thing

webpack also supports Hot Module Replacemet. To enable this feature, first you need to install webpack-dev-server:

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

or install it globally:

1
npm install -g webpack-dev-server

Then, use the following command:

1
webpack-dev-server --hot --inline

Open a browser to visit http://localhost:8080/, you will see your webpages and webpack will automatically regenerate bundle files if you change the source files.
Note: The default path for the generated files are the root folder of your project, if you want to change it, set publicPath to the folder you need:

1
2
3
4
5
6
7
8
9
module.exports = {
entry: './src/app.js',
output: {
publicPath: '/bin',
path: './bin',
filename: 'app.bundle.js'
},
...
};

The template project is here.