Html-webpack-plugin: How to use without "htmlWebpackPlugin.options"

Created on 14 Jun 2019  路  11Comments  路  Source: jantimon/html-webpack-plugin

Hello, I have a question about using the plugin. How do I replace directly without the parent path htmlWebpackPlugin.options?

AS-IS

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
  </head>
  <body>
    <h1><%= htmlWebpackPlugin.options.hello %></h1>
  </body>
</html>

TO-BE

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
  </head>
  <body>
    <h1><%= hello %></h1>
  </body>
</html>

htmlWebpackPlugin.options is a good module, but I think it is too long. Is there any way to reduce it?

Most helpful comment

You can use templateParameters in different ways to adjust how the object is generated before it is passed to your template

new HtmlWebpackPlugin({
 templateParameters: { hello: 'World' }
})

or

new HtmlWebpackPlugin({
 templateParameters: (compilation, assets, assetTags, options) => {
    return { hello: 'World' }
  }
})

or even with a async function:

new HtmlWebpackPlugin({
 templateParameters: async (compilation, assets, assetTags, options) => {
    return { hello: 'World' }
  }
})

If you don't set the templateParameters option the following default function is used:

https://github.com/jantimon/html-webpack-plugin/blob/075473d2b6507eb278dee2fb4da1c6492f8bf492/index.js#L938-L975

All 11 comments

You can use templateParameters in different ways to adjust how the object is generated before it is passed to your template

new HtmlWebpackPlugin({
 templateParameters: { hello: 'World' }
})

or

new HtmlWebpackPlugin({
 templateParameters: (compilation, assets, assetTags, options) => {
    return { hello: 'World' }
  }
})

or even with a async function:

new HtmlWebpackPlugin({
 templateParameters: async (compilation, assets, assetTags, options) => {
    return { hello: 'World' }
  }
})

If you don't set the templateParameters option the following default function is used:

https://github.com/jantimon/html-webpack-plugin/blob/075473d2b6507eb278dee2fb4da1c6492f8bf492/index.js#L938-L975

@jantimon Thank you!, I will try it :D

Cool - please let me know if it worked for you as expected

@jantimon thanks for the explanation.

If i include data with external file:

new HtmlWebpackPlugin({
 templateParameters: (compilation, assets, assetTags, options) => {
    const dataFile = "./src/data.json";
    chokidar.watch(dataFile, {}).on("all", () => {
        // Need help to emit recompile like template change does.
    });
    return require(dataFile);
  }
})

Can i with compilation parameter emit rerender template on data change?

@sim2github as faar as I know this is not possible - however if you require the json from within your template it should work

@jantimon client side rendering is not what i looking for (i would be better prefer static site generator). Trying to find the way in template-engine brought me here. Thanks.

Actually deep dive in webpack plugin interaction give me the way to emit rebuild instance.
All we need is add my data file to compilation.fileDependencies watch list.

new HtmlWebpackPlugin({
 templateParameters: (compilation, assets, assetTags, options) => {
     const dataFile = "./src/data.json";
     if (compilation.fileDependencies.add) {
        compilation.fileDependencies.add(dataFile);
      } else {
        // Before Webpack 4 - fileDepenencies was an array
        compilation.fileDependencies.push(dataFile);
      }

    delete require.cache[require.resolve(dataFile)];
    return require(dataFile);
  }
})

The template is executed during build time - so it is not client side rendering and will automatically do the file watching for you.

Your template would look like this (probably you should use a function as export):

https://github.com/jantimon/html-webpack-plugin/blob/35a154186501fba3ecddb819b6f632556d37a58f/examples/javascript/template.js#L1-L6

I use handlebars-loader "sugar" syntax with current plugin to inject assets and it works perfect in production mode with just

new HtmlWebpackPlugin({
 template: './path/to/template.hbs',
 templateParameters: require('./path/to/data/file.json');
})

but in development mode plugin watch changes of template and not templateParameters value. So

new HtmlWebpackPlugin({
 template: './path/to/template.hbs',
 templateParameters(compilation) {
     const DATA = './path/to/data/file.json';
    // Add datafile path to watch and rebuild when data changes
    compilation.fileDependencies.add(DATA);
    // Clear previous cached data from file if exist
    delete require.cache[require.resolve(DATA)];
    // Return always fresh data
    return require(DATA);
  }
})

works perfect for me (rebuild on file.json change and update page on dev-server).

Thanks. Now i'm happy.

Cool that should work 馃憤

Another approach would be to use a a .js file as template:

template.js

module.exports = function() {
  const data = require('./some/file.json');
  return require('./path/to/template.hbs')(data);
}
new HtmlWebpackPlugin({
 template: './template.js'
})

That way webpack would know about file.json similar to your addDependency call.

@jantimon It works for me. Good advice. Thank you.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lcxfs1991 picture lcxfs1991  路  4Comments

rokoroku picture rokoroku  路  3Comments

GerkinDev picture GerkinDev  路  3Comments

meleyal picture meleyal  路  3Comments

var-bp picture var-bp  路  3Comments