Now that you are reading this blog, we can assume that you’re most likely familiar with the term ‘webpack’. Right?
Well, it’s been almost a decade now, since the concept of ‘Module Bundling’ has been around. The first-ever bundler, i.e. RequireJS popped up in the year 2009 and then a few more names were added in the list but the one that caught the most attention was ‘Webpack’.
Here in this blog, we’ll discuss and understand its basic concepts so that you become confident enough to give it a try-
Webpack is a static module bundler for JavaScript applications (both ESM & CommonJS) which bundles multiple resources and files, not only the script but also assets like images and styles, into a single bundle.
It is a JavaScript library, built and designed by Tobias Koppers, that runs only on NodeJS version >=8.x.
“Webpack provides a powerful and rich API for customization that allows one to use webpack for any stack while staying non-opinionated about your development, testing, and production workflows.”
While processing your applications, it builds a dependency graph that maps all the modules and libraries you need for the project and generates a bundle of them.
When webpack processes your applications, it creates a dependency graph that contains all the necessary modules needed in the application and then, packs them together in a few small bundles (often one!) to be loaded by the browser.
Simple enough, isn’t it??
“The ultimate goal of webpack is to unify all different sources and module types in a way that’s possible to import everything in your JavaScript code, and finally produce a shippable output.”
Before moving further, you need to understand some of its core concepts, i.e.
Every Webpack setup contains one or more entry points that decide which module to be used by webpack to start building the internal dependency graph. Webpack figures out the other modules that depend upon the entry point whether directly or indirectly.
By default, the value of entry point is ./src/index.js, but it can be changed to any file of your choosing, for example -
module.exports = {
entry: './path/to/my/entry/file.js'
};
As the webpack creates bundle files, now the question is where to put these bundles. These created bundles are written on disk and named at the output point.
The main output file is written as ./dist/main.js and other generated files can be added to the ./dist directory. The location of output is same as that of the entry point.
You can also specify an output.filename in your configuration to use for the output file, as given here-
const path = require('path');
module.exports = {
entry: './path/entry/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'webpack_bundle.js'
}
};
In this example, we have used the output.path and output.filename to tell webpack the bundle name and the location we want it to be put at. So, webpack emits the final bundle at dist/webpack_bundle.js.
Webpack can only process JSON and JavaScript files so, you’ll need a way to import other types of files. That’s when ‘Loaders’ play their role.
It gives webpack the ability to import .css, .svg and other files and process them- which starts with downloading loaders. For example, to import .css and .svg files, we’ll install css-loader and svg-inline-loader respectively -
npm install css-loader --save-dev
npm install svg-inline-loader --save-dev
Now, we will add them to our webpack configuration -
// webpack.config.js
const path = require('path');
module.exports = {
entry: './app/index.js',
module: {
rules: [
{ test: /\.svg$/, use: 'svg-inline-loader' },
{ test: /\.css$/, use: 'css-loader' }
]
}
}
Not only loaders allow to import different file types but also do a lot of other things such as running transformations on the code. These transformations are made in the individual files before they turned into bundles.
Plugins are a very important part of the webpack ecosystem. While loaders transform certain module types, plugins handle other tasks that loaders cannot, like asset management, bundle optimization, and injection of environment variables.
A webpack plugin is a JavaScript object that works on an apply method, which, when called by the compiler, gives access to the entire compilation lifecycle. Unlike loaders, plugins perform their tasks after the generation of bundles.
“You can consider plugins as a more free, powerful, and less-restrictive version of loaders.”
As we know that webpack is known for its ability to generate a single bundle out of multiple individual files that we can further use inside the main index.html page.
Here, HtmlWebpackPlugin generates an index.html page, place it inside the directory where the bundle was put and references the newly generated bundle by including a <script> tag automatically.
We can install it from npm, as given under -
npm install html-webpack-plugin --save-dev
Now, we create a plugins array in the configuration to use the plugin -
const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
const webpack = require('webpack'); //to access built-in plugins
module.exports = {
module: {
rules: [
{ test: /\.txt$/, use: 'raw-loader' }
]
},
plugins: [
new HtmlWebpackPlugin({template: './src/index.html'})
]
};
This was just one example, webpack provides many other plugins for different purposes.
There are basically three mode-configurations namely, development, production or none. These modes enable the optimization options respective to each mode. The details are given in the below image-
If not mentioned specifically then it takes production as default value-
module.exports = {
mode: 'production'
};
In short, the whole process starts with webpack grabbing the entry point at ./app/index.js to create the dependency graph. It transforms the code as mentioned in the loader and adds it to the bundle. The final bundle is relocated at the output point, i.e. dist/index_bundle.js.
Before webpack, running JavaScript on web browsers was an issue. No, it wasn’t impossible, just difficult. Either you could create a script for each functionality, which was hard to scale, or you could choose to use a big .js file to store the entire code, which was a big problem in terms of size, readability, and management. Webpack solved this problem by providing IIFEs for large projects.
Though CommonJS is a good solution for NodeJS projects, there are many problems with it, such as- no browser support, slow loading, no live bindings, synchronous module resolution, and no module support, thus came into role were bundlers like webpack.
In order to get started with webpack, you would need to install two packages, i.e. webpack, webpack dev server and webpack CLI -
npm install webpack webpack-dev-server webpack-cli --save-dev
It’s like a boon to have something like webpack which not only takes care of application performance and load times but also keeps adding or improving new features to deliver a wonderful experience to its users and their projects.
After reading about bundling, its worth to know how to achieve the same high performance with unbundled development in another blog.
Happy reading📖!!