Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does html-webpack-plugin work with html-loader?

I thought a loader is invoked only when some resource is imported or required somewhere and the resources match with such a loader.

But in the following codes, no html file is imported anywhere but the html-loader is still necessary to make the compilation pass because of the underscore template stuff in the html.

So I have the following questions:

  1. When does the html-loader come to play? After or before the bundle is generated?
  2. Why does webpack invoke the html-loader? Because of the template setting in the plugin?
  3. Does the plugin use the output of the loader? But the output is just a string and how could it make a difference?

    //webpack.config.js
    const webpack = require('webpack');
    const path = require('path');
    const htmlPlugin = require('html-webpack-plugin');
    module.exports = {
        entry: {
            a: './a.js'
        },
        output: {
        filename: '[name].[chunkhash].js',
        chunkFilename: '[name].[chunkhash].js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [
        {
          test: /\.html$/,
          loader: "html-loader"
        }
        ]
    },
    plugins: [
            new htmlPlugin({
            template:path.resolve(__dirname,'index.html')
    
        })
    ]
    };  
    
    //index.html
        <!DOCTYPE html>
        <html>
        <head>
            <title></title>
        </head>
        <body>
            <script id="item-template" type="text/template">    
            <label><%= title %></label>
          </script>
    
        </body>
        </html>
    
like image 929
Shawn Chen Avatar asked Dec 27 '17 17:12

Shawn Chen


2 Answers

As you said, Webpack only knows about files when you are 'importing' them, otherwise it doesn't know.

However, Webpack first comes into contact with your html file via html-webpack-plugin. You are probably using html-webpack-plugin for templating reasons. I am using it purely to allow webpack to insert the generated JS and CSS bundle into the html automatically. My bundle file names contain "hashes" (e.g. bundle.b88ef660a5aa8442f616.js). I don't want to be doing this by hand.

At this point, html-loader has nothing to do with html-webpack-plugin. The reason why you might additionally use html-loaderis explained below.

What if your template contains images? What some people do (and it's the wrong thing to do) is use copy-webpack-pluginto copy the images folder into the output/dist folder and reference any images in the html relative to that folder. This is wrong because you images are bypassing webpack and losing on webpack benefits like adding hashing to image names, optimising images, tree shaking, etc. If you do this, webpack has no idea about your images and you have to manually look after your images folder.

The 'proper' way is to let webpack know about your image dependancies by 'requiring' the images. So instead of <img src="./img/my-image.jpg"> in the html, you should write <img src="${require(./img/my-image.jpg)}" />. BUT changing all your images references to the require version is cumbersome, so that's when you use the html-loader, it will do that automatically for you.

This may cause an error immediately. The error will be something along the lines of Module parse failed: Unexpected token (1:0) You may need an appropriate loader to handle this file type.

All that error means is that webpack doesn't know how to handle images. And to tell webpack how to handle something it doesn't know about, you need to use the appropriate loader. In this case, file-loader.

Above is the most common use that I have come across of using webpack-html-plugin and html-loader.

like image 161
user1275105 Avatar answered Nov 12 '22 19:11

user1275105


I will try to answer you questions at my best:

There is no dependency from HtmlWebpackPlugin to the html-loader.

  1. The html-loader comes into play when webpack detects the following in your javascript: require('./app.component.html'), because you have the following test: /\.html$/. The default action is to put the html from that file in the place where the require is stated.

  2. The html-loader is independent from HtmlWebpackPlugin.

  3. As far as I know, no.

I hope you will understand webpack a little bit better with this answer.

like image 36
Cees Avatar answered Nov 12 '22 17:11

Cees