Html-webpack-plugin: feature request: support multiple configurations with one HTML file. eg type=module.

Created on 11 Sep 2017  路  8Comments  路  Source: jantimon/html-webpack-plugin

Description

support multiple configurations with one HTML file. eg <script type=module>

Specifically I'd like to create a config with babel loader set to:

{
  "presets": [
    ["env", {
      "targets": {
        "chrome": 61, "safari": "10.2"
      }
    }]
  ]
}

and one with babel loader set to:

{
  "presets": [
    ["env", {
      "targets": {
        "ie": 11
      }
    }]
  ]
}

then render both entry points in the same page with:

<script type="module" src="<- config[0].entry.js ->"><script>
<script nomodule src="<- config[1].entry.js ->"><script>
feature request

Most helpful comment

Is there still appetite for this?

All 8 comments

This would be awesome! I think it's important to keep it open to accepting multiple script sources. In my build, for example, three script tags get added because of code splitting:

<script type="text/javascript" src="/runtime.d4c01c143617f5833c44.js"></script>
<script type="text/javascript" src="/vendor.54efa82295fbe6e5beca.js"></script>
<script type="text/javascript" src="/main.cd860d906240d47980f6.js"></script>

So I guess the solution there would be something like (obviously I'm somewhat making up the syntax here):

<- config[0].output.map(src => `<script type="module" src="${src}></script>`) ->
<- config[1].output.map(src => `<script nomodule src="${src}></script>`) ->

I'm all in for a multiple config setup: https://github.com/jantimon/html-webpack-plugin/issues/780#issuecomment-328331520

Can put down the api you had in mind? (ie: which options would you pass down to new HtmlPlugin())

@mastilver That's a really good question! I don't think this can work unless there's a shared cache 馃槥. Here's how I ended up hacking this together for our (specific) webpack config. It was complicated a bit by us emitting several modules instead of a single main.js or bundle.js. This also doesn't really handle all CSS cases (it worked for our single CSS bundle).

let sharedAssets = { chunks: {}, js: [] }

function HtmlMultiBuildWebpackPlugin() {}

HtmlMultiBuildWebpackPlugin.prototype.apply = function(compiler) {
  compiler.plugin('compilation', function(compilation) {
    compilation.plugin('html-webpack-plugin-before-html-processing', function(data, cb) {
      // Avoid chunk name collisions, since they can be named the same between builds
      // { 'main': {} } to { 'main-modern': {} } if the filename matches
      const obj = mapKeys(data.assets.chunks, (v, k) => {
        if (v.entry.includes('-modern')) { return `${k}-modern` }

        return k
      })

      sharedAssets.js = uniq(concat(sharedAssets.js, data.assets.js))
      sharedAssets.chunks = merge(sharedAssets.chunks, obj)

      const newData = merge(data.assets, sharedAssets)

      cb(null, newData)
    })

    compilation.plugin('html-webpack-plugin-alter-asset-tags', function(args, cb) {
      const newBody = args.body.map((arg) => {
        if (arg.attributes.src.includes('-modern')) {
          return merge(arg, {
            attributes: { type: 'module' }
          })
        } else {
          return merge(arg, {
            attributes: { nomodule: true }
          })
        }
      })

      cb(null, merge(args, { body: newBody }))
    })
  })
}

So I guess an api to accommodate that would look something like this? It's definitely weird!

new HtmlWebpackPlugin({
  multiBuild: {
    cacheName: 'unique-name', // used to cache all chunks that go together
    suffixes: ['-modern'], // list of suffixes to watch out for. Could just be a string
    attributes: { // attributes to append based on the suffixes above. Would NEED to match
      '-modern': { type: 'module' }, // attribute overrides for the modern files
      default: { nomodule: true } // attribute overrides for everything else
    }
  }
})

I tried out @mike-engel 's plugin from above - it works great.

I created a gist with a few tweaks (functionally pretty much the same), and an usage example.

What use cases are there for making this more generic than the scenario described in the opening post?

This issue had no activity for at least half a year. It's subject to automatic issue closing if there is no activity in the next 15 days.

Is there still appetite for this?

created a small plugin for html-webpack-plugin for webpack4 multi-build configuration which also support FF, IE11, Edge, Chrome, Safari 11.
wrote down my findings...
https://github.com/firsttris/html-webpack-multi-build-plugin

Just wanted to add my 2 cents here. I agree with @graingert in that using module/nomodule can help developers trim their bundle sizes by quite a bit (and Babel makes this transpilation process even easier with the esmodules target).

It's so great to see plugins and workarounds created to solve this problem (such as the many already linked in this thread 馃帀), but it would be awesome to have this supported by HTMLWebpackPlugin. Happy to help where possible!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hackteck picture hackteck  路  3Comments

lonelydatum picture lonelydatum  路  3Comments

lonelyclick picture lonelyclick  路  3Comments

Rowno picture Rowno  路  3Comments

amorphius picture amorphius  路  3Comments