forked from jantimon/resource-hints-webpack-plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
112 lines (105 loc) · 3.43 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
'use strict';
var assert = require('assert');
var objectAssign = require('object-assign');
var minimatch = require('minimatch');
var path = require('path');
var preloadDirective = {
'.js': 'script',
'.css': 'style',
'.woff': 'font',
'.woff2': 'font',
'.jpeg': 'image',
'.jpg': 'image',
'.gif': 'image',
'.png': 'image',
'.svg': 'image'
};
function ResourceHintWebpackPlugin (options) {
assert.equal(options, undefined, 'The ResourceHintWebpackPlugin does not accept any options');
}
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) {
var ext = path.extname(tag.attributes.href);
if (preloadDirective[ext]) {
tag.attributes.as = preloadDirective[ext];
}
return tag;
}
ResourceHintWebpackPlugin.prototype.apply = function (compiler) {
var self = this;
// Hook into the html-webpack-plugin processing
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-alter-asset-tags', function (htmlPluginData, callback) {
var htmlWebpackPluginOptions = htmlPluginData.plugin.options;
var pluginData = objectAssign({}, htmlPluginData);
var tags = {
prefetch: [],
// https://w3c.github.io/preload/#link-type-preload
preload: []
};
// Create Resource tags
Object.keys(tags).forEach(function (ResourceHintType) {
var filters;
if (htmlWebpackPluginOptions[ResourceHintType] === false) {
return;
}
// Add all files by default:
if (htmlWebpackPluginOptions[ResourceHintType] === undefined) {
filters = ['**/*.*'];
} else {
filters = [].concat(htmlWebpackPluginOptions[ResourceHintType]);
}
filters.forEach(function (filter) {
if (filter.indexOf('*') !== -1) {
Array.prototype.push.apply(tags[ResourceHintType], self.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
*/
ResourceHintWebpackPlugin.prototype.addResourceHintTags = function (ResourceHintType, filter, assetTags, htmlWebpackPluginOptions) {
var urls = assetTags
.map(function (tag) {
return tag.attributes.src || tag.attributes.href;
})
.filter(function (url) {
return url;
})
.filter(minimatch.filter(filter));
// Add a ResourceHint for every match
return urls.map(function (url) {
return createResourceHintTag(url, ResourceHintType, htmlWebpackPluginOptions);
});
};
module.exports = ResourceHintWebpackPlugin;