About
a collection of simple demos of Webpack
This repo is a collection of simple demos of Webpack.
These demos are purposely written in a simple and clear style. You will find no difficulty in following them to learn the powerful tool.
## How to use
First, install [Webpack](https://www.npmjs.com/package/webpack) and [webpack-dev-server](https://www.npmjs.com/package/webpack-dev-server) globally.
```bash
$ npm i -g webpack webpack-dev-server
```
Then, clone the repo.
```bash
$ git clone https://github.com/ruanyf/webpack-demos.git
```
Install the dependencies.
```bash
$ cd webpack-demos
$ npm install
```
Now, play with the source files under the repo's demo* directories.
```bash
$ cd demo01
$ npm run dev
```
If the above command doesn't open your browser automatically, you have to visit http://127.0.0.1:8080 by yourself.
## Foreword: What is Webpack
Webpack is a front-end tool to build JavaScript module scripts for browsers.
It can be used similar to Browserify, and do much more.
```bash
$ browserify main.js > bundle.js
# be equivalent to
$ webpack main.js bundle.js
```
Webpack needs a configuration file called `webpack.config.js` which is just a CommonJS module.
```javascript
// webpack.config.js
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
}
};
```
After having `webpack.config.js`, you can invoke Webpack without any arguments.
```bash
$ webpack
```
Some command-line options you should know.
- `webpack` – building for development
- `webpack -p` – building for production (minification)
- `webpack --watch` – for continuous incremental building
- `webpack -d` – including source maps
- `webpack --colors` – making building output pretty
You could customize `scripts` field in your package.json file as following.
```javascript
// package.json
{
// ...
"scripts": {
"dev": "webpack-dev-server --devtool eval --progress --colors",
"deploy": "NODE_ENV=production webpack -p"
},
// ...
}
```
## Index
1. [Entry file](#demo01-entry-file-source)
1. [Multiple entry files](#demo02-multiple-entry-files-source)
1. [Babel-loader](#demo03-babel-loader-source)
1. [CSS-loader](#demo04-css-loader-source)
1. [Image loader](#demo05-image-loader-source)
1. [CSS Module](#demo06-css-module-source)
1. [UglifyJs Plugin](#demo07-uglifyjs-plugin-source)
1. [HTML Webpack Plugin and Open Browser Webpack Plugin](#demo08-html-webpack-plugin-and-open-browser-webpack-plugin-source)
1. [Environment flags](#demo09-environment-flags-source)
1. [Code splitting](#demo10-code-splitting-source)
1. [Code splitting with bundle-loader](#demo11-code-splitting-with-bundle-loader-source)
1. [Common chunk](#demo12-common-chunk-source)
1. [Vendor chunk](#demo13-vendor-chunk-source)
1. [Exposing Global Variables](#demo14-exposing-global-variables-source)
1. [React router](#demo15-react-router-source)
## Demo01: Entry file ([source](https://github.com/ruanyf/webpack-demos/tree/master/demo01))
Entry file is a file which Webpack reads to build `bundle.js`.
For example, `main.js` is an entry file.
```javascript
// main.js
document.write('
Hello World
');
```
index.html
```html
```
Webpack follows `webpack.config.js` to build `bundle.js`.
```javascript
// webpack.config.js
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
}
};
```
Launch the server, visit http://127.0.0.1:8080 .
```bash
$ cd demo01
$ npm run dev
```
## Demo02: Multiple entry files ([source](https://github.com/ruanyf/webpack-demos/tree/master/demo02))
Multiple entry files are allowed. It is useful for a multi-page app which has different entry file for each page.
```javascript
// main1.js
document.write('Hello World
');
// main2.js
document.write('Hello Webpack
');
```
index.html
```html
```
webpack.config.js
```javascript
module.exports = {
entry: {
bundle1: './main1.js',
bundle2: './main2.js'
},
output: {
filename: '[name].js'
}
};
```
## Demo03: Babel-loader ([source](https://github.com/ruanyf/webpack-demos/tree/master/demo03))
Loaders are preprocessors which transform a resource file of your app ([more info](https://webpack.js.org/concepts/loaders/)) before Webpack's building process.
For example, [Babel-loader](https://www.npmjs.com/package/babel-loader) can transform JSX/ES6 file into normal JS files,after which Webpack will begin to build these JS files. Webpack's official doc has a complete list of [loaders](https://webpack.js.org/loaders/).
`main.jsx` is a JSX file.
```javascript
// main.jsx
const React = require('react');
const ReactDOM = require('react-dom');
ReactDOM.render(
Hello, world!
,
document.querySelector('#wrapper')
);
```
index.html
```html
```
webpack.config.js
```javascript
module.exports = {
entry: './main.jsx',
output: {
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015', 'react']
}
}
}
]
}
};
```
The above snippet uses `babel-loader` which needs Babel's preset plugins [babel-preset-es2015](https://www.npmjs.com/package/babel-preset-es2015) and [babel-preset-react](https://www.npmjs.com/package/babel-preset-react) to transpile ES6 and React.
## Demo04: CSS-loader ([source](https://github.com/ruanyf/webpack-demos/tree/master/demo04))
Webpack allows you to include CSS in JS file, then preprocessed CSS file with [CSS-loader](https://github.com/webpack-contrib/css-loader).
main.js
```javascript
require('./app.css');
```
app.css
```css
body {
background-color: blue;
}
```
index.html
```html
Hello World
```
webpack.config.js
```javascript
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
module: {
rules:[
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
},
]
}
};
```
Attention, you have to use two loaders to transform CSS file. First is [CSS-loader](https://www.npmjs.com/package/css-loader) to read CSS file, and another one is [Style-loader](https://www.npmjs.com/package/style-loader) to insert `
```
## Demo05: Image loader ([source](https://github.com/ruanyf/webpack-demos/tree/master/demo05))
Webpack could also include images in JS files.
main.js
```javascript
var img1 = document.createElement("img");
img1.src = require("./small.png");
document.body.appendChild(img1);
var img2 = document.createElement("img");
img2.src = require("./big.png");
document.body.appendChild(img2);
```
index.html
```html
```
webpack.config.js
```javascript
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
module: {
rules:[
{
test: /\.(png|jpg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
}
}
]
}
]
}
};
```
[url-loader](https://www.npmjs.com/package/url-loader) transforms image files into `` tag. If the image size is smaller than 8192 bytes, it will be transformed into Data URL; otherwise, it will be transformed into normal URL.
After launching the server, `small.png` and `big.png` have the following URLs.
```html
```
## Demo06: CSS Module ([source](https://github.com/ruanyf/webpack-demos/tree/master/demo06))
`css-loader?modules` (the query parameter modules) enables the [CSS Module](https://github.com/css-modules/css-modules) which gives a local scoped CSS to your JS module's CSS. You can switch it off with `:global(selector)` ([more info](https://css-modules.github.io/webpack-demo/)).
index.html
```html
Hello World
Hello Webpack
```
app.css
```css
/* local scope */
.h1 {
color:red;
}
/* global scope */
:global(.h2) {
color: blue;
}
```
main.jsx
```javascript
var React = require('react');
var ReactDOM = require('react-dom');
var style = require('./app.css');
ReactDOM.render(
,
document.getElementById('example')
);
```
webpack.config.js
```
…
```
Launch the server.
```bash
$ cd demo06
$ npm run dev
```
Visiting http://127.0.0.1:8080 , you'll find that only second `h1` is red, because its CSS is local scoped, and both `h2` is blue, because its CSS is global scoped.
## Demo07: UglifyJs Plugin ([source](https://github.com/ruanyf/webpack-demos/tree/master/demo07))
Webpack has a plugin system to expand its functions. For example, [UglifyJs Plugin](https://webpack.js.org/plugins/uglifyjs-webpack-plugin/) will minify output(`bundle.js`) JS codes.
main.js
```javascript
var longVariableName = 'Hello';
longVariableName += ' World';
document.write('' + longVariableName + '
');
```
index.html
```html
```
webpack.config.js
```javascript
var webpack = require('webpack');
var UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
plugins: [
new UglifyJsPlugin()
]
};
```
After launching the server, `main.js` will be minified into following.
```javascript
var o="Hello";o+=" World",document.write(""+o+"
")
```
## Demo08: HTML Webpack Plugin and Open Browser Webpack Plugin ([source](https://github.com/ruanyf/webpack-demos/tree/master/demo08))
This demo shows you how to load 3rd-party plugins.
[html-webpack-plugin](https://github.com/ampedandwired/html-webpack-plugin) could create `index.html` for you, and [open-browser-webpack-plugin](https://github.com/baldore/open-browser-webpack-plugin) could open a new browser tab when Webpack loads.
main.js
```javascript
document.write('Hello World
');
```
webpack.config.js
```javascript
var HtmlwebpackPlugin = require('html-webpack-plugin');
var OpenBrowserPlugin = require('open-browser-webpack-plugin');
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
plugins: [
new HtmlwebpackPlugin({
title: 'Webpack-demos',
filename: 'index.html'
}),
new OpenBrowserPlugin({
url: 'http://localhost:8080'
})
]
};
```
Launch the server.
```bash
$ cd demo08
$ npm run dev
```
Now you don't need to write `index.html` by hand and don't have to open browser by yourself. Webpack did all these things for you.
## Demo09: Environment flags ([source](https://github.com/ruanyf/webpack-demos/tree/master/demo09))
You can enable some codes only in development environment with environment flags.
main.js
```javascript
document.write('Hello World
');
if (__DEV__) {
document.write(new Date());
}
```
index.html
```html
```
webpack.config.js
```javascript
var webpack = require('webpack');
var devFlagPlugin = new webpack.DefinePlugin({
__DEV__: JSON.stringify(JSON.parse(process.env.DEBUG || 'false'))
});
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
plugins: [devFlagPlugin]
};
```
Now pass environment variable into webpac