Skip to content

Commit 1c2994f

Browse files
author
wilsonsliu
committed
feature(sourcemap&cssMinify):ignore sourcemap inline comment while generate hash & support optimize-cssnano-plugin
1 parent 0b4adc2 commit 1c2994f

File tree

2 files changed

+57
-3
lines changed

2 files changed

+57
-3
lines changed

src/OutputHash.js

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ function OutputHash({ validateOutput = false, validateOutputRegex = /^.*$/ } = {
1313
function replaceStringInAsset(asset, source, target) {
1414
const sourceRE = new RegExp(source, 'g');
1515

16+
// when optimize-cssnano-plugin disable css sourcemap, map file will be delete,so this may be undefined
17+
if (!asset) {
18+
return false;
19+
}
20+
1621
if (typeof asset === 'string') {
1722
return asset.replace(sourceRE, target);
1823
}
@@ -40,7 +45,18 @@ function replaceStringInAsset(asset, source, target) {
4045
asset.children = asset.children.map(child => replaceStringInAsset(child, source, target));
4146
return asset;
4247
}
43-
48+
// support config OutputHash after optimize-cssnano-plugin, genrate hash after minify
49+
if (asset.source && typeof asset.source === 'function') {
50+
const processedCss = asset.source().replace(sourceRE, target);
51+
return {
52+
source: function() {
53+
return processedCss;
54+
},
55+
size: function() {
56+
return processedCss.length;
57+
},
58+
};
59+
}
4460
throw new Error(
4561
`Unknown asset type (${asset.constructor.name})!. ` +
4662
'Unfortunately this type of asset is not supported yet. ' +
@@ -62,11 +78,13 @@ function reHashChunk(chunk, assets, hashFn, nameMap) {
6278
const asset = assets[oldChunkName];
6379
const { fullHash, shortHash: newHash } = hashFn(asset.source());
6480

65-
let newChunkName;
81+
let newChunkName, oldHash;
6682

6783
if (oldChunkName.includes(chunk.renderedHash)) {
6884
// Save the hash map for replacing the secondary files
6985
nameMap[chunk.renderedHash] = newHash;
86+
87+
oldHash = chunk.renderedHash;
7088
newChunkName = oldChunkName.replace(chunk.renderedHash, newHash);
7189

7290
// Keep the chunk hashes in sync
@@ -94,18 +112,40 @@ function reHashChunk(chunk, assets, hashFn, nameMap) {
94112

95113
// Save the hash map for replacing the secondary files
96114
nameMap[module.renderedHash] = newHash;
115+
116+
oldHash = module.renderedHash;
97117
newChunkName = oldChunkName.replace(module.renderedHash, newHash);
98118

99119
// Keep the module hashes in sync
100120
module.hash = fullHash;
101121
module.renderedHash = newHash;
102122
}
103123

124+
// Change inline sourcemap comments to include the new hash
125+
replaceStringInAsset(asset, oldHash, newHash);
126+
104127
// Change file name to include the new hash
105128
chunk.files[index] = newChunkName;
106129
asset._name = newChunkName;
107130
delete assets[oldChunkName];
108131
assets[newChunkName] = asset;
132+
133+
// replace map file hash
134+
const oldMapChunkName = oldChunkName + '.map';
135+
const newMapChunkName = newChunkName + '.map';
136+
const mapAsset = assets[oldMapChunkName];
137+
if (!mapAsset) {
138+
return false;
139+
}
140+
141+
chunk.files.forEach((el, i) => {
142+
if (el == oldMapChunkName) {
143+
chunk.files[i] = newMapChunkName;
144+
}
145+
});
146+
147+
delete assets[oldMapChunkName];
148+
assets[newMapChunkName] = mapAsset;
109149
});
110150

111151
// Update the content of the rest of the files in the chunk
@@ -150,8 +190,15 @@ OutputHash.prototype.apply = function apply(compiler) {
150190
compiler.hooks.emit.taps[0].name !== 'OutputHash'
151191
) {
152192
debugger;
193+
let isHasMatchOutputHash = false;
153194
const plugins = compiler.hooks.emit.taps
154-
.filter(plugin => plugin.name != 'OutputHash')
195+
.filter(plugin => {
196+
if (isHasMatchOutputHash) {
197+
return false;
198+
}
199+
isHasMatchOutputHash = plugin.name === 'OutputHash';
200+
return !isHasMatchOutputHash;
201+
})
155202
.map(plugin => ` * ${plugin.name}`)
156203
.join('\n');
157204

@@ -173,6 +220,10 @@ OutputHash.prototype.apply = function apply(compiler) {
173220

174221
// Reuses webpack options
175222
hashFn = input => {
223+
// generate hash of content without sourcemap
224+
const mapCommentReg = /\s\/[\/|*]#\s?sourceMappingURL=.*.map(\s\*\/)?/g;
225+
input = input.replace(mapCommentReg, '');
226+
176227
const hashObj = crypto.createHash(hashFunction).update(input);
177228
if (hashSalt) hashObj.update(hashSalt);
178229
const fullHash = hashObj.digest(hashDigest);

test/test.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ const makeHashFn = ({
1414
hashDigestLength = 20,
1515
hashSalt = null,
1616
} = {}) => input => {
17+
// generate hash of content without sourcemap
18+
const mapCommentReg = /\s\/[\/|*]#\s?sourceMappingURL=.*.map(\s\*\/)?/g;
19+
input = input.replace(mapCommentReg, '');
1720
const hashObj = crypto.createHash(hashFunction).update(input);
1821
if (hashSalt) hashObj.update(hashSalt);
1922
const fullHash = hashObj.digest(hashDigest);

0 commit comments

Comments
 (0)