July 23, 2018











Hello! Today we introduce the concept of plugins. They differ from loaders in a way that they can perform a wider range of tasks. Basically, they do anything else, that loaders can’t do. While loaders are tied to a certain type of files, plugins can be more generic. This time we will learn what purpose does loaders serve and how to use them. This will be covered using some real-life examples such as generating HTML files with all our assets linked and extracting our CSS to separate files.

Webpack 4 course: plugins. How to use them?

The most basic way to use loaders is to put them in the plugins property of our configuration. You need to create an instance of a plugin by calling it with the new operator.

If you would like to know more about the new keyword and the prototypes, check out Prototype. The big bro behind ES6 class

html-webpack-plugin

Manually adding all JavaScripts file to your HTML can be cumbersome. Thankfully, you don’t need to do that! A very helpful plugin here is the HtmlWebpackPlugin.

1 npm install html - webpack - plugin

It is very easy to use it:

webpack.config.js

1 2 3 4 5 6 7 const HtmlWebpackPlugin = require ( 'html-webpack-plugin' ) ; module . exports = { plugins : [ new HtmlWebpackPlugin ( ) ] } ;

It will create the index.html file for us and drop it in the dist directory. Our output JavaScript code will be linked at the end of the <body> tag.

index.html

1 2 3 4 5 6 7 8 9 <!DOCTYPE html> <html> <head> <meta charset = "UTF-8" > <title> Webpack App </title> </head> <body> <script type = "text/javascript" src = "main.js" > </script> </body> </html>

It will come in handy especially when the number of your files will grow since you would have to keep track of them and add all of them to the HTML file.

Another important thing to note here is that your filenames might change due to the usage of hashes. It makes the HtmlWebpackPlugin even more useful because you don’t need to keep track of the filenames. This mechanism was introduced to handle the way that browsers approach caching. We will cover that topic more in upcoming parts of the course.

Passing options to plugins

You can pass additional options to plugins. An example of it is passing the template to the HtmlWebpackPlugin:

webpack.config.js

1 2 3 4 5 6 7 const HtmlWebpackPlugin = require ( 'html-webpack-plugin' ) ; module . exports = { plugins : [ new HtmlWebpackPlugin ( { template : './src/index.html' } ) ] } ;

Thanks to that, instead of creating a default HTML file, it will use the one that you provide. To see more of the available options, see the repository.

Using the same plugin more than once

You may wonder why do we need to use the new keyword every time that we use a plugin. This due to the fact that you can use the same plugin more than once.

When creating a multiple page application, you might want to output more than one HTML file.

If you would like to know more about the entry and output and how to use them to create multiple page applications, check out the first part of this course.

This can be done by using the HtmlWebpackPlugin several times.

webpack.config.js

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 const HtmlWebpackPlugin = require ( 'html-webpack-plugin' ) ; module . exports = { entry : { one : './src/one.js' , two : './src/two.js' , } , output : { filename : '[name].bundle.js' , path : path . resolve ( __dirname , 'dist' ) } , plugins : [ new HtmlWebpackPlugin ( { filename : 'one.html' , template : './src/one.html' , chunks : [ 'one' ] } ) , new HtmlWebpackPlugin ( { filename : 'two.html' , template : './src/two.html' , chunks : [ 'two' ] } ) ] } ;

The instance of the plugin will match the entry point based on the chunks array. Running the configuration above will result in files: one.html, two.html, one.bundle.js, two.bundle.js.

Plugins working together with loaders

In the previous part of the course, we used combined css-loader and style-loader to inject our css code into the <style> tag. You might prefer to serve actual css files to your users. To do that, use mini-css-extract-plugin.

In the past, we’ve used ExtractTextWebpackPlugin to do that, but since Webpack 4 it should not be used for css. If you would like to know more, read this issue.

Here is how you do that:

1 npm install mini - css - extract - plugin

webpack.config.js

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 const HtmlWebpackPlugin = require ( 'html-webpack-plugin' ) ; const MiniCssExtractPlugin = require ( "mini-css-extract-plugin" ) ; module . exports = { module : { rules : [ { test : / \ . css $ / , use : [ MiniCssExtractPlugin . loader , 'css-loader' ] } ] } , plugins : [ new HtmlWebpackPlugin ( ) , new MiniCssExtractPlugin ( ) ] }

index.js

1 import './styles.css' ;

Thanks to the HtmlWebpackPlugin, the css files generated will be automatically linked to your HTML. You will end up with such output:

index.html

1 2 3 4 5 6 7 8 9 <!DOCTYPE html> <html> <head> <meta charset = "UTF-8" > <title> Webpack App </title> <link href = "main.css" rel = "stylesheet" > </head> <body> <script type = "text/javascript" src = "main.js" > </script> </body> </html>

Running webpack with this configuration will create a CSS file per JavaScript file containing CSS imports. Changing this behaviour requires the usage of SplitChunksPlugin which is covered in another part of the course. You can find the instructions on how to do that in the official documentation.

Summary

Today we’ve covered what the loaders are and learned some basic ways to use them. Not only that, but we’ve also learned how to pass additional options to them and how to make them work with loaders. Even though these are just examples of plugins, using others is similar. To find plugins that serve your needs, you can check the official list. There are many more and to find them, use the search engine. Since webpack itself is built on the same plugin system, it will be interesting to cover how they work under the hood. We will do this in future while implementing our own plugins.