Carles Capellas
Carles Capellas

Reputation: 333

Modify HtmlWebpackPlugin's generated script URLs

When using HtmlWebpackPlugin to generate the dist/index.html file, we can use the inject option to automatically create <script> tags for the javascript bundle files:

new HtmlWebpackPlugin({
    filename: config.build.index,
    template: 'index.html',
    inject: true,
    // ...
})

And get an index.html file that looks similar to:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Webpack App</title>
    </head>
    <body>
        <script src="index_bundle.js"></script>
    </body>
</html>

For server side constraints, I need to add a query string parameter in the generated script source, to make it look like <script src="index_bundle.js?my-parameter=my-value"></script>. I've been looking at the plugin documentation, but I can't find the way to do it.

Is there any option to modify the generated URLs, by appending an string or replacing with a RegEx?

Thanks in advance!

Upvotes: 2

Views: 4725

Answers (3)

Carles Capellas
Carles Capellas

Reputation: 333

Based on thedarkone's answer, I provide the resolution for my question:

I added the query parameter in the webpack configuration output parameter (production build only in my case) and use HtmlWebpackPlugin with the default config:

const webpackConfig = merge(baseWebpackConfig, {
    // ...
    output: {
        path: config.build.assetsRoot,
        filename: utils.assetsPath('js/[name].js?my-parameter=my-value'),
    },
    // ...
    new HtmlWebpackPlugin({
        filename: config.build.index,
        template: 'index.html',
        inject: true,
        // ...
    }
    // ...
}

Since I also need the query parameter in the style links, I also had to modify the ExtractTextPlugin filename parameter in the same way:

// ...
new ExtractTextPlugin({
    filename: 'bundle.[chunkhash].js'
    filename: utils.assetsPath('css/[name].css?my-parameter=my-value'),
})
// ...

Keep in mind that this approach will append the query parameters to ALL of the injected scripts/styles.

Upvotes: 3

customcommander
customcommander

Reputation: 18901

Have you considered doing that yourself by providing your own template to HtmlWebpackPlugin? It would look something like this:

In webpack.config.js:

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = () => ({
  entry: './burrito.js',
  output: {
    filename: './burrito_bundle.js'
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'lunch.ejs',
      templateParameters: {
        query: '?foo=bar&bar=baz'
      },
      filename: 'lunch.html',
      inject: false,
    }),
  ],
});

In lunch.ejs:

<html>
  <body>
    <% htmlWebpackPlugin.files.js.forEach(function(file) { %>
      <script src="<%= file %><%= htmlWebpackPlugin.options.templateParameters.query %>"></script>
    <% }) %>
  </body>
</html>

HtmlWebpackPlugin will expose a global variable htmlWebpackPlugin for your template to read values from. Cf. https://github.com/jantimon/html-webpack-plugin#writing-your-own-templates

When you run Webpack, it will process your lunch.ejs template and produce lunch.html:

<html>
  <body>
    <script src="./burrito_bundle.js?foo=bar&bar=baz"></script>
  </body>
</html>

Upvotes: 3

thedarkone
thedarkone

Reputation: 412

output: {
    filename: `bundle.js?param=${Math.random()}`
}

This would add the query parameter to bundle.js

The file name would rename as bundle.js though

If you wanted to generate a new file every time, the below would be better suited

output: {
    filename: 'bundle.[chunkhash].js'
}

Upvotes: 1

Related Questions