In this part we will work on introducing another Webpack Plugin named html-webpack-plugin
.
If you remember in previous part of the tutorial we forgot to add <link>
tag in our dist/index.html
referencing the bundled CSS generated by mini-css-extract-plugin
and because of
which our page didn't shown up as expected and we needed to get into diagnosing mode.
Forgetting minor things like those can happen during development but it should prove to be really annoying when we work on a large feature and such minor mistakes makes our work return unexpected results. So is there something available which can help us avoid such minor mistakes? Fortunately yes because we are not the first ones who has encountered this issue. The developers who were seriously disappointed with the faced issue determined themselves to build a soution which can help other developers to avoid facing the disappoinments they faced and those altruistic developers came up with HTML Webpack Plugin. First I came across this plugin while I was going through this reference and then I ended up finding this reference.
Note that if you check the plugin's documentation on the official page it says
This is a webpack plugin that simplifies creation of HTML files to serve your webpack bundles
Reading that you might get a thought then how come it will help solve the primary issue of helping us avoid manually include the CSS in our HTMl file. To answer that if you read the details under Usage section in the official documentation you should find following:
If you have multiple webpack entry points, they will all be included with script tags in the generated HTML.
If you have any CSS assets in webpack's output (for example, CSS extracted with the ExtractTextPlugin) then these will be included with tags in the HTML head.
That confirms that we have ended up with the right solution. And we get additional advantage to automatically generate one or more HTML files, generate HTML files based on a template file and other such awesome features the plugin provides.
OK so let's get to integrating it in our application.
First we install it
project_root$ npm install html-webpack-plugin --save-dev
That should do following 2 things:
- update package.json by updating
devDependencies
section under it by appending ithtml-webpack-plugin
package like following
"html-webpack-plugin": "^3.2.0",
Note: The dependencies versions are the then versions when the dependencies were installed at on this tutorial author's local machine.
- update
package-lock.json
w.r.t changes inpackage.json
Next we will update our webpack.config.js
by adding configuration for this plugin. To do that open the file in a text-editor and do following:
- add following at the top of file BEFORE
module.exports
:
const HtmlWebpackPlugin = require('html-webpack-plugin')
- add following under
module.exports.plugins
Array
new HtmlWebpackPlugin({
title: 'Hello World',
template: path.resolve(__dirname, 'src/index.html')
})
That config will use the template HTML generate a file index.html
that includes all your webpack bundles. That will be generated under folder project_root/dist
, having its title set to Hello World
. Why under folder project_root/dist
? Because that is path we have configured through Webpack's output
option.
Plugin provides various configuration options for customization. Please refer the documentation.
So after those modifications our webpack.config.js
should look like (note unchanged parts are shown as truncated with ...)
...
...
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
...
plugins: [
new MiniCssExtractPlugin(),
new HtmlWebpackPlugin({
title: 'Hello World',
template: path.resolve(__dirname, 'src/index.html')
})
],
...
...
}
Next we add our template file index.html
under project_root/src
folder. To do that first create the file
project_root$ touch src/index.html
Then open the file in a text-editor and add following content to it
<!doctype html>
<html class="no-js" lang="">
<head>
<title><%= htmlWebpackPlugin.options.title %></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
</body>
</html>
An interesting thing you can see in there is the code <%= htmlWebpackPlugin.options.title %>
. htmlWebpackPlugin.options
is a variable provided by HTML Webpack Plugin to make our templates use the values configured for the plugin in webpack.config.js
. There are other variables available too. Please refer the documentation for more details on them.
Now that we are using a template HTML file we should get rid of the index.html
we manually created under project_root/dist
in the beginning of this whole tutorial.
Now let's re-build the bundle using following command
project_root$ npm run build
That should show output like following
> hello-world-imba@1.1.0 build $project_root$
> webpack
Hash: bffcd483c63c9ae4754a
Version: webpack 4.29.0
Time: 834ms
Built at: 03/09/2019 1:14:59 PM
Asset Size Chunks Chunk Names
app.css 22.9 KiB app [emitted] app
client.js 108 KiB app [emitted] app
index.html 316 bytes [emitted]
Entrypoint app = app.css client.js
[./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {app} [built]
[./src/css/w3.css] 39 bytes {app} [built]
[./src/frontend/client.imba] 872 bytes {app} [built]
+ 14 hidden modules
Child html-webpack-plugin for "index.html":
1 asset
Entrypoint undefined = index.html
[./node_modules/html-webpack-plugin/lib/loader.js!./src/index.html] 487 bytes {0} [built]
[./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {0} [built]
[./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {0} [built]
+ 1 hidden module
Child mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!src/css/w3.css:
Entrypoint mini-css-extract-plugin = *
[./node_modules/css-loader/dist/cjs.js!./src/css/w3.css] 23.5 KiB {mini-css-extract-plugin} [built]
+ 1 hidden module
As can be seen there are three assets generated by names client.js
, app.css
, index.html
all under project_root/dist
folder as specified by our output
property in webpack.config.js
. The app.css
has been generated by the mini-css-extract-plugin
and index.html
has been generated by the html-webpack-plugin
we configured. The file name and the output folder to generate to etc should be based on default values used by it.
Now if check the project_root/dist/index.html
you should see that it has our CSS and JS bundles automatically included. That's facilitates by HTML Webpack Plugin!
Now let's start the webpack-dev-server using command
project_root$ npm run start:dev
and then open a browser window at http://localhost:8080 and you should see the the styled content. Congrats!
Now one last thing remains is to update our .gitignore
file by adding dist/index.html
because that is a bundled asset which is not intended to be pushed to our repository.
Now save the changes made in codebase and commit the changes. Note that while commiting dist/index.html
should not be committed.