UNPKG

12.8 kBMarkdownView Raw
1Script Extension for HTML Webpack Plugin
2========================================
3[![npm version](https://badge.fury.io/js/script-ext-html-webpack-plugin.svg)](http://badge.fury.io/js/script-ext-html-webpack-plugin) [![Dependency Status](https://david-dm.org/numical/script-ext-html-webpack-plugin.svg)](https://david-dm.org/numical/script-ext-html-webpack-plugin) [![Build status](https://travis-ci.org/numical/script-ext-html-webpack-plugin.svg)](https://travis-ci.org/numical/script-ext-html-webpack-plugin) [![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg?style=flat-square)](https://github.com/Flet/semistandard)
4
5[![NPM](https://nodei.co/npm/script-ext-html-webpack-plugin.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/script-ext-html-webpack-plugin/)
6
7
8Enhances [html-webpack-plugin](https://github.com/ampedandwired/html-webpack-plugin)
9functionality with different deployment options for your scripts including:
10- [`async`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#Attributes) attribute;
11- [`defer`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#Attributes) attribute;
12- [`type="module"`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#Attributes) attribute;
13- any custom attributes you wish to add;
14- inlining;
15- [`preload`](https://www.w3.org/TR/preload/) resource hint;
16- [`prefetch`](https://www.w3.org/TR/resource-hints/#dfn-prefetch) resource hint
17
18This is an extension plugin for the [webpack](http://webpack.github.io) plugin [html-webpack-plugin](https://github.com/ampedandwired/html-webpack-plugin) - a plugin that simplifies the creation of HTML files to serve your webpack bundles.
19
20The raw [html-webpack-plugin](https://github.com/ampedandwired/html-webpack-plugin) incorporates all webpack-generated javascipt as synchronous`<script>` elements in the generated html. This plugin allows you to:
21- add standard and custom attributes to these elements;
22- inline the code in the elements;
23- add prefetch and preload resource hints for initial and dynamically loaded scripts.
24
25Installation
26------------
27You must be running webpack (1.x or 2.x) )on node 4+.
28
29Install the plugin with npm:
30```shell
31$ npm install --save-dev script-ext-html-webpack-plugin
32```
33
34You may see an `UNMET PEER DEPENDENCY` warning for webpack.
35
36This is fine; in testing, we dynamically download multiple versions of webpack (via the [dynavers](https://github.com/numical/dynavers) module).
37
38
39Basic Usage
40-----------
41Add the plugin to your webpack config as follows:
42
43```javascript
44plugins: [
45 new HtmlWebpackPlugin(),
46 new ScriptExtHtmlWebpackPlugin()
47]
48```
49The above configuration will actually do nothing due to the configuration defaults. Some more useful scenarios:
50
51All scripts set to `async`:
52```javascript
53plugins: [
54 new HtmlWebpackPlugin(),
55 new ScriptExtHtmlWebpackPlugin({
56 defaultAttribute: 'async'
57 })
58]
59```
60
61All scripts set to `async` except 'first.js' which is sync:
62```javascript
63plugins: [
64 new HtmlWebpackPlugin(),
65 new ScriptExtHtmlWebpackPlugin({
66 sync: 'first.js',
67 defaultAttribute: 'async'
68 })
69]
70```
71
72Configuration offers much more complex options:
73
74Configuration
75-------------
76You must pass a hash of configuration options to the plugin to cause the addition of attributes:
77- `inline`: a __script matching pattern__ defining scripts that should be inlined in the html (default: `[]`);
78- `sync`: a __script matching pattern__ defining script names that should have no attribute (default: `[]`);
79- `async`: a __script matching pattern__ defining script names that should have an `async` attribute (default: `[]`);
80- `defer`: a __script matching pattern__ defining script names that should have a `defer` attribute (default: `[]`);
81- `defaultAttribute`: `'sync' | 'async' | 'defer'` The default attribute to set - `'sync'` actually results in no attribute (default: `'sync'`);
82- `module`: a __script matching pattern__ defining script names that should have a
83`type="module"` attribute (default: `[]`);
84- `preload`: a __script matching pattern__ defining scripts that should have accompanying preload resource hints (default: `[]`);
85- `prefetch`: a __script matching pattern__ defining scripts that should have accompanying prefetch resource hints (default: `[]`);
86- `custom`: a single hash or an array of hashes with the following structure:
87 - `test`: a **script matching pattern** defining scripts that should have a custom attribute added;
88 - `attribute`: a `String` attribute to add;
89 - `value`: (optional) a `String` value for the attribute; if not set the attribute has no value set (equivalent of `true`).
90
91A __script matching pattern__ matches against a script's name. It can be one of:
92- a `String`- matches if it is a substring of the script name;
93- a `RegExp`;
94- an array of `String`'s and/or `RegExp`'s - matches if any one element matches;
95- a hash with property `test` with a value of one of the above.
96
97In 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:
98
991. if a script name matches the`inline` script matching pattern, it will be inlined;
100
1012. if a script name matches the `sync` script matching pattern, it will have no attribute, *unless* it matched condition 1;
102
1033. if a script name the `async` script matching pattern, it will have the `async` attribute, *unless* it matched conditions 1 or 2;
104
1054. if a script name matches the `defer` script matching pattern, it will have the `defer` attribute, *unless* it matched conditions 1, 2 or 3;
106
1075. if a script name does not match any of the previous conditions, it will have the `defaultAttribute' attribute.
108
109The `module` attribute is independent of conditions 2-5, but will be ignored if the script isinlined.
110
111
112Dynamically Loaded Scripts
113--------------------------
114The `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:
115- `initial`: default behaviour, no asynchronour scripts;
116- `async`: only asynchronouse scripts;
117- `all`: all scripts
118Note that you must still supply a `test` __script matching pattern__ which is also applied when selecting scripts.
119
120
121Configuration Examples
122---------------------
123
124All scripts with 'important' in their name are sync and all others set to `defer`:
125```javascript
126plugins: [
127 new HtmlWebpackPlugin(),
128 new ScriptExtHtmlWebpackPlugin({
129 sync: 'important'
130 defaultAttribute: 'defer'
131 })
132]
133```
134
135Alternatively, using a regular expression:
136```javascript
137plugins: [
138 new HtmlWebpackPlugin(),
139 new ScriptExtHtmlWebpackPlugin({
140 sync: /important/,
141 defaultAttribute: 'defer'
142 })
143]
144```
145
146All 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):
147```javascript
148plugins: [
149 new HtmlWebpackPlugin(),
150 new ScriptExtHtmlWebpackPlugin({
151 async: 'mod',
152 module: 'mod'
153 })
154]
155```
156
157Script 'startup.js' is inlined whilst all other scripts are async and preloaded:
158```javascript
159plugins: [
160 new HtmlWebpackPlugin(),
161 new ScriptExtHtmlWebpackPlugin({
162 inline: 'startup',
163 preload: /\.js$/,
164 defaultAttribute: 'async'
165 })
166]
167```
168
169All asynchronous scripts are added as `preload` resource hints. All other scripts are `async`:
170```javascript
171plugins: [
172 new HtmlWebpackPlugin(),
173 new ScriptExtHtmlWebpackPlugin({
174 async: /\.js$/
175 preload: {
176 test: /\.js$/,
177 chunks: 'async'
178 }
179 })
180]
181```
182
183All scripts have custom attribute `type='text/paperscript'` and ui.js also has a custom attribute of `id='1235'`:
184```javascript
185plugins: [
186 new HtmlWebpackPlugin(),
187 new ScriptExtHtmlWebpackPlugin({
188 custom: [
189 {
190 test: /\.js$/,
191 attribute: 'type',
192 value: 'text/paperscript'
193 },
194 {
195 test: 'ui.js',
196 attribute: 'id',
197 value: '12345'
198 }
199 ]
200 })
201]
202```
203
204And so on, to craziness:
205```javascript
206plugins: [
207 new HtmlWebpackPlugin(),
208 new ScriptExtHtmlWebpackPlugin({
209 inline: 'startup',
210 sync: [/imp(1|2){1,3}}/, 'initial'],
211 defer: ['slow', /big.*andslow/],
212 module: [/^((?!sync).)*/, 'mod'],
213 prefetch: 'indirectly-referenced.js',
214 defaultAttribute: 'async'
215 })
216]
217```
218
219Any problems with real-world examples, just raise an issue.
220
221
222A Note on Script Names
223----------------------
224In 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](https://webpack.js.org/concepts/entry-points/#object-syntax) to create aliases that the plugin will then use for its pattern matching. Your `webpack.config.js` will look something like this:
225```javascript
226entry: {
227 a: path.join(__dirname, 'lib/myFunctions.js'),
228 b: path.join(__dirname, 'lib/otherFunctions.js'),
229 c: path.join(__dirname, 'lib/criticalFuntions.js')
230},
231output: {
232 ...
233 filename: '[name].js'
234}
235plugins: [
236 new HtmlWebpackPlugin(),
237 new ScriptExtHtmlWebpackPlugin({
238 inline: ['c'],
239 defer: ['a', 'b']
240 })
241]
242```
243
244
245Inlining
246--------
247Several notes and caveats apply:
248* This feature is for `<script>`'s only. If you wish to inline css please see the sister plugin
249[style-ext-html-webpack-plugin](https://github.com/numical/style-ext-html-webpack-plugin).
250* Even the simplest script will be wrapped with webpack boilerplate; ensure you minify your javascript if you want your output html to be legible!
251* Hot replacement of inlined scripts will only work if caching is [switched off](https://github.com/ampedandwired/html-webpack-plugin#configuration) for html-webpack-plugin:
252```javascript
253plugins: [
254 new HtmlWebpackPlugin({
255 cache: false
256 }),
257 new ScriptExtHtmlWebpackPlugin({
258 inline: ['myinlinedscript.js']
259 })
260]
261```
262* An alternative approach, based on jade templates is illustrated in the [HtmlWebpackPlugin inline example](https://github.com/ampedandwired/html-webpack-plugin/tree/master/examples/inline).
263
264
265Resource Hints
266--------------
267In most cases, modern browsers will intelligently preload referenced script assets.
268However if you wish, this plugin can add resource hint elements to the `<head>` element of the form:
269```html
270<link rel="[preload|prefetch]" href="[scriptname]" as="script">
271```
272Use the `preload` and `prefetch` configuration options.
273Where `preload` and `prefetch` patterns overlap, `preload` takes precedence.
274
275Possibly a more compelling use case is to preload/prefetch dynamically loaded scripts generated by Webpack's [code splitting](https://webpack.js.org/guides/code-splitting-require). Since v1.7.0, this plugin can do this - see 'Dynamically Loaded Scripts' above.
276
277
278Notes:
279- for more on resource hints, see the [`w3c`](https://www.w3.org/TR/resource-hints) definition;
280- for a more complete solution that allows the preloading\fetching of assets other than scripts, see the [resource-hints-webpack-plugin](https://github.com/jantimon/resource-hints-webpack-plugin).
281
282
283
284Change History
285--------------
286
287v1.8.x
288* added custom attributes
289
290v1.7.x
291* updated for Webpack 2.5.x and updated all dependencies
292* adds asynchronous script resource hints
293* fixed [issue 13](https://github.com/numical/script-ext-html-webpack-plugin/issues/13) - inline functionality not working with HtmlWebpackPlugin hashing
294* fixed [issue 16](https://github.com/numical/script-ext-html-webpack-plugin/issues/16) - unnecessary <link> closing tag
295* fixed [issue 18](https://github.com/numical/script-ext-html-webpack-plugin/issues/18) - added defensive coding against unpopulated event arguments
296* refactored for better handling of `publicPath` - thanks @koalaink
297
298v1.6.x
299* works with webpack 2.2.1
300* enhanced API (no need to use array), fully backwardly compatible
301* refactor in preparation for v2
302
303v1.5.x
304* added resource hints
305* works with webpack 2.2.0
306
307v1.4.x
308* updated internal mechanism to use new(ish) [HtmlWebpackPlugin event](https://github.com/ampedandwired/html-webpack-plugin#events)
309* improved test mechanism and enhanced test coverage
310* added support for `publicPath` for inline scripts (thanks @JustAboutJeff)
311* works with 'webpack -p' (thanks @brandongoode)
312
313v1.3.x
314* added `type="text/javascript"` by default, in response to [Safari 9.1.1 bug](https://github.com/ampedandwired/html-webpack-plugin/issues/309)
315* removed experimental status of inline option
316* added weback 2.2.x beta support
317
318v1.2.x
319* added inline option
320
321v1.1.x
322* added `type="module"` option
323
324v1.0.x
325* initial release