webpack introduction

Webpack: An Introduction

Before coming to the discussion about Webpack, let’s discuss how web development has evolved over the past few years and why we even need a build tool for something like Javascript.

The only way to load javascript in an HTML document is to add a script tag. So if a developer wants to include a javascript file, he/she has to add a script tag in the HTML to include it. Since web apps are becoming fairly common these days, it is common to see javascript code cross 10,000 lines. Putting all of this code in a single file can bring in problems related to scope, performance, maintainability, and security.

Clearly, we want to write as much of modular javascript as we can. The problem with that is that you can end up having thousands of files and you can only download a limited number of scripts in a browser at a time.

The solution to that can be splitting files into modules which can be concatenated later. That is when module systems came into the picture. A problem when fetching modules on the browser is that you need to ensure the order in which modules are loaded. If one module depends on the other, the other module has to be loaded before this one. This was exactly what brought in a line of tools like gulp, grunt, broccoli etc.

But there still existed problems such as dead code elimination, full rebuilds on changing a single file, lazy loading files. This is where bundlers and loaders started gaining popularity.

The next question that comes to mind then is

Why do I need Webpack?

Webpack supports all javascript module formats (ES Modules, commonjs etc.). It also allows you to use not only javascript, but it also supports other processors for CSS (SASS, LESS, Stylus), HTML, assets etc.

So it is a module bundler that allows you to use any module format and compiles them for the browser. (It even supports Web assembly modules). It also allows you to create code splitted bundles at build time (which brings in a lot of static analysis optimizations) that can be  lazily loaded later.

Webpack also has a rich vast ecosystem and a lot of the major CLI’s such as Angular CLI, Create React App, Vue use it. It is super extensible and has a vast amount of plugins for different kinds of workflows.

Other features of webpack include concatenation, minification, hot module replacement, converting/transpiling files from one format to another, linting files etc.

Webpack can be considered as a specialized task runner which optimally processes input files into output files. It does so by using making use of components called loaders. For installing Webpack, you need to have NPM installed. After that, as with all node modules, you do a npm install webpack -g for installing it globally. You can then use the CLI for transpiling files, but since projects are more complex than just putting files together and passing them as parameters in the command line, we would mostly use a config file for running Webpack. For doing so, we need to create a webpack.config.js file in our project’s root directory. A configuration file in itself is a module, so it needs to have a module.exports statement. The object being returned should have two important keys for a basic build, namely the entry key which is a string or array of strings that point to the file(s) that we need to include in our build. The other key which we need to specify is the output key which is an object that can contain the directory to output to, the filename etc. So a basic configuration file which converts a single app.js file to a bundle.js file would like the following:

module.exports = {
    entry : "./app.js",
    output: {
        filename: "bundle.js"
    }
}

The above file seems like not much is happening, and that we are just converting one app.js file to another bundle.js file which is meaningless. But even this basic configuration will make Webpack look inside the app.js files, and if you have required or imported other modules inside it, then Webpack will go and fetch those dependencies as well. All this is done with Webpack maintaining a dependency graph for the developer so that they do not focus on maintaining the order of importing modules. So a lot will be happening in this scenario if you have referenced other modules in your app.js file. But many times, you need to process multiple files. In that case, the entry key will have an array of files as its value. That is, the line will now become

entry: ["./app.js","./file.js"]

Using the above configuration, you can create a very basic build for your project. But what makes Webpack a flexible build tool is the capability of extending it by making use of loaders. By using loaders, you can go beyond the processing, minification and concatenation of javascript files of the build tool. I will take the example of babel loader which is the most common transpiler for converting ES6 (or ES2015) code into ES5. I already assume you have the babel cli, babel preset es2015 installed. If not, install them using NPM using the command npm install babel-cli babel-preset-es2015 babel-loader --save .You also need to install babel loader which plugs babel in as a loader for Webpack. Also, for transpiling, you need a .babelrc file in your project directory. The file contents will be an object containing the presets key and its value set to an array containing an item value es2015. Next, for the configuration of Webpack, we will add a module key in the config which will have the following object:

module.exports = {
    entry : "./app.js",
    output: {
        filename: "bundle.js"
    },
    rules: {
        loaders: [
            {
                test: /\.js/,
                exclude: /node_modules/,
                loader: "babel-loader"
            }
        ]
    }
}

The above configuration adds the babel loader to our build pipeline. The babel loader runs on all javascript files except for those that are present in the node_modules folder (as specified in the RegEx in the test and exclude sections). And this is all you need to do to add a loader to Webpack! Similarly, you can add a preloaders key in the module object to add preloaders to your build. They can be useful for linting purposes and jshint is usually used for this purpose.

After creating your configuration file, all you need to do is type in “webpack” in your command line. The bundler will then do everything that you had specified in the config file. You can also run it in watch mode by using “webpack -w”. This will re-run the build everytime you make changes to a file in the directory.

And if you wish to serve your files over HTTP using webpack, you can install webpack-dev-server for doing so.

There are a lot of other nice features in Webpack such as hot module replacement, adding CSS to modules, building multiple bundles, chaining loaders, adding plugins etc.

This post should be enough to get you started and you can play with other features. If you want a more detailed post, do let me know in the comments section below. I will write another one with some advanced builds!