Lang
Blog

Introduction to Webpack — Why do we need it?

Mapping and bundling of the required modules through dependency graph!

ByPayal Mittal
August 4th . 5 min read
Introduction to Webpack — Why do we need it?

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-

What is Webpack?

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.

Key features & functionalities -

  • Rich plugin interface
  • Multiple caching levels
  • Code splitting
  • Incredibly fast on incremental compilations
  • Browser compatibility
  • Supports most of the existing libraries
  • Out-of-box support for ES2015+, CommonJS and AMD modules
  • Reduces the bundle size
  • Reduction in runtime size
  • Highly modular plugin system
  • Static code analysis
  • Cache friendly
  • Tree Shaking (Dead code elimination)
  • Hot module replacement

webpack_1.jpg

How it works?

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.

Entry:

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'
};

Output:

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.

Loaders:

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' }
]
}
}

Loaders, basically, have two properties in the configuration, that are -

  • Test: The test property determines which file(s) should be transformed.
  • Use: The use property specifies which loader will be used for that particular file.

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:

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.”

Let’s take an example of HtmlWebpackPlugin -

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.

Mode:

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'
};

webpack_2.jpg

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.

Why Webpack?

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.

  • Immediately invoked function expressions (IIFE’s): With IIFE, you can concatenate your project files together safely, no matter how big they are.
  • Automatic Dependency Collection: Unlike Task Runners, you don’t need to declare all dependencies manually with webpack. It works automatically and builds a dependency graph according to the application-needs of modules and what is being imported in the script.
  • ECMAScript Modules (ESM): As modules are becoming more and more like an official feature in ESM, bundling being more popular among developers and faster than the incomplete-bowser-support feature, preferred for these module implementations.
  • Code Splitting: It is yet another compelling feature of webpack that reduces the load timing. It enables you to split up your code into multiple small bundles, called ‘chunks’, that can be loaded either on-demand or parallelly.

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

Wrap Up:

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📖!!

Share:
0
+0