jantimon/html-webpack-plugin

Using a html loader: raw-loader vs asset/source does not give the same output

PierBJX opened this issue ยท 7 comments

Current behaviour ๐Ÿ’ฃ

Using html-webpack-plugin with a loader for html does not give the same output if I use the loader raw-loader or the type asset/source.

With the raw-loader, I have a classic index.html corresponding to the template I provide. However, if I use the asset/source, I have this kind of output in my index.html:

var _ = non_webpack_require("C:\Users...\node_modules\lodash\lodash.js");module.exports = function (templateParams) { with(templateParams) {return (function(data) { var __t, __p = ''; __p += '<!doctype html>Webpack App'; return __p })();}}

A discussion has been already opened on webpack github and the problem is with html-webpack-plugin. Find the discussion here.

Expected behaviour โ˜€๏ธ

We should have the same output as it is mentioned in the documentation.

Reproduction Example ๐Ÿ‘พ

You can find this repo which reproduces the issue. Just switch between the raw-loader and the asset/source.

Environment ๐Ÿ–ฅ

Node.js v14.17.5
win32 10.0.18363
html-webpack-plugin 5.5.0
webpack version 5.64.4

The html-webpack-plugin allows to use any loader - however if no loader is configured it provides a default loader..

This allows using an ejs like syntax without configuration.

E.g.: <%= title %>

The problem you describe could be caused by the fact that the current fallback loader is not capable of detecting asset/source..

The code for that part is here: https://github.com/jantimon/html-webpack-plugin/blob/main/lib/loader.js

There are two possible solutions:

  1. rename your index.html to index.ejs so it doesn't conflict with your html settings
  2. try to find out how we might add support for asset/source and create a pull request

Same problem here for .master files (ASP.Net Framework).
.master files starts with <%@ Master Language... which interferes with ejs syntax, so cant work.
try to use assets/source but it wont get it.

 {
      test: /\.master$/,
      type: 'asset/source',
  },

Of course this also wont work

 new HtmlWebpackPlugin({
            template: "!!asset/source!" + path.resolve(__dirname, '../MasterPageTemplate.master'),
            filename: 'MasterPage.master'
        }),

Raw-loader are deprecated in 5 so i never try it

I ran into this issue as well, as I'm upgrading from webpack 3 to webpack 5 and am switching from html-loader to asset/source for HTML files.

The issue comes from asset/source not being visible in the list of loaders, so when HTMLWebpackPlugin introspects the loader list, it can't find one. I was able to trick HTMLWebpackPlugin with a one-line passthrough loader:

html-hack.js

module.exports = (source) => source;

webpack.config.js

module.exports = {
  // ...
  plugins: [
    new (require("html-webpack-plugin")(),
  ],
  module: {
    rules: [
      { test: /src\/index.html/, use: [require.resolve('./html-hack')],
      { test: /.html/, type: 'asset/source' },
    ],
  }
};

I see two solutions:

  • HTMLWebpackPlugin could add an option to suppress loader detection. Based on the code, this might be as simple as adding if (options.detectLoader === false) return source to lib/loader.js and updating the readme.
  • Webpack would need to add a way to detect that a file was being treated as asset/source, and then HTMLWebpackPlugin could leverage that mechanism.

The first option seems the most plausible in the short term, as it's hard to say how difficult the second would be to implement.

 {
                test: /\.html$/,
                exclude: /index\.html/,
                type: 'asset/source'
 },

Should resolve the issue

I could not get it working..

do you have any stackblitz with solution?

I trying to leave raw-loader as of angular v16, but need html to be imported as raw for achieving template concatenation .. It works on angular v15)
@component{ ... ommited
template: ${templateA} ${templateB}

I could not get it working..

do you have any stackblitz with solution?

I trying to leave raw-loader as of angular v16, but need html to be imported as raw for achieving template concatenation .. It works on angular v15) @component{ ... ommited template: ${templateA} ${templateB}

Here below is my html loading snippet:
Webpack

const HtmlWebpackPlugin = require("html-webpack-plugin");
const buildPath = path.resolve(__dirname, "../build/");

{
                test: /\.([cm]?ts|tsx)$/, 
                use: [
                    "ts-loader",
                    "angular2-template-loader"
                ],
                exclude: [/node_modules/]
            },
            {
                test: /\.html$/,
                exclude: /index\.html/,
                type: 'asset/source'
            }

plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "../src/index.html"),
            filename: "index.html",
            showErrors: true,
            path: buildPath,
            hash: true
        })
    ]

Component:

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html'
})

@PureIso tks for the info.

However it didnt worked for my scenario.

Could you please take a look here, at the issue and stackblitz.

angular/angular#51805 (comment)

how to accomplish that?

tks