How does html-webpack-plugin work with html-loader?
Asked Answered
G

2

25

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>
    
Grovel answered 27/12, 2017 at 17:21 Comment(3)
I was curious about this myself, then I checked out the html-webpack-plugin's documentation in detail. Check this link out in particular: github.com/jantimon/… Seems like when using the template field, our template loader, i.e. html-loader is invoked.Pursuer
Please checkout my answer and accept it if it makes sense to you.Unroot
This <label><%= title %></label> doesn't work when using html-loader with html webpack plugin, anybody figured out a workaround?Pickett
U
34

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.

Unroot answered 6/7, 2019 at 23:1 Comment(1)
This has been extremely helpful, thank you very much. One last question, if I use html-loader for my "shortcut icon" and "apple-touch-icon", is there a way to create a manifest.json on the fly with the names of the images html-loader has created? Again thank you and regardsPansypant
R
5

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.

Roadside answered 12/1, 2018 at 10:12 Comment(6)
Can you explain the "require('./app.component.html')" stuff a little further?Grovel
I will try to explain this in my own words. Webpack is 'indexing' your javascript and when it finds a require it let node pick the file for webpack and present it as a string to webpack, so webpack can integrate it in it's pipeline. Also, when webpack finds a require, it also try to find a loader that could be asociated with it to do some post processing (like the regex of a loader). Did this make sense to you?Roadside
Your comment makes sense to me. But my javascript file doesn't include anything like require("xxx.html") as I stated early in my question. The question is why my project still needs a html-loader to compile.Grovel
That is what I did not test before.. maybe for the html files (without the require)? Or it has some kind of strangled dependency?Roadside
In my case the following line invokes the html-loader: <img src="../src/images/lion.png">Password
@Roadside - how do you user require with a variable? ie my img src is in obj slide.src but require(slide.src) throws an error. thanks.Mime

© 2022 - 2024 — McMap. All rights reserved.