Html-webpack-plugin: config option for adding `async` attribute to script tag?

Created on 7 Nov 2015  路  18Comments  路  Source: jantimon/html-webpack-plugin

Hi,

I didn't see anything in the source or docs about a config option to add the async attribute to the script tags that get injected, am I missing something?

http://www.w3schools.com/tags/att_script_async.asp

Making the script load async is usually recommended after running https://developers.google.com/speed/pagespeed/insights/

I am happy to submit a PR, but just want to check first.

Thanks for the lib!

Most helpful comment

For anyone monitoring this issue, version 1.2.0 of script-ext-html-webpack-plugin now offers async, defer, type="module" and in-lining options. Just waiting for @jantimon to make this all redundant by building it all into html-webpack-plugin...

All 18 comments

:+1: pls don't forget about defer.
for now I'll just use custom template

:+1: Loving the plugin! And I'd love it even more if this was a feature ;)

I don't think it's safe to add the async attribute to these script tags as their execution order matters.

For example, when I generate a bundle with two entry points, only one of them provides the window.webpackJsonp global callback. Subsequent chunks depend on that function in order to register their modules.

That could be overcome by only omitting the defer attribute on the first script tag but including it on subsequent tags, but this seems to be a path toward some complexity, rather than just turing a defer option on or off for the whole plugin.

I'd really love to see async and defer options for those that want to fine-tune their page load.

I imagine the config could map to config.entry keys, e.g. given the following webpack config:

  entry: {
    app: ['./app/bootstrap.js'],
    vendor: ['./app/vendor.js'],
    thirdparty: ['./app/third-party.js']
  }

The plugin config could look something like:

  new HtmlWebpackPlugin({
    filename: 'app.html',
    template: 'html!./src/app.html',
    inject: 'body',
    async: ['app', 'vendor'],
    defer: ['thirdparty']
  })

@alextreppass Unfortunately there are more then just asnyc and defer..
Async

Maybe a more future proof solution could be

new HtmlWebpackPlugin({
  inject: {
    default: 'body',
    entries: {
       app: 'defer',
       vendor: 'module',
       thirdparty: 'head'
    }
  }
});

what do you think?

I have gone down a slightly different route with script-ext-html-webpack-plugin.
No module support yet but I will look at that next...

@jantimon: +1 for keying it on entries, it reads better 馃憤

How would we do module + async - support arrays?

new HtmlWebpackPlugin({
  inject: {
    default: 'body',
    entries: {
       app: ['module', 'async'],
       vendor: 'module',
       thirdparty: 'head'
    }
  }
});

FYI, version 1.1.0 of script-ext-html-webpack-plugin now supports modules.
Note that the string matching/regex configuration is quite concise in most (sane) use cases - see README for some examples.

For anyone monitoring this issue, version 1.2.0 of script-ext-html-webpack-plugin now offers async, defer, type="module" and in-lining options. Just waiting for @jantimon to make this all redundant by building it all into html-webpack-plugin...

I guess we can use script-ext-html-webpack-plugin for now.

Nice one thanks @numical

Any reason we wouldn't want to combine the features. @jantimon could we just call compiler.apply() and use that plugin if we had a property set to true etc.

Well such a plugin could be built even simpler now with the new hooks that the current html plugin provides. But even without that the plugin should work :)

Would you accept a PR to add config options for html-webpack-plugin that support setting async/module/defer etc?

What is the motivation of not using the plugin which already supports that?

to solve this problem:
I opted to edit the index.js on line 479
replacing with the following code -> type: 'module',

with async bugs,
because you need elements in the dom
I would like you to contemplate this change for your next version

in: node_modules/html-wepack-plugin/index.js

/**

  • Injects the assets into the given html string
    */
    HtmlWebpackPlugin.prototype.generateAssetTags = function (assets) {
    // Turn script files into script tags
    var scripts = assets.js.map(function (scriptPath) {
    return {
    tagName: 'script',
    closeTag: true,
    attributes: {
    type: 'module',
    src: scriptPath
    }
    };
    });
    // Make tags self-closing in case of xhtml
    var selfClosingTag = !!this.options.xhtml;
    // Turn css files into link tags
    var styles = assets.css.map(function (stylePath) {
    return {
    tagName: 'link',
    selfClosingTag: selfClosingTag,
    attributes: {
    href: stylePath,
    rel: 'stylesheet'
    }
    };
    });
    // Injection targets
    var head = [];
    var body = [];

// If there is a favicon present, add it to the head
if (assets.favicon) {
head.push({
tagName: 'link',
selfClosingTag: selfClosingTag,
attributes: {
rel: 'shortcut icon',
href: assets.favicon
}
});
}
// Add styles to the head
head = head.concat(styles);
// Add scripts to body or head
if (this.options.inject === 'head') {
head = head.concat(scripts);
} else {
body = body.concat(scripts);
}
return {head: head, body: body};
};

motivation here should be simple -> dynamic import() and anything that's being injected in to <head> script/style related

ScriptExtHtmlWebpackPlugin supports only what HtmlWebpackPlugin -> meaning <body> static injections

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

azat-io picture azat-io  路  4Comments

klinki picture klinki  路  3Comments

var-bp picture var-bp  路  3Comments

lonelydatum picture lonelydatum  路  3Comments

hackteck picture hackteck  路  3Comments