Skip to content

Latest commit

 

History

History
167 lines (122 loc) · 7.86 KB

part-08.md

File metadata and controls

167 lines (122 loc) · 7.86 KB

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:

  1. update package.json by updating devDependencies section under it by appending it html-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.

  1. update package-lock.json w.r.t changes in package.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:

  1. add following at the top of file BEFORE module.exports:
const HtmlWebpackPlugin = require('html-webpack-plugin')
  1. 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.