Security News
JSR Working Group Kicks Off with Ambitious Roadmap and Plans for Open Governance
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
script-ext-html-webpack-plugin
Advanced tools
Enhances html-webpack-plugin functionality with async and defer attributes for script elements
Enhances html-webpack-plugin functionality with different deployment options for your scripts including:
async
attribute;defer
attribute;type="module"
attribute;preload
resource hint;prefetch
resource hintThis is an extension plugin for the webpack plugin html-webpack-plugin - a plugin that simplifies the creation of HTML files to serve your webpack bundles.
The raw html-webpack-plugin incorporates all webpack-generated javascipt as synchronous<script>
elements in the generated html. This plugin allows you to:
You must be running webpack (1.x or 2.x) )on node 4+.
Install the plugin with npm:
$ npm install --save-dev script-ext-html-webpack-plugin
You may see an UNMET PEER DEPENDENCY
warning for webpack.
This is fine; in testing, we dynamically download multiple versions of webpack (via the dynavers module).
Add the plugin to your webpack config as follows:
plugins: [
new HtmlWebpackPlugin(),
new ScriptExtHtmlWebpackPlugin()
]
The above configuration will actually do nothing due to the configuration defaults. Some more useful scenarios:
All scripts set to async
:
plugins: [
new HtmlWebpackPlugin(),
new ScriptExtHtmlWebpackPlugin({
defaultAttribute: 'async'
})
]
All scripts set to async
except 'first.js' which is sync:
plugins: [
new HtmlWebpackPlugin(),
new ScriptExtHtmlWebpackPlugin({
sync: 'first.js',
defaultAttribute: 'async'
})
]
Configuration offers much more complex options:
You must pass a hash of configuration options to the plugin to cause the addition of attributes:
inline
: a script matching pattern defining scripts that should be inlined in the html (default: []
);sync
: a script matching pattern defining script names that should have no attribute (default: []
);async
: a script matching pattern defining script names that should have an async
attribute (default: []
);defer
: a script matching pattern defining script names that should have a defer
attribute (default: []
);defaultAttribute
: 'sync' | 'async' | 'defer'
The default attribute to set - 'sync'
actually results in no attribute (default: 'sync'
);module
: a script matching pattern defining script names that should have a
type="module"
attribute (default: []
);preload
: a script matching pattern defining scripts that should have accompanying preload resource hints (default: []
);prefetch
: a script matching pattern defining scripts that should have accompanying prefetch resource hints (default: []
);custom
: a single hash or an array of hashes with the following structure:test
: a script matching pattern defining scripts that should have a custom attribute added;attribute
: a String
attribute to add;value
: (optional) a String
value for the attribute; if not set the attribute has no value set (equivalent of true
).A script matching pattern matches against a script's name. It can be one of:
String
- matches if it is a substring of the script name;RegExp
;String
's and/or RegExp
's - matches if any one element matches;test
with a value of one of the above.In more complicated use cases it may prove difficult to ensure that the pattern matching for different attributes are mutually exclusive. To prevent confusion, the plugin operates a simple precedence model:
if a script name matches theinline
script matching pattern, it will be inlined;
if a script name matches the sync
script matching pattern, it will have no attribute, unless it matched condition 1;
if a script name the async
script matching pattern, it will have the async
attribute, unless it matched conditions 1 or 2;
if a script name matches the defer
script matching pattern, it will have the defer
attribute, unless it matched conditions 1, 2 or 3;
if a script name does not match any of the previous conditions, it will have the `defaultAttribute' attribute.
The module
attribute is independent of conditions 2-5, but will be ignored if the script isinlined.
The preload
and prefetch
configuration also have allow an additional property in the hash form that can be passed to include dynamically loaded (asynchronous) scripts. This property is chunks
and can have one of the following String
values:
initial
: default behaviour, no asynchronour scripts;async
: only asynchronouse scripts;all
: all scripts
Note that you must still supply a test
script matching pattern which is also applied when selecting scripts.All scripts with 'important' in their name are sync and all others set to defer
:
plugins: [
new HtmlWebpackPlugin(),
new ScriptExtHtmlWebpackPlugin({
sync: 'important'
defaultAttribute: 'defer'
})
]
Alternatively, using a regular expression:
plugins: [
new HtmlWebpackPlugin(),
new ScriptExtHtmlWebpackPlugin({
sync: /important/,
defaultAttribute: 'defer'
})
]
All scripts with 'mod' in their name are async and type 'module', all others are sync (no explicit setting for this as it is the default):
plugins: [
new HtmlWebpackPlugin(),
new ScriptExtHtmlWebpackPlugin({
async: 'mod',
module: 'mod'
})
]
Script 'startup.js' is inlined whilst all other scripts are async and preloaded:
plugins: [
new HtmlWebpackPlugin(),
new ScriptExtHtmlWebpackPlugin({
inline: 'startup',
preload: /\.js$/,
defaultAttribute: 'async'
})
]
All asynchronous scripts are added as preload
resource hints. All other scripts are async
:
plugins: [
new HtmlWebpackPlugin(),
new ScriptExtHtmlWebpackPlugin({
async: /\.js$/
preload: {
test: /\.js$/,
chunks: 'async'
}
})
]
All scripts have custom attribute type='text/paperscript'
and ui.js also has a custom attribute of id='1235'
:
plugins: [
new HtmlWebpackPlugin(),
new ScriptExtHtmlWebpackPlugin({
custom: [
{
test: /\.js$/,
attribute: 'type',
value: 'text/paperscript'
},
{
test: 'ui.js',
attribute: 'id',
value: '12345'
}
]
})
]
And so on, to craziness:
plugins: [
new HtmlWebpackPlugin(),
new ScriptExtHtmlWebpackPlugin({
inline: 'startup',
sync: [/imp(1|2){1,3}}/, 'initial'],
defer: ['slow', /big.*andslow/],
module: [/^((?!sync).)*/, 'mod'],
prefetch: 'indirectly-referenced.js',
defaultAttribute: 'async'
})
]
Any problems with real-world examples, just raise an issue.
In the above examples the actual script names are used to select the deployment option. You may not wish to couple asset names to your deployment like this. Instead you can use Webpack's entry configuration to create aliases that the plugin will then use for its pattern matching. Your webpack.config.js
will look something like this:
entry: {
a: path.join(__dirname, 'lib/myFunctions.js'),
b: path.join(__dirname, 'lib/otherFunctions.js'),
c: path.join(__dirname, 'lib/criticalFuntions.js')
},
output: {
...
filename: '[name].js'
}
plugins: [
new HtmlWebpackPlugin(),
new ScriptExtHtmlWebpackPlugin({
inline: ['c'],
defer: ['a', 'b']
})
]
Several notes and caveats apply:
<script>
's only. If you wish to inline css please see the sister plugin
style-ext-html-webpack-plugin.plugins: [
new HtmlWebpackPlugin({
cache: false
}),
new ScriptExtHtmlWebpackPlugin({
inline: ['myinlinedscript.js']
})
]
In most cases, modern browsers will intelligently preload referenced script assets.
However if you wish, this plugin can add resource hint elements to the <head>
element of the form:
<link rel="[preload|prefetch]" href="[scriptname]" as="script">
Use the preload
and prefetch
configuration options.
Where preload
and prefetch
patterns overlap, preload
takes precedence.
Possibly a more compelling use case is to preload/prefetch dynamically loaded scripts generated by Webpack's code splitting. Since v1.7.0, this plugin can do this - see 'Dynamically Loaded Scripts' above.
Notes:
w3c
definition;v1.8.x
v1.7.x
publicPath
- thanks @koalainkv1.6.x
v1.5.x
v1.4.x
publicPath
for inline scripts (thanks @JustAboutJeff)v1.3.x
type="text/javascript"
by default, in response to Safari 9.1.1 bugv1.2.x
v1.1.x
type="module"
optionv1.0.x
FAQs
Enhances html-webpack-plugin functionality with async and defer attributes for script elements
We found that script-ext-html-webpack-plugin demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
Security News
Research
An advanced npm supply chain attack is leveraging Ethereum smart contracts for decentralized, persistent malware control, evading traditional defenses.
Security News
Research
Attackers are impersonating Sindre Sorhus on npm with a fake 'chalk-node' package containing a malicious backdoor to compromise developers' projects.