Pass variables from html-webpack-plugin to pug template

5k Views Asked by At

Is it possible to pass a variable to the .pug template loaded by the 'pug-html-loader' which I defined in the 'html-webpack-plugin' before?

webpack.config.babel.js

...

{
  test: /\.pug$/,
  use: [
      {
          loader: 'html-loader'
      },
      {
          loader: 'pug-html-loader',
          options: {
              self: true
          }
      }]
}


...

 plugins: [

        new HtmlWebpackPlugin({
            chunks: ['index'],
            filename: 'index.html',
            template: './src/templates/layout.pug',
            title: 'Welcome',
            file: 'index'
        }),

        new HtmlWebpackPlugin({
            chunks: ['index', 'contact'],
            filename: 'contact.html',
            template: './src/templates/layout.pug',
            title: 'Contact us',
            file: 'contact'
        }),

]

In a layout.html I have defined as follows:

<!doctype html>
<html class="no-js" lang="en">
<head>
    <meta charset="utf-8">
    <title><%= htmlWebpackPlugin.options.title %></title>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>

<main>
    ${ require('html-loader!../partials/' + htmlWebpackPlugin.options.file + '.html' ) }
</main>

</body>
</html>

How can I use it to pass all variables - defined in the Webpack plugin for the usage in my PugTemplates and files? The application is supposed to be a simple process for creating simple webpages, which consists of several static pages.

5

There are 5 best solutions below

0
On

You can replace TAGs from your HTML file by using InterpolateHtmlPlugin.

plugins: [

        // Makes some environment variables available in index.html.
        // The public URL is available as %PUBLIC_URL% in index.html, e.g.:
        // <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
        // In development, this will be an empty string.
        new InterpolateHtmlPlugin({
            PUBLIC_URL: publicUrl
        }),
...
}

You can install the plugin from react-dev-utils npm package

const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');

You can see full example here:

HTML file: https://github.com/jquintozamora/react-typescript-webpack2-cssModules-postCSS/blob/master/public/index.html#L8

webpack config: https://github.com/jquintozamora/react-typescript-webpack2-cssModules-postCSS/blob/master/webpack/webpack.config.dev.js#L9 and https://github.com/jquintozamora/react-typescript-webpack2-cssModules-postCSS/blob/master/webpack/webpack.config.dev.js#L80-L82

package.json: https://github.com/jquintozamora/react-typescript-webpack2-cssModules-postCSS/blob/master/package.json#L55

0
On

I have tried to use templateParameters at HtmlWebpackPlugin, it seems not working.

But find a sample here https://github.com/jantimon/html-webpack-plugin/tree/main/examples/template-parameters, and this is a sample to pass variables into ejs template files

Then I got the answer at pug-html-loader, it can pass data into pug files, just use the 'data' property at options, like below, I add an 'IMG_PREFIX' in it.

module.exports = {
  rules: [
    loaders: [{
      include: /\.pug/,
      loader: ['pug-html-loader'],
      options: {
        data: {
          IMG_PREFIX: '/'
        }
      }
    }]
  ]
};

then you can receive the variable at pug file and use it

- var imgPrefix = IMG_PREFIX

div.avatar-block
    img.avatar(src=imgPrefix+'xxx.jpg')
1
On

your code should work.

Is there any particular reason why you are using html-loader ?

Although nothing stops you from making use of multiple templates in your app or even chain load them if they convert nicely; we usually make use of one templating engine. Now, I haven't taken a look at the html-loader source code, but from the comment posted at the link provided below, html-loader does not support template parameters. It does not make use of them, pass it down or up to other loaders in the same chain.

In short, Template parameters do not work in html-loader and that may be the reason why you're having this issue.

Try removing the html-loader and see if that fixes it.

https://github.com/jantimon/html-webpack-plugin/issues/1400

0
On

For those that are having trouble with this answer. The solution is to create a templateGenerator

Example:

new HTMLWebpackPlugin({
   inject: true,
   templateParameters: paramGenerator(globals), // <--- Here
   template: '/mytemplate.pug',
}),
import { environment } from '../environment';

export function paramGenerator(globals: () => {[key: string]: any}) {
  return (compilation, assets, assetTags, options) => {
    return {
      compilation: compilation,
      webpackConfig: compilation.options,
      htmlWebpackPlugin: {
        tags: assetTags,
        files: assets,
        options: options
      },
      environment,
      ...globals(),
    };
  }
}

Where globals is a function that returns a simple object that is attached to your global pug scope.

1
On

pug-html-loader options argument accepts a data property where you can pass your configuration variables. See here:

Pass data to pug using pug-html-loader (cannot read property of undefined)

{
  loader: 'pug-html-loader',
  options: {
    data: {
      title: 'Hello World'
    }
  }
}