Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

In the html-loader documentation there is this example

require("html?interpolate=require!./file.ftl");  <#list list as list>     <a href="${list.href!}" />${list.name}</a> </#list>  <img src="${require(`./images/gallery.png`)}"> <div>${require('./components/gallery.html')}</div> 

Where does "list" come from? How can I provide parameters to the interpolation scope?

I would like to do something like template-string-loader does:

var template = require("html?interpolate!./file.html")({data: '123'}); 

and then in file.html

<div>${scope.data}</div> 

But it doesn't work. I have try to mix the template-string-loader with the html-loader but it doesn't works. I could only use the template-string-loader but then the images in the HTML are not transformed by webpack.

Any ideas? Thank you

like image 623
Patrick Lafrance Avatar asked Sep 07 '16 15:09

Patrick Lafrance


People also ask

How does HTML Webpack plugin work?

The HtmlWebpackPlugin simplifies creation of HTML files to serve your webpack bundles. This is especially useful for webpack bundles that include a hash in the filename which changes every compilation.

What is the use of HTML loader?

The html-loader defination says that it exports html as String (What does it mean). it also says that every loadable attributes (for example <img src="image. png" is imported as require('./image. png') ,and you may need to specify loader for images in your configuration ( file-loader or url-loader ), What does it mean.


2 Answers

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.

like image 53
pldg Avatar answered Sep 17 '22 23:09

pldg


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> 
like image 40
potench Avatar answered Sep 18 '22 23:09

potench