-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathindex.js
132 lines (123 loc) · 3.96 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
'use strict';
const assert = require('assert');
const objectAssign = require('object-assign');
const minimatch = require('minimatch');
const path = require('path');
const preloadDirective = {
'.js': 'script',
'.css': 'style',
'.woff': 'font',
'.woff2': 'font',
'.jpeg': 'image',
'.jpg': 'image',
'.gif': 'image',
'.png': 'image',
'.svg': 'image'
};
// By default all files are prefetched and preload
const defaultFilter = ['**/*.*'];
class ResourceHintWebpackPlugin {
constructor (options) {
assert.equal(options, undefined, 'The ResourceHintWebpackPlugin does not accept any options');
}
apply (compiler) {
// Hook into the html-webpack-plugin processing
if (compiler.hooks) {
// Webpack 4+ Plugin System
compiler.hooks.compilation.tap('ResourceHintWebpackPlugin', compilation => {
if (compilation.hooks.htmlWebpackPluginAlterAssetTags) {
compilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync('ResourceHintWebpackPluginAlterAssetTags',
resourceHintWebpackPluginAlterAssetTags
);
}
});
} else {
// Webpack 1-3 Plugin System
compiler.plugin('compilation', compilation => {
compilation.plugin('html-webpack-plugin-alter-asset-tags',
resourceHintWebpackPluginAlterAssetTags
);
});
}
}
}
/**
* The main processing function
*/
function resourceHintWebpackPluginAlterAssetTags (htmlPluginData, callback) {
const htmlWebpackPluginOptions = htmlPluginData.plugin.options;
const pluginData = objectAssign({}, htmlPluginData);
const tags = {
prefetch: [],
// https://w3c.github.io/preload/#link-type-preload
preload: []
};
// Create Resource tags
Object.keys(tags).forEach(resourceHintType => {
// Check if it is disabled for the current htmlWebpackPlugin instance:
// e.g.
// new HtmlWebpackPlugin({
// prefetch: false
// })
if (htmlWebpackPluginOptions[resourceHintType] === false) {
return;
}
// If no options are found all files are prefetched / preload
const fileFilters = htmlWebpackPluginOptions[resourceHintType]
? [].concat(htmlWebpackPluginOptions[resourceHintType])
: defaultFilter;
// Process every filter
fileFilters.forEach(filter => {
if (filter.indexOf('*') !== -1) {
Array.prototype.push.apply(tags[resourceHintType], addResourceHintTags(
resourceHintType,
filter,
pluginData.body,
htmlWebpackPluginOptions
));
} else {
tags[resourceHintType].push(createResourceHintTag(filter, resourceHintType, htmlWebpackPluginOptions));
}
});
});
// Add all Resource tags to the head
Array.prototype.push.apply(pluginData.head, tags.preload.map(addPreloadType));
Array.prototype.push.apply(pluginData.head, tags.prefetch);
callback(null, pluginData);
}
/**
* Adds Resource hint tags
*/
function addResourceHintTags (resourceHintType, filter, assetTags, htmlWebpackPluginOptions) {
const urls = assetTags
.map(tag => tag.attributes.src || tag.attributes.href)
.filter(url => url)
.filter(minimatch.filter(filter));
// Add a ResourceHint for every match
return urls.map(url => createResourceHintTag(url, resourceHintType, htmlWebpackPluginOptions));
}
function createResourceHintTag (url, resourceHintType, htmlWebpackPluginOptions) {
return {
tagName: 'link',
selfClosingTag: !!htmlWebpackPluginOptions.xhtml,
attributes: {
rel: resourceHintType,
href: url
}
};
}
/**
* The as attribute's value must be a valid request destination.
* If the provided value is omitted, the value is initialized to the empty string.
*
* @see https://w3c.github.io/preload/#link-element-interface-extensions
* @param {[type]} tag [description]
*/
function addPreloadType (tag) {
const ext = path.extname(tag.attributes.href);
if (preloadDirective[ext]) {
tag.attributes.as = preloadDirective[ext];
}
return tag;
}
module.exports = ResourceHintWebpackPlugin;