Skip to content

Commit c72da78

Browse files
committed
refactoring in preparation for v2
1 parent 14c6912 commit c72da78

File tree

10 files changed

+93
-83
lines changed

10 files changed

+93
-83
lines changed

README.md

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ All scripts set to `async` except 'first.js' which is sync:
5959
plugins: [
6060
new HtmlWebpackPlugin(),
6161
new ScriptExtHtmlWebpackPlugin({
62-
sync: ['first.js'],
62+
sync: 'first.js',
6363
defaultAttribute: 'async'
6464
})
6565
]
@@ -70,27 +70,31 @@ Configuration offers much more complex options:
7070
Configuration
7171
-------------
7272
You must pass a hash of configuration options to the plugin to cause the addition of attributes:
73-
- `inline`: array of `String`'s and/or `RegExp`'s defining scripts that should be inlined in the html (default: `[]`);
74-
- `sync`: array of `String`'s and/or `RegExp`'s defining script names that should have no attribute (default: `[]`);
75-
- `async`: array of `String`'s and/or `RegExp`'s defining script names that should have an `async` attribute (default: `[]`);
76-
- `defer`: array of `String`'s and/or `RegExp`'s defining script names that should have a `defer` attribute (default: `[]`);
73+
- `inline`: a __script matching pattern__ defining scripts that should be inlined in the html (default: `[]`);
74+
- `sync`: a __script matching pattern__ defining script names that should have no attribute (default: `[]`);
75+
- `async`: a __script matching pattern__ defining script names that should have an `async` attribute (default: `[]`);
76+
- `defer`: a __script matching pattern__ defining script names that should have a `defer` attribute (default: `[]`);
7777
- `defaultAttribute`: `'sync' | 'async' | 'defer'` The default attribute to set - `'sync'` actually results in no attribute (default: `'sync'`);
78-
- `module`: array of `String`'s and/or `RegExp`'s defining script names that should have a
78+
- `module`: a __script matching pattern__ defining script names that should have a
7979
`type="module"` attribute (default: `[]`);
80-
- `preload`: array of `String`'s and/or `RegExp`'s defining scripts that should have accompanying preload resource hints (default: `[]`);
81-
- `prefetch`: array of `String`'s and/or `RegExp`'s defining scripts that should have accompanying prefetch resource hints (default: `[]`);
80+
- `preload`: a __script matching pattern__ defining scripts that should have accompanying preload resource hints (default: `[]`);
81+
- `prefetch`: a __script matching pattern__ defining scripts that should have accompanying prefetch resource hints (default: `[]`);
8282

83-
In the arrays a `String` value matches if it is a substring of the script name.
83+
A __script matching pattern__ matches against a script's name. It can be one of:
84+
- a `String`- matches if it is a substring of the script name;
85+
- a `RegExp`;
86+
- an array of `String`'s and/or `RegExp`'s - matches if any one element matches;
87+
- a hash with property `test` with a value of one of the above.
8488

8589
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:
8690

87-
1. if a script name matches a `RegEx` or `String` from the `inline` option, it will be inlined;
91+
1. if a script name matches the`inline` script matching pattern, it will be inlined;
8892

89-
2. if a script name matches a `Regex` or `String` from the `sync` option, it will have no attribute, *unless* it matched condition 1;
93+
2. if a script name matches the `sync` script matching pattern, it will have no attribute, *unless* it matched condition 1;
9094

91-
3. if a script name matches a `Regex` or `String` from the `async` option, it will have the `async` attribute, *unless* it matched conditions 1 or 2;
95+
3. if a script name the `async` script matching pattern, it will have the `async` attribute, *unless* it matched conditions 1 or 2;
9296

93-
4. if a script name matches a `Regex` or `String` from the `defer` option, it will have the `defer` attribute, *unless* it matched conditions 1, 2 or 3;
97+
4. if a script name matches the `defer` script matching pattern, it will have the `defer` attribute, *unless* it matched conditions 1, 2 or 3;
9498

9599
5. if a script name does not match any of the previous conditions, it will have the `defaultAttribute' attribute.
96100

@@ -104,7 +108,7 @@ All scripts with 'important' in their name are sync and all others set to `defer
104108
plugins: [
105109
new HtmlWebpackPlugin(),
106110
new ScriptExtHtmlWebpackPlugin({
107-
sync: ['important'],
111+
sync: 'important'
108112
defaultAttribute: 'defer'
109113
})
110114
]
@@ -115,7 +119,7 @@ Alternatively, using a regular expression:
115119
plugins: [
116120
new HtmlWebpackPlugin(),
117121
new ScriptExtHtmlWebpackPlugin({
118-
sync: [/important/],
122+
sync: /important/,
119123
defaultAttribute: 'defer'
120124
})
121125
]
@@ -126,8 +130,8 @@ All scripts with 'mod' in their name are async and type 'module', all others are
126130
plugins: [
127131
new HtmlWebpackPlugin(),
128132
new ScriptExtHtmlWebpackPlugin({
129-
async: ['mod'],
130-
module: ['mod']
133+
async: 'mod',
134+
module: 'mod'
131135
})
132136
]
133137
```
@@ -137,25 +141,24 @@ Script 'startup.js' is inlined whilst all other scripts are async and preloaded:
137141
plugins: [
138142
new HtmlWebpackPlugin(),
139143
new ScriptExtHtmlWebpackPlugin({
140-
inline: ['startup'],
141-
preload: [/\.js$/],
144+
inline: 'startup',
145+
preload: /\.js$/,
142146
defaultAttribute: 'async'
143147
})
144148
]
145149
```
146150

147151

148-
149152
And so on, to craziness:
150153
```javascript
151154
plugins: [
152155
new HtmlWebpackPlugin(),
153156
new ScriptExtHtmlWebpackPlugin({
154-
inline: ['startup'],
157+
inline: 'startup',
155158
sync: [/imp(1|2){1,3}}/, 'initial'],
156159
defer: ['slow', /big.*andslow/],
157160
module: [/^((?!sync).)*/, 'mod'],
158-
prefetch: ['indirectly-referenced.js'],
161+
prefetch: 'indirectly-referenced.js',
159162
defaultAttribute: 'async'
160163
})
161164
]
@@ -229,7 +232,8 @@ Change History
229232

230233
v1.5.x
231234
* added resource hints
232-
* works with webpack 2.2.0
235+
* works with webpack 2.2.1
236+
* enhanced API (no need to use array), fully backwardly compatible
233237

234238
v1.4.x
235239
* updated internal mechanism to use new(ish) [HtmlWebpackPlugin event](https://github.com/ampedandwired/html-webpack-plugin#events)

dynavers.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"path": "dynavers_modules",
33
"versions": {
4-
"webpack" : ["1.14.0", "2.2.0"]
4+
"webpack" : ["1.14.0", "2.2.1"]
55
}
66
}

lib/common.js

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
'use strict';
22

33
const debug = require('debug')('ScriptExt');
4-
const PLUGIN = 'ScriptExtHtmlWebpackPlugin';
5-
const EVENT = 'html-webpack-plugin-alter-asset-tags';
6-
const INLINE = 'inline';
7-
const PUBLIC_PATH_PREFIX = /^.*\//;
84

95
const matches = (scriptName, tagOptions) => {
106
return tagOptions.test.some((pattern) => {
@@ -18,9 +14,5 @@ const matches = (scriptName, tagOptions) => {
1814

1915
module.exports = {
2016
debug,
21-
PLUGIN,
22-
EVENT,
23-
INLINE,
24-
PUBLIC_PATH_PREFIX,
2517
matches
2618
};

lib/config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
const { PLUGIN } = require('./common.js');
3+
const PLUGIN = require('./constants.js').PLUGIN;
44

55
const DEFAULT_HASH = Object.freeze({
66
test: []

lib/constants.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use strict';
2+
3+
const PLUGIN = 'ScriptExtHtmlWebpackPlugin';
4+
const EVENT = 'html-webpack-plugin-alter-asset-tags';
5+
const INLINE = 'inline';
6+
const PUBLIC_PATH_PREFIX = /^.*\//;
7+
8+
module.exports = {
9+
PLUGIN,
10+
EVENT,
11+
INLINE,
12+
PUBLIC_PATH_PREFIX
13+
};

lib/elements.js

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
'use strict';
22

3-
const { debug, PLUGIN, EVENT, INLINE, PUBLIC_PATH_PREFIX } = require('./common.js');
3+
const CONSTANTS = require('./constants.js');
44
const SYNC = 'sync';
55
const ATTRIBUTE_PRIORITIES = [SYNC, 'async', 'defer'];
66
const MODULE = 'module';
77

8-
const shouldUpdateElements = (options) => {
8+
const debug = require('./common.js').debug;
9+
const matches = require('./common.js').matches;
10+
11+
const shouldUpdate = (options) => {
912
if (ATTRIBUTE_PRIORITIES.indexOf(options.defaultAttribute) < 0) {
10-
throw new Error(`${PLUGIN}: invalid default attribute`);
13+
throw new Error(`${CONSTANTS.PLUGIN}: invalid default attribute`);
1114
}
1215
return !(options.defaultAttribute === SYNC &&
1316
options.inline.test.length === 0 &&
@@ -16,7 +19,7 @@ const shouldUpdateElements = (options) => {
1619
options.module.test.length === 0);
1720
};
1821

19-
const updateElements = (compilation, options, tags) => {
22+
const update = (compilation, options, tags) => {
2023
const update = updateElement.bind(null, compilation, options);
2124
return tags.map(update);
2225
};
@@ -30,42 +33,32 @@ const updateElement = (compilation, options, tag) => {
3033
const isScript = (tag) => tag.tagName === 'script';
3134

3235
const updateScriptElement = (compilation, options, tag) => {
33-
debug(`${EVENT}: processing <script> element: ${JSON.stringify(tag)}`);
36+
debug(`${CONSTANTS.EVENT}: processing <script> element: ${JSON.stringify(tag)}`);
3437
return (isInline(options, tag))
3538
? replaceWithInlineElement(compilation, tag)
3639
: updateSrcElement(options, tag);
3740
};
3841

39-
const isInline = (options, tag) => matches(tag.attributes.src, options[INLINE]);
40-
41-
const matches = (scriptName, tagOptions) => {
42-
return tagOptions.test.some((pattern) => {
43-
if (pattern instanceof RegExp) {
44-
return pattern.test(scriptName);
45-
} else {
46-
return scriptName.includes(pattern);
47-
}
48-
});
49-
};
42+
const isInline = (options, tag) => matches(tag.attributes.src, options[CONSTANTS.INLINE]);
5043

5144
const replaceWithInlineElement = (compilation, tag) => {
5245
const scriptName = getScriptName(tag);
5346
const asset = compilation.assets[scriptName];
54-
if (!asset) throw new Error(`${PLUGIN}: no asset with href '${scriptName}'`);
47+
if (!asset) throw new Error(`${CONSTANTS.PLUGIN}: no asset with href '${scriptName}'`);
5548
const newTag = {
5649
tagName: 'script',
5750
closeTag: true,
5851
innerHTML: asset.source()
5952
};
60-
debug(`${PLUGIN}: replaced by: ${JSON.stringify(newTag)}`);
53+
debug(`${CONSTANTS.PLUGIN}: replaced by: ${JSON.stringify(newTag)}`);
6154
return newTag;
6255
};
6356

6457
const getScriptName = (tag) => {
6558
let scriptName = getRawScriptName(tag);
6659
// remove publicPath prefix
6760
if (scriptName.includes('/')) {
68-
scriptName = scriptName.replace(PUBLIC_PATH_PREFIX, '');
61+
scriptName = scriptName.replace(CONSTANTS.PUBLIC_PATH_PREFIX, '');
6962
}
7063
return scriptName;
7164
};
@@ -90,11 +83,11 @@ const updateSrcElement = (options, tag) => {
9083
if (matches(scriptName, options[MODULE])) {
9184
tag.attributes.type = 'module';
9285
}
93-
debug(`${PLUGIN}: updated to: ${JSON.stringify(tag)}`);
86+
debug(`${CONSTANTS.PLUGIN}: updated to: ${JSON.stringify(tag)}`);
9487
return tag;
9588
};
9689

9790
module.exports = {
98-
shouldUpdateElements,
99-
updateElements
91+
shouldUpdate,
92+
update
10093
};

lib/plugin.js

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
'use strict';
22

3-
const { debug, EVENT, INLINE, matches } = require('./common.js');
3+
const CONSTANTS = require('./constants.js');
4+
5+
const debug = require('./common.js').debug;
6+
const matches = require('./common.js').matches;
47
const denormaliseOptions = require('./config.js');
5-
const { shouldAddResourceHints, addResourceHints } = require('./resource-hints.js');
6-
const { shouldUpdateElements, updateElements } = require('./elements.js');
8+
const resourceHints = require('./resource-hints.js');
9+
const elements = require('./elements.js');
10+
11+
const debugEvent = msg => {
12+
debug(`${CONSTANTS.EVENT}: ${msg}`);
13+
};
714

8-
const falsySafeConcat = (arrays) => {
15+
const falsySafeConcat = arrays => {
916
return arrays.reduce(
1017
(combined, array) => array ? combined.concat(array) : combined,
1118
[]
@@ -19,35 +26,35 @@ class ScriptExtHtmlWebpackPlugin {
1926
apply (compiler) {
2027
const options = this.options;
2128
compiler.plugin('compilation', (compilation) => {
22-
compilation.plugin(EVENT, (pluginArgs, callback) => {
29+
compilation.plugin(CONSTANTS.EVENT, (pluginArgs, callback) => {
2330
try {
24-
debug(`${EVENT}: starting`);
25-
if (shouldUpdateElements(options)) {
26-
debug(`${EVENT}: replacing <head> <script> elements`);
27-
pluginArgs.head = updateElements(compilation, options, pluginArgs.head);
28-
debug(`${EVENT}: replacing <body> <script> elements`);
29-
pluginArgs.body = updateElements(compilation, options, pluginArgs.body);
31+
debugEvent('starting');
32+
if (elements.shouldUpdate(options)) {
33+
debugEvent('replacing <head> <script> elements');
34+
pluginArgs.head = elements.update(compilation, options, pluginArgs.head);
35+
debugEvent('replacing <body> <script> elements');
36+
pluginArgs.body = elements.update(compilation, options, pluginArgs.body);
3037
}
31-
if (shouldAddResourceHints(options)) {
32-
debug(`${EVENT}: adding resource hints`);
38+
if (resourceHints.shouldAdd(options)) {
39+
debugEvent('adding resource hints');
3340
pluginArgs.head = falsySafeConcat([
3441
pluginArgs.head,
35-
addResourceHints(options, pluginArgs.head),
36-
addResourceHints(options, pluginArgs.body)
42+
resourceHints.add(options, pluginArgs.head),
43+
resourceHints.add(options, pluginArgs.body)
3744
]);
3845
}
39-
debug(`${EVENT}: completed`);
46+
debugEvent('completed');
4047
callback(null, pluginArgs);
4148
} catch (err) {
4249
callback(err);
4350
}
4451
});
4552
});
4653
compiler.plugin('emit', (compilation, callback) => {
47-
if (options[INLINE].length > 0 && options.removeInlinedAssets) {
54+
if (options[CONSTANTS.INLINE].length > 0 && options.removeInlinedAssets) {
4855
debug('emit: deleting assets');
4956
Object.keys(compilation.assets).forEach((assetName) => {
50-
if (matches(assetName, options[INLINE])) {
57+
if (matches(assetName, options[CONSTANTS.INLINE])) {
5158
debug(`emit: deleting asset '${assetName}'`);
5259
delete compilation.assets[assetName];
5360
}

lib/resource-hints.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
'use strict';
22

3-
const { PUBLIC_PATH_PREFIX, matches } = require('./common.js');
3+
const PUBLIC_PATH_PREFIX = require('./constants.js').PUBLIC_PATH_PREFIX;
4+
const matches = require('./common.js').matches;
45

5-
const shouldAddResourceHints = (options) => {
6+
const shouldAdd = options => {
67
return !(options.prefetch.test.length === 0 &&
78
options.preload.test.length === 0);
89
};
910

10-
const addResourceHints = (options, tags) => {
11+
const add = (options, tags) => {
1112
return tags
1213
.filter(hasScriptName)
1314
.reduce((hints, tag) => {
@@ -23,7 +24,7 @@ const addResourceHints = (options, tags) => {
2324
);
2425
};
2526

26-
const getScriptName = (tag) => {
27+
const getScriptName = tag => {
2728
let scriptName = getRawScriptName(tag);
2829
// remove publicPath prefix
2930
if (scriptName.includes('/')) {
@@ -32,9 +33,9 @@ const getScriptName = (tag) => {
3233
return scriptName;
3334
};
3435

35-
const getRawScriptName = (tag) => tag.attributes.src;
36+
const getRawScriptName = tag => tag.attributes.src;
3637

37-
const hasScriptName = (tag) => tag.attributes && tag.attributes.src;
38+
const hasScriptName = tag => tag.attributes && tag.attributes.src;
3839

3940
const createResourceHint = (rel, tag) => {
4041
return {
@@ -49,6 +50,6 @@ const createResourceHint = (rel, tag) => {
4950
};
5051

5152
module.exports = {
52-
shouldAddResourceHints,
53-
addResourceHints
53+
shouldAdd,
54+
add
5455
};

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
"dynavers": "^0.2.0",
4545
"handlebars": "^4.0.6",
4646
"handlebars-loader": "^1.4.0",
47-
"html-webpack-plugin": "^2.26.0",
47+
"html-webpack-plugin": "^2.28.0",
4848
"jasmine": "^2.5.3",
4949
"jasmine-spec-reporter": "^3.2.0",
5050
"jasmine2-custom-message": "^0.8.2",

0 commit comments

Comments
 (0)