Webpack is a tool that has received much attention in recent years, and it can now be used in almost every project. Understand it.
- What is webpack?
- Install webpack
- Webpack configuration
- Entry point
- Output
- Loader
- Plug-in
- Webpack mode
- Run webpack
- Observe changes
- Process the image
- Process your SASS code and convert it to CSS
- Generate source map
What is webpack?
Webpack is a tool that allows you to compile JavaScript modules, also known asModule Bundler.
Given a large number of files, it will generate one (or several files) to run your application.
It can perform many operations:
- Help you bundle resources.
- Monitor the changes and rerun the task.
- Babel can be converted and run to ES5, allowing you to use the latest versionJavaScriptFeatures without worrying about browser support.
- Can convert CoffeeScript to JavaScript
- You can convert embedded images into data URIs.
- Allows you to use require() for CSS files.
- Can run the development web server.
- Can handle hot module replacement.
- The output file can be divided into multiple files to avoid loading huge js files when the homepage hits.
- Can be executedShake the tree.
Webpack is not limited to the front-end use, it is also very useful in the back-end Node.js development.
The predecessors of Webpack and the tools that are still widely used include:
- Grunt
- broccoli
- Gulp
These have many similarities with what Webpack can do, but the main difference is that these are calledTask runner, And webpack was born as a module bundler.
It is a more targeted tool: you can specify the entry point of the application (it can even be an HTML file with a script tag), and then Webpack will analyze these files and take all the content needed to run the application Bundled in a JavaScript output file (or more) files (if you use code splitting).
Install webpack
Webpack can be installed globally or locally in each project.
Global installation
This is the method of global installation in the following wayyarn:
yarn global add webpack webpack-cliwith npm:
npm i -g webpack webpack-clionce this is done, you should be able to run
webpack-cli

Local install
Webpack can be installed locally as well. It’s the recommended setup, because webpack can be updated per-project, and you have less resistance to using the latest features just for a small project rather than updating all the projects you have that use webpack.
With Yarn:
yarn add webpack webpack-cli -Dwith npm:
npm i webpack webpack-cli --save-devOnce this is done, add this to your package.json
file:
{
//...
"scripts": {
"build": "webpack"
}
}
once this is done, you can run webpack by typing
yarn build
in the project root.
Webpack configuration
By default, webpack (starting from version 4) does not require any config if you respect these conventions:
- the entry point of your app is
./src/index.js
- the output is put in
./dist/main.js
.
- Webpack works in production mode
You can customize every little bit of webpack of course, when you need. The webpack configuration is stored in the webpack.config.js
file, in the project root folder.
The entry point
By default the entry point is ./src/index.js
This simple example uses the ./index.js
file as a starting point:
module.exports = {
/*...*/
entry: './index.js'
/*...*/
}
The output
By default the output is generated in ./dist/main.js
. This example puts the output bundle into app.js
:
module.exports = {
/*...*/
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js'
}
/*...*/
}
Loaders
Using webpack allows you to use import
or require
statements in your JavaScript code to not just include other JavaScript, but any kind of file, for example CSS.
Webpack aims to handle all our dependencies, not just JavaScript, and loaders are one way to do that.
For example, in your code you can use:
import 'style.css'
by using this loader configuration:
module.exports = {
/*...*/
module: {
rules: [
{ test: /\.css$/, use: 'css-loader' },
]
}
/*...*/
}
The regular expression targets any CSS file.
A loader can have options:
module.exports = {
/*...*/
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
]
}
/*...*/
}
You can require multiple loaders for each rule:
module.exports = {
/*...*/
module: {
rules: [
{
test: /\.css$/,
use:
[
'style-loader',
'css-loader',
]
}
]
}
/*...*/
}
In this example, css-loader
interprets the import 'style.css'
directive in the CSS. style-loader
is then responsible for injecting that CSS in the DOM, using a <style>
tag.
The order matters, and it’s reversed (the last is executed first).
What kind of loaders are there? Many! You can find the full list here.
A commonly used loader is Babel, which is used to transpile modern JavaScript to ES5 code:
module.exports = {
/*...*/
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
/*...*/
}
This example makes Babel preprocess all our React/JSX files:
module.exports = {
/*...*/
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: 'babel-loader'
}
]
},
resolve: {
extensions: [
'.js',
'.jsx'
]
}
/*...*/
}
See the babel-loader
options here.
Plugins
Plugins are like loaders, but on steroids. They can do things that loaders can’t do, and they are the main building block of webpack.
Take this example:
module.exports = {
/*...*/
plugins: [
new HTMLWebpackPlugin()
]
/*...*/
}
The HTMLWebpackPlugin
plugin has the job of automatically creating an HTML file, adding the output JS bundle path, so the JavaScript is ready to be served.
There are lots of plugins available.
One useful plugin, CleanWebpackPlugin
, can be used to clear the dist/
folder before creating any output, so you don’t leave files around when you change the name of the output file:
module.exports = {
/*...*/
plugins: [
new CleanWebpackPlugin(['dist']),
]
/*...*/
}
The webpack mode
This mode (introduced in webpack 4) sets the environment on which webpack works. It can be set to development
or production
(defaults to production, so you only set it when moving to development)
module.exports = {
entry: './index.js',
mode: 'development',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js'
}
}
Development mode:
- builds very fast
- is less optimized than production
- does not remove comments
- provides more detailed error messages and suggestions
- provides a better debugging experience
Production mode is slower to build, since it needs to generate a more optimized bundle. The resulting JavaScript file is smaller in size, as it removes many things that are not needed in production.
I made a sample app that just prints a console.log
statement.
Here’s the production bundle:

Here’s the development bundle:

Running webpack
Webpack can be run from the command line manually if installed globally, but generally you write a script inside the package.json
file, which is then run using npm
or yarn
.
For example this package.json
scripts definition we used before:
"scripts": {
"build": "webpack"
}
allows us to run webpack
by running
npm run build
or
yarn run build
or
yarn build
Watching changes
Webpack can automatically rebuild the bundle when a change in your app happens, and keep listening for the next change.
Just add this script:
"scripts": {
"watch": "webpack --watch"
}
and run
npm run watch
or
yarn run watch
or
yarn watch
One nice feature of the watch mode is that the bundle is only changed if the build has no errors. If there are errors, watch
will keep listening for changes, and try to rebuild the bundle, but the current, working bundle is not affected by those problematic builds.
Handling images
Webpack allows us to use images in a very convenient way, using the file-loader
loader.
This simple configuration:
module.exports = {
/*...*/
module: {
rules: [
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
}
]
}
/*...*/
}
Allows you to import images in your JavaScript:
import Icon from './icon.png'
const img = new Image()
img.src = Icon
element.appendChild(img)
(img
is an HTMLImageElement. Check the Image docs)
file-loader
can handle other asset types as well, like fonts, CSV files, xml, and more.
Another nice tool to work with images is the url-loader
loader.
This example loads any PNG file smaller than 8KB as a data URL.
module.exports = {
/*...*/
module: {
rules: [
{
test: /\.png$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
}
}
]
}
]
}
/*...*/
}
Process your SASS code and transform it to CSS
Using sass-loader
, css-loader
and style-loader
:
module.exports = {
/*...*/
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
}
/*...*/
}
Generate Source Maps
Since webpack bundles the code, Source Maps are mandatory to get a reference to the original file that raised an error, for example.
You tell webpack to generate source maps using the devtool
property of the configuration:
module.exports = {
/*...*/
devtool: 'inline-source-map',
/*...*/
}
devtool
has many possible values, the most used probably are:
none
: adds no source maps
source-map
: ideal for production, provides a separate source map that can be minimized, and adds a reference into the bundle, so development tools know that the source map is available. Of course you should configure the server to avoid shipping this, and just use it for debugging purposes
inline-source-map
: ideal for development, inlines the source map as a Data URL
More devtools tutorials:
- Introduction to Yeoman
- Bower, the browser package manager
- Introduction to Frontend Testing
- Using node-webkit to create a Desktop App
- VS Code: use language-specific settings
- Introduction to Webpack
- A short and simple guide to Babel
- An introduction to Yarn
- Overview of the Browser DevTools
- Format your code with Prettier
- Keep your code clean with ESLint
- A list of cool Chrome DevTools Tips and Tricks
- Testing JavaScript with Jest
- How to use Visual Studio Code
- Introduction to Electron
- Parcel, a simpler webpack
- An Emmet reference for HTML
- The V8 JavaScript Engine
- Configuring VS Code
- Configuring the macOS command line
- How to disable an ESLint rule
- How to open VS Code from the command line
- How to set up hot reload on Electron