Skip to content

Commit 53e4cbe

Browse files
Refactor into class and restructure
1 parent 285e92d commit 53e4cbe

1 file changed

Lines changed: 75 additions & 89 deletions

File tree

lib/plugin.js

Lines changed: 75 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,95 @@
1-
const _ = require('lodash');
21
require('require-safe')('html-webpack-plugin');
32

4-
function ChunkHashExclude(options) {
5-
this.options = _.assign({
6-
excludeJs: [],
7-
excludeCss: [],
8-
publicCssPath: '',
9-
cancelHtmlHash: true,
10-
}, options);
3+
// Escape a string suitable for using in regex
4+
function esc(string) {
5+
return string ? string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') : string;
116
}
127

13-
ChunkHashExclude.prototype.cancelAssetsHash = (compilation, callback) => {
14-
compilation.chunks.forEach((chunk, i) => {
15-
chunk.files.forEach((filename, j) => {
16-
if (this.options.excludeJs.indexOf(chunk.name) > -1 && filename.indexOf('js') > -1) {
17-
let reg = new RegExp(`(js/)(${chunk.name})(.*)(.js|.js.map)`);
18-
if (filename.replace(reg, '$1$2$4') !== filename) {
19-
compilation.chunks[i].files.splice(j, 1, filename.replace(reg, '$1$2$4'));
20-
compilation.assets[filename.replace(reg, '$1$2$4')] = compilation.assets[filename];
21-
delete compilation.assets[filename];
8+
class WebpackHashExcludePlugin {
9+
options;
10+
11+
constructor(options) {
12+
this.options = Object.assign({
13+
excludeJs: [],
14+
excludeCss: [],
15+
removeHtmlHash: true,
16+
}, options);
17+
}
18+
19+
removeAssetsHash(compilation, callback){
20+
const renameChunkFiles = (compilation, index, chunkName, filename, suffix) => {
21+
const reg = new RegExp(`(${esc(chunkName)})(?:.*)(\.${suffix}|\.${suffix}\.map)$`);
22+
const newFilename = filename.replace(reg, '$1$2');
23+
if (newFilename === filename) return;
24+
compilation.chunks[index].files.splice(index, 1, newFilename);
25+
compilation.assets[newFilename] = compilation.assets[filename];
26+
delete compilation.assets[filename];
27+
28+
29+
compilation.entrypoints.get(chunkName).chunks.map((chunk) => {
30+
if (chunk.name === chunkName) {
31+
chunk.files = chunk.files.map((file) => file.replace(reg, '$1$2'));
2232
}
23-
}
24-
if (filename.indexOf('css') > -1) {
25-
let reg = new RegExp(`(css/)(${chunk.name})(.*)(.css|.css.map)`);
26-
let newFilename = filename.replace(reg, '$1$2$4');
27-
if (this.options.excludeCss.indexOf(chunk.name) > -1) {
28-
if (newFilename !== filename) {
29-
compilation.chunks[i].files.splice(j, 1, newFilename);
30-
compilation.assets[newFilename] = compilation.assets[filename];
31-
delete compilation.assets[filename];
32-
}
33+
});
34+
};
35+
36+
compilation.chunks.forEach((chunk) => {
37+
chunk.files.forEach((filename, index) => {
38+
if (this.options.excludeJs.indexOf(chunk.name) > -1 && filename.indexOf('js') > -1) {
39+
renameChunkFiles(compilation, index, chunk.name, filename, 'js');
3340
}
34-
}
41+
if (this.options.excludeCss.indexOf(chunk.name) > -1 && filename.indexOf('css') > -1) {
42+
renameChunkFiles(compilation, index, chunk.name, filename, 'css');
43+
}
44+
});
3545
});
36-
});
37-
callback();
38-
};
46+
callback();
47+
}
3948

40-
ChunkHashExclude.prototype.cancelHtmlHash = (compilation, callback) => {
41-
compilation.chunks.map(chunk => {
42-
if (this.options.excludeJs.indexOf(chunk.names[0]) > -1) {
43-
let reg = new RegExp(`(js/)(${chunk.names[0]})(.*)(.js)`);
44-
let index = -1;
45-
compilation.body.some((item, i) => {
46-
if (item.attributes.src.indexOf(chunk.names[0]) > -1) {
47-
index = i;
48-
return true;
49+
removeHtmlHash(compilation, callback) {
50+
const chunksMapCallback = (chunk) => {
51+
const chunkName = chunk.names[0];
52+
const getIndex = (item) => item.attributes.href.indexOf(chunkName) > -1;
53+
let index;
54+
55+
if (this.options.excludeJs.indexOf(chunkName) > -1) {
56+
const reg = new RegExp(`^(${esc(chunkName)})(?:.*)(\.js)$`);
57+
index = compilation.body.findIndex(getIndex);
58+
if (index > -1) {
59+
compilation.body[index].attributes.src = compilation.body[index].attributes.src.replace(reg, '$1$2');
4960
}
50-
return false;
51-
});
52-
if (index > -1) compilation.body[index].attributes.src = compilation.body[index].attributes.src.replace(reg, '$1$2$4');
53-
}
54-
if (this.options.excludeCss.indexOf(chunk.names[0]) > -1) {
55-
let reg = new RegExp(`(css/)(${chunk.names[0]})(.*)(.css)`);
56-
let index = -1;
57-
compilation.head.some((item, i) => {
58-
if (item.attributes.href.indexOf(chunk.names[0]) > -1) {
59-
index = i;
60-
return true;
61+
}
62+
if (this.options.excludeCss.indexOf(chunkName) > -1) {
63+
const reg = new RegExp(`^(${esc(chunkName)})(?:.*)(\.css)$`);
64+
index = compilation.head.findIndex(getIndex);
65+
if (index > -1) {
66+
compilation.head[index].attributes.href = compilation.head[index].attributes.href.replace(reg, '$1$2');
6167
}
62-
return false;
63-
});
64-
if (index > -1) compilation.head[index].attributes.href = compilation.head[index].attributes.href.replace(reg, '$1$2$4');
65-
}
66-
});
67-
callback();
68-
};
69-
// Remove the hash value of the corresponding chunk resource file in the html template
70-
ChunkHashExclude.prototype.apply = (compiler) => {
71-
if (compiler.hooks) {
72-
if (this.options.publicCssPath) {
73-
compiler.hooks.thisCompilation.tap('thisCompilation', compilation => {
74-
compilation.mainTemplate.hooks.requireEnsure.tap('requireEnsure', (source, chunk, hash) => {
75-
return source.replace('__webpack_require__.p', `'${this.options.publicCssPath}'`);
76-
});
77-
});
78-
}
68+
}
69+
};
70+
compilation.chunks.map(chunksMapCallback);
71+
callback();
72+
}
73+
74+
apply(compiler) {
75+
// Remove the has from asset file names
7976
compiler.hooks.emit.tapAsync('emit', (compilation, callback) => {
80-
this.cancelAssetsHash(compilation, callback);
77+
this.removeAssetsHash(compilation, callback);
78+
});
79+
// Remove the hash value of the corresponding chunk resource file
80+
compiler.hooks.thisCompilation.tap('thisCompilation', compilation => {
81+
const requireEnsure = (source) => source.replace('__webpack_require__.p', `'${compilation.options.output.publicPath}'`);
82+
compilation.mainTemplate.hooks.requireEnsure.tap('requireEnsure', requireEnsure);
8183
});
8284
// Replace the hash value of the html static resource
83-
if (this.options.cancelHtmlHash) {
85+
if (this.options.removeHtmlHash) {
8486
compiler.hooks.compilation.tap('compilation', (compilation) => {
8587
compilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync('compilation', (compilation, callback) => {
86-
this.cancelHtmlHash(compilation, callback);
87-
});
88-
});
89-
}
90-
} else {
91-
compiler.plugin('emit', (compilation, callback) => {
92-
cancelAssetsHash(compilation, callback);
93-
});
94-
if (this.options.cancelHtmlHash) {
95-
compiler.plugin('html-webpack-plugin-alter-asset-tags', (compilation, callback) => {
96-
cancelHtmlHash(compilation, callback);
97-
});
98-
}
99-
if (this.options.publicCssPath) {
100-
compiler.plugin('this-compilation', compilation => {
101-
compilation.mainTemplate.plugin('require-ensure', (source, chunk, hash) => {
102-
return source.replace('__webpack_require__.p', `'${this.options.publicCssPath}'`);
88+
this.removeHtmlHash(compilation, callback);
10389
});
10490
});
10591
}
10692
}
107-
};
93+
}
10894

109-
module.exports = ChunkHashExclude;
95+
module.exports = WebpackHashExcludePlugin;

0 commit comments

Comments
 (0)