Getting Started with Webpack [With Example Project]
Webpack is a module bundler that facilitates building complex JavaScript applications. It has gained serious traction since the React community chose it as its main build tool. Webpack is neither a package manager nor a task runner as it uses a different (more advanced) approach, but its goal is also to set up a dynamic build process.
Webpack works with vanilla JavaScript. You can use it to bundle the static assets of an application, such as images, fonts, stylesheets, scripts into one single file while taking care of all the dependencies.
You won’t need Webpack to create a simple app or website, for instance one that has only one JavaScript and one CSS file and a few images, however it can be a life-saver for a more complex application with several assets and dependencies.
Read Also: Getting Started with React.js
Webpack vs. task runners vs. Browserify
So, how does Webpack stack up compared to other build tools such as Grunt, Gulp, or Browserify?
Grunt and Gulp are task runners. In their config file, you specify the tasks, and the task runner executes them. The workflow of a task runner basically looks like this:
However, Webpack is a module bundler that analyzes the whole project, sets up a dependency tree, and creates a bundled JavaScript file that it serves to the browser.
Browserify is closer to Webpack than task runners, as it also creates a dependency graph but it does so only for JavaScript modules. Webpack goes one step further, and it doesn’t only bundle source code but also other assets such as images, stylesheets, fonts, etc.
If you want to know more on how Webpack compares to other build tools, I recommend you two articles:
- Andrew Ray’s Webpack: When to Use and Why on his own blog
- Cory House’s Browserify vs Webpack on freeCodeCamp (with awesome illustrations)
Four core concepts of Webpack
Webpack has four main configuration options called “core concepts” that you will need to define in the development process:
- Entry – the starting point of the dependency graph (one or more JavaScript files).
- Output – the file where you want the output to be bundled to (one JavaScript file).
- Loaders – transformations on the assets that turn them into Webpack modules so that they can be added to the dependency graph. For instance,
css-loader
is used for the import of CSS files. - Plugins – custom actions and functionalities performed on the bundle. For instance, the
i18n-webpack-plugin
embeds localization into the bundle.
Loaders work on a per-file basis before the compilation takes place. Plugins are executed on the bundled code, at the end of the compilation process.
Install Webpack
To install Webpack, open the command-line, navigate to your project folder, and run the following command:
npm init
If you don’t want to do the configuration yourself, you can make npm populate the package.json
file with the default values with the following command:
npm init -y
Next, install Webpack:
npm install webpack --save-dev
If you have used the default values this is how your package.json
file should look like now (the properties can be in a different order):
{ "name": "_tests", "version": "1.0.0", "description": "", "main": "webpack.config.js", "dependencies": { "webpack": "^3.6.0" }, "devDependencies": { "webpack": "^3.6.0" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }
Create the configuration file
You need to create a webpack.config.js
file in the root folder of the project. This configuration file has a central role, as this is where you will define the four core concepts (entry points, output, loaders, plugins).
The webpack.config.js
file holds a configuration object of which properties you need to specify. In this article, we will specify the four properties that correspond to the four core concepts (entry
, output
, module
, and plugin
), but the config object has other properties as well.
1. Create the entry point(s)
You can have one or more entry points. You need to define them in the entry
property.
Insert the following code snippet into the webpack.config.js
file. It specifies one entry point:
module.exports = { entry: "./src/script.js" };
To specify more than one entry points you can use either the array or the object syntax.
In your project folder, create a new src
folder and a script.js
file inside it. This will be your entry point. For testing purposes, just place a string inside it. I used the following one (however, you can also use a more interesting one):
const greeting = "Hi. I'm a Webpack starter project."; document.write(greeting);
2. Define the output
You can have only one output file. Webpack bundles all the assets into this file. You need to configure the output
property in the following way:
const path = require("path"); module.exports = { entry: "./src/script.js", output: { filename: "bundle.js", path: path.resolve(__dirname, 'dist') } };
The filename
property defines the name of the bundled file, while the path
property specifies the name of the directory. The example above will create the /dist/bundle.js
file.
Although it’s not compulsory, it’s better to use the path.resolve()
method when you define the path
property, as it ensures accurate module resolution (the absolute path of the output is created according to different rules in different environments, module resolution solves this discrepancy). If you use path.resolve
, you need to require the
path
Node module at the top of the webpack.config.js
file.
3. Add the loaders
To add the loaders, you need to define the module
property. Below, we add the babel-loader
that allows you to safely use the ECMAScript 6 features in your JS files:
const path = require("path"); module.exports = { entry: "./src/script.js", output: { filename: "bundle.js", path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: { loader: "babel-loader", options: { presets: ["env"] } } } ] } };
The config may seem difficult but it’s just copy-pasted from Babel loader’s documentation. Most loaders come with either a readme file or some kind of documentation, so you can (almost) always know how to configure them properly. And, the Webpack docs also have a page that explains how to configure module.rules
.
You can add as many loaders as you need, here’s the full list. Note that you also need to install each loader with npm to make them work. For the Babel loader, you need to install the necessary Node packages with npm:
npm install --save-dev babel-loader babel-core babel-preset-env webpack
If you have a look at your package.json
file, you’ll see that npm added three Babel-related packages to the devDependencies
property, these will take care of the ES6 compilation.
4. Add the plugins
To add the plugins, you need to specify the plugins
property. Plus, you also have to require the plugins one by one, as they are external modules.
In our example, we add two Webpack plugins: the HTML Webpack plugin and the Preload Webpack plugin. Webpack has a nice plugin ecosystem, you can browse the full list here.
To require the plugins as Node modules, create two new constants: HtmlWebpackPlugin
and PreloadWebpackPlugin
and use the require()
function.
const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const PreloadWebpackPlugin = require("preload-webpack-plugin"); module.exports = { entry: "./src/script.js", output: { filename: "bundle.js", path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: { loader: "babel-loader", options: { presets: ["env"] } } } ] }, plugins: [ new HtmlWebpackPlugin(), new PreloadWebpackPlugin() ] };
Just like in the case of loaders, you also have to install the Webpack plugins with npm. To install the two plugins in the example, run the following two commands in your command line:
npm install html-webpack-plugin --save-dev npm install --save-dev preload-webpack-plugin
If you check your package.json
file now, you’ll see that npm added the two plugins to the devDependencies
property.
Run Webpack
To create the dependency tree and output the bundle, run the following command in the command line:
webpack
It usually takes one or two minutes for Webpack to build the project. When finished, you’ll see a similar message in your CLI:
If everything went right Webpack created a dist
folder in the root of your project and placed the two bundled files (bundle.js
and index.html
) inside it.
Github repo
If you want to check out, download, or fork the whole project, have a look at our Github repo.
Read Also: 11 Dependency Management Tools for Web Developers