Lesson Weekend

So far we've used webpack to bundle our JavaScript and CSS files. We can also use webpack to generate HTML files for us.

Why would we do this? Well, a larger application might have many entry points. What if someone adds an entry point or changes the output configuration in webpack.config.js? Our HTML file's script tags would need to be updated, too. That might lead to errors and it's not very DRY. A bigger application could have many HTML files, all with multiple different entry points. Ideally, we should only have to update our configuration file and then webpack will handle the rest for us.

Webpack Plugins

To add this functionality to webpack, we'll use our first plugin: HtmlWebpackPlugin.

So what's the difference between a webpack loader and a webpack plugin?

  • Loaders preprocess code, generally before or during the process of creating our bundle. They work with single files.

  • Plugins are more powerful. They can modify and work with the entire bundle, so they generally run after the bundle has been created.

Note: You can use webpack just fine at this point without knowing the difference between loaders and plugins. If this is still confusing, feel free to keep on moving.

Before we install the plugin, let's move our index.html file from the dist folder to the src folder. From now on, we'll let webpack handle bundling our HTML and outputting it to dist.

Now let's add another dev dependency with npm:

$ npm install [email protected] --save-dev

Let's also update webpack.config.js:

webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/main.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Ping Pong',
      template: './src/index.html',
      inject: 'body'
    })
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      }
    ]
  }
};
  • First we require html-webpack-plugin and make it available to our application.

  • Next we add a section to our configuration file for plugins.

  • Finally, we instantiate a new HtmlWebpackPlugin. Our instantiated plugin is taking three arguments:

    • title: This will be the title of our bundled HTML file.
    • template: This is the HTML file we'll bundle. Here we specify that it should be the index.html file we just moved to the src folder. If we didn't specify a template, then webpack would just generate a file with a <head> and <title> and <script> tags.
    • inject: This is a nice little option; webpack will inject our script at the bottom of our HTML for us. It's yucky to put script tags in the body when we're writing code because it's hard to read and mixes HTML and JS, which are separate concerns. However, our code will be more performant in production if we put our script tags there. Webpack gives us the best of both worlds. We can write clean code when we're developing and then let webpack make it more performant for us by moving the script tags to the bottom of the HTML.

Before we $ npm run build our application again, let's remove the <script> tag currently linking our bundled JavaScript from index.html. We no longer need it because webpack now will add it for us.

Now run $ npm run build. Webpack will add index.html to our dist folder. If you take a look, you'll see that webpack has added a script tag for our bundled JavaScript to the bottom of our HTML file.