Building your own Webpack Plugin
Tags: webpack, webdev, javascript, showdev
Published: 2020-11-18 11:44:37

In the last post I discussed about the bundling and architecture of Webpack. In this post I would be focussing on building webpack plugins and how it can help you to solve your bundling problems. Webpack is built on plugin system which is used in webpack configurations and helps us in extending webpack's implementation which cannot be achieved by loaders and parsers.

I will be taking a simple example of a plugin which takes few arguments and prints them when webpack's lifecycle hooks are emitted. So let's begin building our own webpack plugin.


##Steps

* Create a project named my-first-webpack-plugin and install webpack in it.

```shell
mkdir my-first-webpack-plugin
npm init -y
npm install webpack webpack-cli --save-dev
```

* Create a file `my-first-webpack-plugin.js` and create a class defining your plugin properties. This will bind your plugin with the lifecycle hooks of webpack.

```javascript
class MyFirstWebpackPlugin {
    constructor(options) {
        this.options = options;
    }
    apply(compiler) {
        console.log("My First webpack plugin");
    }
};

module.export = MyFirstWebpackPlugin;
```
This plugin will print the statement when the webpack runs.

* You can include this plugin in your `webpack.config.js` in the following way.

```javascript
const myFirstWebpackPlugin = require("./my-first-webpack-plugin.js");

module.exports = {
    entry: resolve(__dirname, "src/index.js"),
    output: {
        filename: "bundle.js"
    },
    plugins: [new myFirstWebpackPlugin()]
};
``` 

* This is very basic plugin which logs the statement. We can customise this plugin by passing some options.  

```javascript
class MyFirstWebpackPlugin {
    constructor(options) {
        this.options = options || {
            env: "dev"
        };
    }
    apply(compiler) {
        console.log("My First webpack plugin");
    }
};
```
* The plugin in the `webpack.config.js` would be passed with arguments.

```javascript
plugins: [
    new myFirstWebpackPlugin({
        env: "staging"
    })
]
```
* We have our plugin ready let's modify by printing the statement when the `compiler.hooks.done` is emitted.

```javascript
apply(compiler) {
    compiler.hooks.done.tap("MyFirstWebpackPlugin", (stats) => {
        console.log(`My first webpack plugin is running on ${this.options.env}`)
        console.log("stats", stats);
    })
}
```
**Stats** here will show a large object with every possible detail about the compilation and the file available for that hook.

The **Tapable** instance on which webpack is based has different parts and each part has different hooks associated with it.

###Compiler Hooks
There are many other hooks like **run, emit, beforeRun** and [many other](https://webpack.js.org/api/compiler-hooks/) with which we can bind our plugins. Hooks extends the Tapable class in order to register and call plugins. The compiler module is the main engine that creates compilation instance with all options passed to it, most of the user facing plugins are first registered on compiler.

###Compilation Hooks
Compilation helps in **loading, sealing, optimising, chunking, hashing and restoring the modules**. The compilation also extends Tapable and provides lifecycle hooks. It can be used to change modules before the module is build, rebuild or after successful built of module [etc](https://webpack.js.org/api/compilation-hooks/)

###Javascript Parser Hooks
Similarly there is Javascript Parser Hooks which is **used to parse each module processed by webpack**. It extends Tapable and can be used by your custom plugin to enhance the parsing process. You can find more about the Parser hooks [here](https://webpack.js.org/api/parser/)

Yay!!!! :tada:
With this you have learnt how to create your custom webpack plugin.

I have created a custom plugin to solve one of the problems which I faced while working on chrome extension. I have to repeat series of manual process when I was trying to deploy my extension on web store for different environments. Every time I have to minify js files, create a zip file of source code and change the version in the `manifest.json` file. Creating webpack plugin helped me to automate the process and learn about the bundling process and working of webpack and its architecture.

You can have a look at the plugin on GitHub and can use it in your project by installing it using the following command.

```shell
npm i extension-build-webpack-plugin
```
{% github Jasmin2895/extension-build-webpack-plugin %}

Happy Reading!