Unable to inject data into template with html-webpack-plugin

Detuned picture Detuned · Jul 20, 2017 · Viewed 10.7k times · Source

I've tried to get custom data injected into our .html template using this loader without any success. We've been able to successfully build our assets and have them injected, however, the ability to pass in dynamic data has not worked. Looking at the examples provided in this repo, I don't see how options.title is passed into the template.

I'm using this starter kit, which is quite simple with this plugin: https://github.com/AngularClass/NG6-starter

Here are the versions of the relevant dependencies:

"webpack": "^2.2.1"
"html-webpack-plugin": "^2.29.0"

Copy the relevant section from webpack.config.js:

module.exports = {
  devtool: 'source-map',
  entry: {
    app: [
      'babel-polyfill',
      path.join(__dirname, 'client', 'app/app.js')
    ]
  },
  module: {
    loaders: [
       { test: /\.js$/, exclude: [/app\/lib/, /node_modules/], loader: 'ng-annotate-loader!babel-loader' },
       { test: /\.html$/, loader: 'raw-loader' }, // have also tried with the html-loader
       { test: /\.(scss|sass)$/, loader: 'style-loader!css-loader!sass-loader' },
       { test: /\.css$/, loader: 'style-loader!css-loader' }
    ]
  },
  plugins: [
    // Injects bundles in your index.html instead of wiring all manually.
    // It also adds hash to all injected assets so we don't have problems
    // with cache purging during deployment.
    new HtmlWebpackPlugin({
      template: 'client/index.html',
      // inject: 'body',
      // hash: true,
      title: 'TEST!!!!!!!!!!!',
      options: {
        title: "TEST!!!!!!!!!!!!!*"
      },
      chunks: ['vendor', 'app']
    }),

    // Automatically move all modules defined outside of application directory to vendor bundle.
    // If you are using more complicated project structure, consider to specify common chunks manually.
    new webpack.optimize.CommonsChunkPlugin({
      name: "vendor",
      minChunks: module => /node_modules/.test(module.resource)
    })
  ]
};

Template file

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="description" content="NG6-Starter by @AngularClass">
    <link rel="icon" href="data:;base64,iVBORw0KGgo=">
    <base href="/">
  </head>
  <body ng-app="app" ng-strict-di ng-cloak>


  <%= htmlWebpackPlugin.options.title %>

  <%= htmlWebpackPlugin.title %>

  <%= title %>

  <%= '\<\%\= htmlWebpackPlugin.title \%\>' %>

  <%= '\<\%\= htmlWebpackPlugin.options \%\>' %>

  </body>
</html>

Answer

Michael Jungo picture Michael Jungo · Jul 20, 2017

The correct option is:

<%= htmlWebpackPlugin.options.title %>

This is EJS syntax. It evaluates the expression and puts the result into the HTML in its place. That means it needs to be in the <head> like so:

<title><%= htmlWebpackPlugin.options.title %></title>

The reason that your template is not working, is because you've configured raw-loader to be used for .html files. That means the template is treated as an HTML file. html-webpack-plugin a fallback ejs loader, which is only used if there's no loader configured for a given file. It's a good idea to use .ejs instead of .html for the template, to not conflict the loaders. See also The template option for other solutions (e.g. if you want to use another template engine).

Rename client/index.html to client/index.ejs.

new HtmlWebpackPlugin({
  template: 'client/index.ejs',
  // inject: 'body',
  // hash: true,
  title: 'TEST!!!!!!!!!!!',
  chunks: ['vendor', 'app']
}),

The repository you linked uses old versions of many things (webpack and html-webpack-plugin for instance) and it appears that the version of html-webpack-plugin does not work with the above configuration. You need to upgrade it with:

npm install --save-dev html-webpack-plugin@latest