Webpack can be used to bundle scripts, styles, images, and assets. During the bundle process, it will analyze the dependencies between files and modules, and finally output static files. These static files already contain third-party modules. In other words, there is no need to install third-party modules in runtime. Many SPA frameworks, such as React, Angular, Vue.js and React Native, all use Webpack.
The complete code can be found in .
Table of Contents
Creating a Webpack Project
Create an NPM project.
% mkdir WebpackExample % cd WebpackExample WebpackExample % npm init -y
Install webpack and webpack-cli packages.
WebpackExample % npm install webpack webpack-cli --save-dev
Create the first JavaScript file called index.js where we will use Lodash module, so let’s install it.
WebpackExample % npm install --save lodash WebpackExample % mkdir src WebpackExample % cd src WebpackExample/src % vi index.js
In index.js, we use lodash simply to print “Hello Webpack!”.
import _ from 'lodash'; console.log(_.join(['Hello', 'Webpack'], ' '));
Create a configuration file for Webpack. Its default file name is webpack.config.js. In this configuration file, the entry property is the entry file, and the output property is the output directory and file name.
const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'index.js', path: path.resolve(__dirname, 'dist'), }, };
The basic Webpack project is done. Let’s use Webpack command shown below to bundle src/. If the configuration file of webpack is not named as webpack.config.js, use –config to specify the path of the file.
WebpackExample% npx webpack Hash: 4cdaba133dc7948617d8 Version: webpack 4.43.0 Time: 42ms Built at: 07/06/2020 11:13:20 AM Asset Size Chunks Chunk Names index.js 959 bytes 0 [emitted] main Entrypoint main = index.js [0] ./src/index.js 31 bytes {0} [built] WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
We can see a folded added called under the project. Under the folder, the file dist/index.js is the bundle file.
WebpackExample % ls dist index.js
Take at look at dist/index.js. You can see that Lodash module is also compiled in it. Webpack bundles several JavaScript files into a single JavaScript file, and also minifies the bundle file.
Finally, let’s add npx webpack
command to the NPM script. Modify package.json as follows:
{ "name": "WebpackExample", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "build": "webpack" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "webpack": "^4.43.0", "webpack-cli": "^3.3.12" } }
After adding the NPM script, you can use npm run build
command to bundle the project.
WebpackExample % npm run build
HtmlWebpackPlugin
The main purpose of Webpack is to bundle several JavaScript files into a single JavaScript file. Of course, it is far more than that. JavaScript is mainly used to develop web pages, so there must be HTML files. So Webpack can also help us output HTML files.
Install HtmlWebpackPlugin .
WebpackExample% npm install --save-dev html-webpack-plugin
Add an HTML template file.
WebpackExample % mkdir public WebpackExample % cd public WebpackExample/public % vi index.html
The HTML template file is as follows. It is a very simple HTML file, and Webpack will automatically add the compiled index.js to the template file.
<html> <head> </head> <body> <div id="app"> </div> </body> </html>
Modify src/index.js as follows:
import _ from 'lodash'; const app = document.getElementById('app'); app.innerHTML = _.join(['Hello', 'Webpack'], ' ');
In webpack.config.js, we add HtmlWebpackPlugin to the plugin list. The template
is our HTML template file, filename
is the name of the output file under dist/, and inject
is whether to inject index.js into the HTML template file.
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/index.js', output: { filename: 'index.js', path: path.resolve(__dirname, 'dist'), }, plugins: [ new HtmlWebpackPlugin({ title: 'Home', filename: 'index.html', template: 'public/index.html', inject: true, }), ], };
Let’s bundle the project!
WebpackExample% npm run build
Let’s look at dist/, you can see index.html is added. Open index.html with browsers, you can see it outputs “Hello Webpack”. Open and take a look at index.html, you can find that not only index.js is injected, but the entire file is also minified.
WebpackExample % ls dist index.html index.js
CleanWebpackPlugin
Every time we bundle a project, it directly outputs to the dist folder and overwrites the existing files. It doesn’t clear the last output files, but just directly overwrites them. That turns out dist/ may contains some files from the last bundle but not existing in this bundle. We can use CleanWebpackPlugin to clear the last Bundle.
Install CleanWebpackPlugin.
WebpackExample% npm install --save-dev clean-webpack-plugin
Add CleanWebpackPlugin to webpack.config.js so that every time we bundle the project, the last bundle output will be cleared first.
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { entry: './src/index.js', output: { filename: 'index.js, path: path.resolve(__dirname, 'dist'), }, plugins: [ new HtmlWebpackPlugin({ title: 'Home', filename: 'index.html', template: 'public/index.html', inject: true, }), new CleanWebpackPlugin(), ], };
Change Entry File
The entry
in webpack.cofig.js can be a string or an object. When it is a string, its default name is index; when it is an object, we can set multiple entries and names.
Modify webpack.config.js as follows. Now there is an app
under entry
. On output
, we can set the output file name according to the name of the entry.
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { entry: { app: './src/index.js', }, output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist'), }, plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title: 'Home', filename: 'index.html', template: 'public/index.html', inject: true, }), ], };
After bundling the project again, app.bundle.js will be added under dist/.
WebpackExample % npm run build WebpackExample % ls dist app.bundle.js index.html
CSS Loaders
Webpack handles js files by default, but it can handle other file types by adding loaders. Next, let’s make our project can handle CSS files.
Install style-loader and css-loader .
WebpackExample % npm install --save-dev css-loader style-loader
Create src/style.css file.
.hello { color: red; }
In src/index.js, we can use import
to import CSS files.
import _ from 'lodash'; import './style.css'; const app = document.getElementById('app'); app.innerHTML = _.join(['Hello', 'Webpack'], ' '); app.classList.add('hello');
Finally, we have to set the CSS loader in webpack.config.js as follows. Add style-loader and css-loader to the rules
, and specify the file types that the loader can handle.
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { entry: { app: './src/index.js', }, output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist'), }, plugins: [ new HtmlWebpackPlugin({ title: 'Home', filename: 'index.html', template: 'public/index.html', inject: true, }), new CleanWebpackPlugin(), ], module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader', ], }, ], }, };
Aftr bundling the project, you can found that there is no .css file in the dist/. This is because CSS is bundled into app.bundle.js.
File Loaders
With file-loader , Webpack can also handle image files. Next, let’s add a loader to process image files.
Install file-loader.
npm install --save-dev file-loader
Put an image file in src/, and name it as src/icon.png.
In src/index.js, you can use import
to import image files.
import _ from 'lodash'; import './style.css'; import Icon from './icon.png'; const app = document.getElementById('app'); app.innerHTML = _.join(['Hello', 'Webpack'], ' '); app.classList.add('hello'); const icon = new Image(); icon.src = Icon; app.appendChild(icon);
Finally, in webpack.config.js, add file-loader and set the file types that can be processed.
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { entry: { app: './src/index.js', }, output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist'), }, plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title: 'Home', filename: 'index.html', template: 'public/index.html', inject: true, }), ], module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader', ], }, { test: /\.(png|svg|jpg|gif)$/, use: [ 'file-loader', ], }, ], }, };
Bundle the project. You can a .png file added under dist/. The file name has been re-encoded.
WebpackExample % ls dist 99d4ae376af2a9084b5f65b2fc8b8156.png app.bundle.js index.html
HotReload/LiveReload
We will introduce powerful features of Webpack, that are Hot Reload and Live Reload. Both mean that when the project has any changes, it can immediately recompile and refresh the display on browsers. The difference is that Hot Reload only updates the changed parts, while Live Reload refreshes entirely. Many SPA frameworks support Hot/Live Reload. It is very easy to add this feature to Webpack projects.
Install webpack-dev-server .
npm install --save-dev webpack-dev-server
In webpack.config.js, we have added devtool and devServer. devtool can specify different source maps.
DevServer settings:
- port: Specify the port number. The server url will be http://localhost:[port].
- transportMode: refers to how browsers communicates with devServer. ws means to use WebSocket. The default is sockjs, that uses sockjs-node module. This is because some browsers do not support WebSocket.
- hot/liveReload: Refers to use either Hot Reload or Live Reload.
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { mode: 'development', entry: { app: './src/index.js', }, devtool: 'inline-source-map', devServer: { transportMode: 'ws', hot: false, liveReload: true, port: 9000, }, output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist'), }, plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title: 'Home', filename: 'index.html', template: 'public/index.html', inject: true, }), ], module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader', ], }, { test: /\.(png|svg|jpg|gif)$/, use: [ 'file-loader', ], }, ], }, };
Add the command to start devServer in package.json. --open
is to let Webpack automatically open the browser for us and browse directly to http://localhost:[port].
{ "name": "WebpackExample", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "build": "webpack", "start": "webpack-dev-server --open" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "clean-webpack-plugin": "^3.0.0", "css-loader": "^3.6.0", "file-loader": "^6.0.0", "html-webpack-plugin": "^4.3.0", "style-loader": "^1.2.1", "webpack": "^4.43.0", "webpack-cli": "^3.3.12", "webpack-dev-server": "^3.11.0" }, "dependencies": { "lodash": "^4.17.15" } }
Finally, let’s run devServer. Modifing the string of “Hello Webpack”, you can see it immediately refresh the screen!
WebpackExample % npm run start
TypeScript
Finally, if you want to use TypeScript to develop your project, you can refer to the following article, which explains how to add ts-loader.
Conclusion
Although we have introduced many features of Webpack. However, it has much more features than these, and this article can only give you a general idea of Webpack. With plugins and loaders, you can expand the functionality of Webpack, and you can also develop it yourself. Although we may not actually build our own Webpack project, if you are a web developer, you will definitely use React/Angular/Vue.js. They all use Webpack to bundle projects. Understanding Webpack can give us a better understanding of these frameworks.