How can I provide parameters for webpack html-loader interpolation?

喜欢而已 提交于 2019-11-28 06:25:44

Solution 1

I found another solution, using html-loader with interpolate option.

https://github.com/webpack-contrib/html-loader#interpolation

{ test: /\.(html)$/,
  include: path.join(__dirname, 'src/views'),
  use: {
    loader: 'html-loader',
    options: {
      interpolate: true
    }
  }
}

And then in html page you can import partials html and javascript variables.

<!-- Importing top <head> section -->
${require('./partials/top.html')}
<title>Home</title>
</head>
<body>
  <!-- Importing navbar -->
  ${require('./partials/nav.html')}
  <!-- Importing variable from javascript file -->
  <h1>${require('../js/html-variables.js').hello}</h1>
  <!-- Importing footer -->
  ${require('./partials/footer.html')}
</body>

The only downside is that you can't import other variables from HtmlWebpackPlugin like this <%= htmlWebpackPlugin.options.title %> (at least I can't find a way to import them) but for me it's not an issue, just write the title in your html or use a separate javascript file for handle variables.

Solution 2

Old answer

Not sure if this is the right solution for you but I'll share my workflow (tested in Webpack 3).

Instead of html-loader you can use this plugin github.com/bazilio91/ejs-compiled-loader:

{ test: /\.ejs$/, use: 'ejs-compiled-loader' }

Change your .html files in .ejs and your HtmlWebpackPlugin to point to the right .ejs template:

new HtmlWebpackPlugin({
    template: 'src/views/index.ejs',
    filename: 'index.html',
    title: 'Home',
    chunks: ['index']
})

You can import partials, variables, and assets in .ejs files:

src/views/partials/head.ejs:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8"/>
  <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
  <title><%= htmlWebpackPlugin.options.title %></title>
</head>

src/js/ejs_variables.js:

const hello = 'Hello!';
const bye = 'Bye!';

export {hello, bye}

src/views/index.ejs:

<% include src/views/partials/head.ejs %>
<body>    
  <h2><%= require("../js/ejs_variables.js").hello %></h2>

  <img src=<%= require("../../assets/sample_image.jpg") %> />

  <h2><%= require("../js/ejs_variables.js").bye %></h2>
</body>

A note, when you include a partial the path must be relative to the root of your project.

mustache-loader did the work for me:

var html = require('mustache-loader!html-loader?interpolate!./index.html')({foo:'bar'});

Then in your template you can use {{foo}}, and even insert other templates

<h1>{{foo}}</h1>
${require('mustache-loader!html-loader?interpolate!./partial.html')({foo2: 'bar2'})}

You might laugh, but using default loaders provided with HTMLWebpackPlugin you could do string replacement on the HTML-partial file.

  1. index.html is ejs template (ejs is the default loader in HTMLWebpackPlugin)
  2. file.html is just an html string (loaded via html-loader also available by default with HTMLWebpackPlugin or maybe it comes with webpack?)

Setup

Just use the default ejs templating provided in HTMLWebpackPlugin

new HtmlWebpackPlugin({
    template: 'src/views/index.ejs',
    filename: 'index.html',
    title: 'Home',
    chunks: ['index'],
    templateParameters(compilation, assets, options) {
        return {
            foo: 'bar'
        }
    }
})

Here's my top level ejs file

// index.html 

<html lang="en" dir="ltr">
    <head>
        <title><%=foo%></title>
    </head>
    <body>
        <%
            var template = require("html-loader!./file.html");
        %>
        <%= template.replace('${foo}',foo); %>
    </body>
</html>

Here's file.html, which html-loader exports as a string.

// file.html 

<h1>${foo}</h1>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!