Learning Webpack Concepts and Creating your Custom Webpack Plugin.
Tags: javascript, webpack, webdev, productivity
Published: 2020-11-09 22:07:18

In this post I will be covering the core concepts of Webpack which will help us to understand the basic mechanism and give us more clarity before building our own custom webpack plugin. So let's dive into details.


##Why do we need webpack?

The tendency to write more JS code on the client side due to the enhanced browser features, faster Javascript engines and proliferation of mobile devices such as iPad has definitely shifted the trend from server side to client side development.
This leads to more Js code, modules and dependencies on the client side which will be dependent on one another. 

**For example, consider a file `index.js` which imports two other files `file1.js` and `file2.js` and `file2.js` is dependent on `file1.js`. In this case how the browser will know which file to load first such that it yields the desired result.**

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/occ3lrzmksj0xzp9txrr.png)


####Solution

Webpack!💫 

**So the next question is how webpack solves this problem for us?**

Webpack is a module bundler which builds and loads the modules  synchronously. It converts dependencies into modules and make sure to pull the dependencies and modules at the right time in the correct scope. All the dependencies and modules are loaded in one file which will be downloaded.

This is the basic explanation of what is webpack but let's find out how webpack actually does all this work.

##How webpack work on top of the hood?

In this section we will discuss the initial configuration that we will be using in the our `webpack.config.js` file to setup our client application.

* **Entry** - It is used as the entry point for its dependency graph and create module as necessary.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/iisir6ztbcxdh8s0bt2i.png)

In the above example `bootstrap.min.ts` is the first file to load and to **kick-off** your app. Webpack will use this file to build dependency graph.

* **Output** - It defines the absolute path to distribute bundles. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/kuwoly3jgib0pom8wwgu.png)

* **Loaders** - It tells the javascript how to resolve non-javascript modules after it has been used in the modules. It takes the resource file and returns the modified state.

```javascript
modules: {
    rules: {
        {
            test: /\.ts$\,
            use: 'ts-loader'
        }
    }
}
```
You can similarly have many more loaders like css, babel etc. All the files other than js are converted into javascript module in some representation by these functional transformations. You can also filter through these modules by using properties like **_exclude_, _include_, _enforce_** etc.
There is also a way to chain loaders such that loaders that perform one operation will be transformed once and then you can chain them together.

```javascript
rules: [{
    test: /\.less$\, 
    use: ['css-loader', 'style-loader', 'less-loader']
}]
```

* **Plugins** - An plugin is an ES5 class which implements an apply function and allow you to hook into the entire compilation lifecycle. The compiler uses it to emit events. It adds the new instance to the plugin key in config object.

```javascript
var HelloWorldPlugin = require('hello-world');

module.exports = {
  // ... configuration settings here ...
  plugins: [new HelloWorldPlugin({ options: true })]
};
```

This covers mainly what webpack does on top of the hood. There are multiple [https://webpack.js.org/concepts/](configurable options) which you can use while working on your applications.

##How webpack under the hood?

In this section we will discuss what is webpack's architecture and how it works as a system bundler. In order to learn this we would start with a question "What is **tapable**"?


#### Tapable 
It is the backbone of the plugin system. It allows us to mix your code with an existing class and make use of exiting functions like apply plugins parallel or apply plugins async etc, and emits events that we are listening to like the node event emitter. For example, simple basic plugin declaration would look like: 

```javascript
class BasicPlugin {
    apply(compiler) {
        compiler.apply('make', (compilation) => {
            console.log('I now have access to the compilation!!!!!!');
        });
    }
}

module.exports = BasicPlugin;
```
A Tapable instance is a class/ object that extends Tapable and something you can plug into. There are some Tapable instances which are responsible for the working of webpack.

1. **Compiler** - It is the central dispatch, it's kind of start or stop which delegates the top level events that are happening when webpack runs or finishes and it gets exposed.

2. **Compilation** - It creates and runs the dependancy graph algorithm and works as the brain behind the webpack about what it does and what happens inside the compilation.

3. **Resolver** - It justifies the term with what work it does, it majorly helps in finding files and dependencies like for example your `index.js` has imports specified with partial path or any other dependencies, resolver helps in finding the file from the information of partial file path import and build dependency graph.

4. **Module Factory** - It takes the resolved request and collects source of that file and returns Module Object.

5. **Parser** - It converts the raw source code into an AST such that it can be easily traversed. It starts by finding all require, imports and creates dependency object out of it.

6. **Template** -  It is responsible for binding data for your modules and creates code that we see in the bundle. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ivygids45ezq777yekgr.png)


To summarise the whole process.

Webpack first reads the entry point and it go through resolver to verify that it exists or not. After that it goes through our normal module object that will pass through parser. Once the parser identifies the dependency type it passes it to loader if it is a non Javascript module whereas it simply collects dependencies and attach to the modules if it is a Javascript module. We have to then again check for dependencies that exists in the module and pass it through resolver, after this the entire cycle repeats until the complete dependency graph is build.

With this you have learnt how the webpack works internally.😁 💃 

In the next post I will cover how I created my first webpack plugin to solve one of the problems which i was facing during building chrome extension.


Happy Reading! 📖