Skip to content

Commit

Permalink
fix: invalidate cache when a file name was changed (#171)
Browse files Browse the repository at this point in the history
  • Loading branch information
evilebottnawi committed Oct 10, 2019
1 parent c2efe18 commit 7e1d370
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 102 deletions.
215 changes: 114 additions & 101 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,133 +186,146 @@ class TerserPlugin {

const optimizeFn = async (compilation, chunks) => {
const processedAssets = new WeakSet();
const matchObject = ModuleFilenameHelpers.matchObject.bind(
// eslint-disable-next-line no-undefined
undefined,
this.options
);
const additionalChunkAssets = Array.from(
compilation.additionalChunkAssets || []
);
const filteredChunks = Array.from(chunks).filter(
(chunk) => this.options.chunkFilter && this.options.chunkFilter(chunk)
);
const chunksFiles = filteredChunks.reduce(
(acc, chunk) => acc.concat(Array.from(chunk.files || [])),
[]
);
const files = [].concat(additionalChunkAssets).concat(chunksFiles);
const tasks = [];

const { chunkFilter } = this.options;
files.forEach((file) => {
if (!matchObject(file)) {
return;
}

Array.from(chunks)
.filter((chunk) => chunkFilter && chunkFilter(chunk))
.reduce((acc, chunk) => acc.concat(Array.from(chunk.files || [])), [])
.concat(Array.from(compilation.additionalChunkAssets || []))
.filter(ModuleFilenameHelpers.matchObject.bind(null, this.options))
.forEach((file) => {
let inputSourceMap;
let inputSourceMap;

const asset = compilation.assets[file];
const asset = compilation.assets[file];

if (processedAssets.has(asset)) {
return;
}

try {
let input;
if (processedAssets.has(asset)) {
return;
}

if (this.options.sourceMap && asset.sourceAndMap) {
const { source, map } = asset.sourceAndMap();
try {
let input;

input = source;
if (this.options.sourceMap && asset.sourceAndMap) {
const { source, map } = asset.sourceAndMap();

if (TerserPlugin.isSourceMap(map)) {
inputSourceMap = map;
} else {
inputSourceMap = map;
input = source;

compilation.warnings.push(
new Error(`${file} contains invalid source map`)
);
}
if (TerserPlugin.isSourceMap(map)) {
inputSourceMap = map;
} else {
input = asset.source();
inputSourceMap = null;
inputSourceMap = map;

compilation.warnings.push(
new Error(`${file} contains invalid source map`)
);
}
} else {
input = asset.source();
inputSourceMap = null;
}

// Handling comment extraction
let commentsFilename = false;
// Handling comment extraction
let commentsFilename = false;

if (this.options.extractComments) {
commentsFilename =
this.options.extractComments.filename ||
'[file].LICENSE[query]';
if (this.options.extractComments) {
commentsFilename =
this.options.extractComments.filename || '[file].LICENSE[query]';

// Todo remove this in next major release
if (typeof commentsFilename === 'function') {
commentsFilename = commentsFilename.bind(null, file);
}
// Todo remove this in next major release
if (typeof commentsFilename === 'function') {
commentsFilename = commentsFilename.bind(null, file);
}

let query = '';
let filename = file;
let query = '';
let filename = file;

const querySplit = filename.indexOf('?');
const querySplit = filename.indexOf('?');

if (querySplit >= 0) {
query = filename.substr(querySplit);
filename = filename.substr(0, querySplit);
}
if (querySplit >= 0) {
query = filename.substr(querySplit);
filename = filename.substr(0, querySplit);
}

const lastSlashIndex = filename.lastIndexOf('/');
const lastSlashIndex = filename.lastIndexOf('/');

const basename =
lastSlashIndex === -1
? filename
: filename.substr(lastSlashIndex + 1);
const basename =
lastSlashIndex === -1
? filename
: filename.substr(lastSlashIndex + 1);

const data = { filename, basename, query };
const data = { filename, basename, query };

commentsFilename = compilation.getPath(commentsFilename, data);
}
commentsFilename = compilation.getPath(commentsFilename, data);
}

if (
commentsFilename &&
TerserPlugin.hasAsset(commentsFilename, compilation.assets)
) {
// Todo make error and stop uglifing in next major release
compilation.warnings.push(
new Error(
`The comment file "${TerserPlugin.removeQueryString(
commentsFilename
)}" conflicts with an existing asset, this may lead to code corruption, please use a different name`
)
);
}
if (
commentsFilename &&
TerserPlugin.hasAsset(commentsFilename, compilation.assets)
) {
// Todo make error and stop uglifing in next major release
compilation.warnings.push(
new Error(
`The comment file "${TerserPlugin.removeQueryString(
commentsFilename
)}" conflicts with an existing asset, this may lead to code corruption, please use a different name`
)
);
}

const task = {
file,
input,
inputSourceMap,
commentsFilename,
extractComments: this.options.extractComments,
terserOptions: this.options.terserOptions,
minify: this.options.minify,
const task = {
file,
input,
inputSourceMap,
commentsFilename,
extractComments: this.options.extractComments,
terserOptions: this.options.terserOptions,
minify: this.options.minify,
};

if (this.options.cache) {
const defaultCacheKeys = {
terser: terserPackageJson.version,
// eslint-disable-next-line global-require
'terser-webpack-plugin': require('../package.json').version,
'terser-webpack-plugin-options': this.options,
nodeVersion: process.version,
filename: file,
contentHash: crypto
.createHash('md4')
.update(input)
.digest('hex'),
};

if (this.options.cache) {
const defaultCacheKeys = {
terser: terserPackageJson.version,
node_version: process.version,
// eslint-disable-next-line global-require
'terser-webpack-plugin': require('../package.json').version,
'terser-webpack-plugin-options': this.options,
hash: crypto
.createHash('md4')
.update(input)
.digest('hex'),
};

task.cacheKeys = this.options.cacheKeys(defaultCacheKeys, file);
}

tasks.push(task);
} catch (error) {
compilation.errors.push(
TerserPlugin.buildError(
error,
file,
TerserPlugin.buildSourceMap(inputSourceMap),
new RequestShortener(compiler.context)
)
);
task.cacheKeys = this.options.cacheKeys(defaultCacheKeys, file);
}
});

tasks.push(task);
} catch (error) {
compilation.errors.push(
TerserPlugin.buildError(
error,
file,
TerserPlugin.buildSourceMap(inputSourceMap),
new RequestShortener(compiler.context)
)
);
}
});

if (tasks.length === 0) {
return Promise.resolve();
Expand Down
28 changes: 28 additions & 0 deletions test/__snapshots__/cache-option.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`cache option should match snapshot and invalid cache when entry point was renamed: assets 1`] = `
Object {
"five.js": "!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&\\"object\\"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,\\"default\\",{enumerable:!0,value:e}),2&t&&\\"string\\"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,\\"a\\",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=\\"\\",n(n.s=4)}({4:function(e,t){e.exports=function(){console.log(7)}}});",
"four.js": "!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&\\"object\\"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,\\"default\\",{enumerable:!0,value:e}),2&t&&\\"string\\"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,\\"a\\",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p=\\"\\",r(r.s=3)}({3:function(e,t){e.exports=class{}}});",
"one.js": "!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&\\"object\\"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,\\"default\\",{enumerable:!0,value:e}),2&t&&\\"string\\"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,\\"a\\",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=\\"\\",n(n.s=0)}([function(e,t){e.exports=function(){console.log(7)}}]);",
"three.js": "!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&\\"object\\"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,\\"default\\",{enumerable:!0,value:e}),2&t&&\\"string\\"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,\\"a\\",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p=\\"\\",r(r.s=2)}({2:function(e,t){e.exports=()=>/test/}});",
"two.js": "!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&\\"object\\"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,\\"default\\",{enumerable:!0,value:e}),2&t&&\\"string\\"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,\\"a\\",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p=\\"\\",r(r.s=1)}([,function(e,t){e.exports=\\"string\\"}]);",
}
`;

exports[`cache option should match snapshot and invalid cache when entry point was renamed: assets 2`] = `
Object {
"five.js": "!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&\\"object\\"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,\\"default\\",{enumerable:!0,value:e}),2&t&&\\"string\\"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,\\"a\\",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=\\"\\",n(n.s=4)}({4:function(e,t){e.exports=function(){console.log(7)}}});",
"four.js": "!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&\\"object\\"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,\\"default\\",{enumerable:!0,value:e}),2&t&&\\"string\\"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,\\"a\\",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p=\\"\\",r(r.s=3)}({3:function(e,t){e.exports=class{}}});",
"onne.js": "!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&\\"object\\"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,\\"default\\",{enumerable:!0,value:e}),2&t&&\\"string\\"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,\\"a\\",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=\\"\\",n(n.s=0)}([function(e,t){e.exports=function(){console.log(7)}}]);",
"three.js": "!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&\\"object\\"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,\\"default\\",{enumerable:!0,value:e}),2&t&&\\"string\\"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,\\"a\\",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p=\\"\\",r(r.s=2)}({2:function(e,t){e.exports=()=>/test/}});",
"two.js": "!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&\\"object\\"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,\\"default\\",{enumerable:!0,value:e}),2&t&&\\"string\\"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,\\"a\\",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p=\\"\\",r(r.s=1)}([,function(e,t){e.exports=\\"string\\"}]);",
}
`;

exports[`cache option should match snapshot and invalid cache when entry point was renamed: errors 1`] = `Array []`;

exports[`cache option should match snapshot and invalid cache when entry point was renamed: errors 2`] = `Array []`;

exports[`cache option should match snapshot and invalid cache when entry point was renamed: warnings 1`] = `Array []`;

exports[`cache option should match snapshot and invalid cache when entry point was renamed: warnings 2`] = `Array []`;

exports[`cache option should match snapshot for errors into the "cacheKeys" option: errors 1`] = `
Array [
"Error: five.js from Terser
Expand Down
Loading

0 comments on commit 7e1d370

Please sign in to comment.