terser-webpack-plugin
Advanced tools
Comparing version 2.3.6 to 3.0.0
@@ -5,2 +5,14 @@ # Changelog | ||
## [3.0.0](https://github.com/webpack-contrib/terser-webpack-plugin/compare/v2.3.6...v3.0.0) (2020-05-01) | ||
### ⚠ BREAKING CHANGES | ||
* minimum supported Node.js version is `10.13` | ||
* the `chunkFilter` was removed, please use `test`/`include`/`exclude` options | ||
* change arguments order for the `warningFilter` option from `Function<(warning, file, source) -> Boolean>` to `Function<(file, warning, source) -> Boolean>` | ||
* when the `extractComments.filename` option is a function it pass only one argument and it is object with `filename`, `basename`, `query` and `hash` properties | ||
* if the value from the `extractComments.filename` option conflicts with existing assets, an error will be thrown instead of a warning | ||
* use the `optimizeAssets` hook for webpack@5 | ||
### [2.3.6](https://github.com/webpack-contrib/terser-webpack-plugin/compare/v2.3.5...v2.3.6) (2020-04-25) | ||
@@ -7,0 +19,0 @@ |
@@ -10,2 +10,4 @@ "use strict"; | ||
var _os = _interopRequireDefault(require("os")); | ||
var _sourceMap = require("source-map"); | ||
@@ -25,5 +27,9 @@ | ||
var _pLimit = _interopRequireDefault(require("p-limit")); | ||
var _jestWorker = _interopRequireDefault(require("jest-worker")); | ||
var _options = _interopRequireDefault(require("./options.json")); | ||
var _TaskRunner = _interopRequireDefault(require("./TaskRunner")); | ||
var _minify = require("./minify"); | ||
@@ -85,3 +91,2 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
static buildError(error, file, sourceMap, requestShortener) { | ||
// Handling error which should have line, col, filename and message | ||
if (error.line) { | ||
@@ -110,3 +115,3 @@ const original = sourceMap && sourceMap.originalPositionFor({ | ||
let locationMessage = ''; | ||
let source = null; | ||
let source; | ||
@@ -132,6 +137,5 @@ if (sourceMap) { | ||
} | ||
} // Todo change order in next major release | ||
} | ||
if (warningsFilter && !warningsFilter(warning, source, file)) { | ||
if (warningsFilter && !warningsFilter(warning, file, source)) { | ||
return null; | ||
@@ -154,4 +158,4 @@ } | ||
static hasAsset(commentFilename, assets) { | ||
const assetFilenames = Object.keys(assets).map(assetFilename => TerserPlugin.removeQueryString(assetFilename)); | ||
static hasAsset(commentFilename, compilation) { | ||
const assetFilenames = Object.keys(compilation.assets).map(assetFilename => TerserPlugin.removeQueryString(assetFilename)); | ||
return assetFilenames.includes(TerserPlugin.removeQueryString(commentFilename)); | ||
@@ -164,200 +168,284 @@ } | ||
static getAvailableNumberOfCores(parallel) { | ||
// In some cases cpus() returns undefined | ||
// https://github.com/nodejs/node/issues/19022 | ||
const cpus = _os.default.cpus() || { | ||
length: 1 | ||
}; | ||
return parallel === true ? cpus.length - 1 : Math.min(Number(parallel) || 0, cpus.length - 1); | ||
} | ||
*taskGenerator(compiler, compilation, allExtractedComments, file) { | ||
const assetSource = compilation.assets[file]; | ||
let input; | ||
let inputSourceMap; | ||
const asset = compilation.assets[file]; | ||
try { | ||
let input; | ||
if (this.options.sourceMap && assetSource.sourceAndMap) { | ||
const { | ||
source, | ||
map | ||
} = assetSource.sourceAndMap(); | ||
input = source; | ||
if (this.options.sourceMap && asset.sourceAndMap) { | ||
const { | ||
source, | ||
map | ||
} = asset.sourceAndMap(); | ||
input = source; | ||
if (TerserPlugin.isSourceMap(map)) { | ||
inputSourceMap = map; | ||
} else { | ||
inputSourceMap = map; | ||
compilation.warnings.push(new Error(`${file} contains invalid source map`)); | ||
} | ||
if (TerserPlugin.isSourceMap(map)) { | ||
inputSourceMap = map; | ||
} else { | ||
input = asset.source(); | ||
inputSourceMap = null; | ||
} // Handling comment extraction | ||
inputSourceMap = map; | ||
compilation.warnings.push(new Error(`${file} contains invalid source map`)); | ||
} | ||
} else { | ||
input = assetSource.source(); | ||
inputSourceMap = null; | ||
} // Handling comment extraction | ||
let commentsFilename = false; | ||
let commentsFilename = false; | ||
if (this.options.extractComments) { | ||
commentsFilename = this.options.extractComments.filename || '[file].LICENSE.txt[query]'; | ||
if (this.options.extractComments) { | ||
commentsFilename = this.options.extractComments.filename || '[file].LICENSE.txt[query]'; | ||
let query = ''; | ||
let filename = file; | ||
const querySplit = filename.indexOf('?'); | ||
if (TerserPlugin.isWebpack4()) { | ||
// Todo remove this in next major release | ||
if (typeof commentsFilename === 'function') { | ||
commentsFilename = commentsFilename.bind(null, file); | ||
} | ||
} | ||
if (querySplit >= 0) { | ||
query = filename.substr(querySplit); | ||
filename = filename.substr(0, querySplit); | ||
} | ||
let query = ''; | ||
let filename = file; | ||
const querySplit = filename.indexOf('?'); | ||
const lastSlashIndex = filename.lastIndexOf('/'); | ||
const basename = lastSlashIndex === -1 ? filename : filename.substr(lastSlashIndex + 1); | ||
const data = { | ||
filename, | ||
basename, | ||
query | ||
}; | ||
commentsFilename = compilation.getPath(commentsFilename, data); | ||
if (querySplit >= 0) { | ||
query = filename.substr(querySplit); | ||
filename = filename.substr(0, querySplit); | ||
} | ||
if (TerserPlugin.hasAsset(commentsFilename, compilation)) { | ||
compilation.errors.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`)); | ||
yield false; | ||
} | ||
} | ||
const lastSlashIndex = filename.lastIndexOf('/'); | ||
const basename = lastSlashIndex === -1 ? filename : filename.substr(lastSlashIndex + 1); | ||
const data = { | ||
filename, | ||
basename, | ||
query | ||
}; | ||
commentsFilename = compilation.getPath(commentsFilename, data); | ||
const callback = taskResult => { | ||
let { | ||
code | ||
} = taskResult; | ||
const { | ||
error, | ||
map, | ||
warnings | ||
} = taskResult; | ||
const { | ||
extractedComments | ||
} = taskResult; | ||
let sourceMap = null; | ||
if (error || warnings && warnings.length > 0) { | ||
sourceMap = TerserPlugin.buildSourceMap(inputSourceMap); | ||
} // Handling results | ||
// Error case: add errors, and go to next file | ||
if (error) { | ||
compilation.errors.push(TerserPlugin.buildError(error, file, sourceMap, new _RequestShortener.default(compiler.context))); | ||
return; | ||
} | ||
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 hasExtractedComments = commentsFilename && extractedComments && extractedComments.length > 0; | ||
const hasBannerForExtractedComments = hasExtractedComments && this.options.extractComments.banner !== false; | ||
let outputSource; | ||
let shebang; | ||
if (hasExtractedComments && hasBannerForExtractedComments && code.startsWith('#!')) { | ||
const firstNewlinePosition = code.indexOf('\n'); | ||
shebang = code.substring(0, firstNewlinePosition); | ||
code = code.substring(firstNewlinePosition + 1); | ||
} | ||
const callback = taskResult => { | ||
let { | ||
code | ||
} = taskResult; | ||
const { | ||
error, | ||
map, | ||
warnings | ||
} = taskResult; | ||
const { | ||
extractedComments | ||
} = taskResult; | ||
let sourceMap = null; | ||
if (map) { | ||
outputSource = new _webpackSources.SourceMapSource(code, file, map, input, inputSourceMap, true); | ||
} else { | ||
outputSource = new _webpackSources.RawSource(code); | ||
} // Write extracted comments to commentsFilename | ||
if (error || warnings && warnings.length > 0) { | ||
sourceMap = TerserPlugin.buildSourceMap(inputSourceMap); | ||
} // Handling results | ||
// Error case: add errors, and go to next file | ||
if (hasExtractedComments) { | ||
if (!allExtractedComments[commentsFilename]) { | ||
// eslint-disable-next-line no-param-reassign | ||
allExtractedComments[commentsFilename] = []; | ||
} // eslint-disable-next-line no-param-reassign | ||
if (error) { | ||
compilation.errors.push(TerserPlugin.buildError(error, file, sourceMap, new _RequestShortener.default(compiler.context))); | ||
return; | ||
allExtractedComments[commentsFilename] = allExtractedComments[commentsFilename].concat(extractedComments); // Add a banner to the original file | ||
if (hasBannerForExtractedComments) { | ||
let banner = this.options.extractComments.banner || `For license information please see ${_path.default.relative(_path.default.dirname(file), commentsFilename).replace(/\\/g, '/')}`; | ||
if (typeof banner === 'function') { | ||
banner = banner(commentsFilename); | ||
} | ||
if (banner) { | ||
outputSource = new _webpackSources.ConcatSource(shebang ? `${shebang}\n` : '', `/*! ${banner} */\n`, outputSource); | ||
} | ||
} | ||
} // Updating assets | ||
// eslint-disable-next-line no-param-reassign | ||
const hasExtractedComments = commentsFilename && extractedComments && extractedComments.length > 0; | ||
const hasBannerForExtractedComments = hasExtractedComments && this.options.extractComments.banner !== false; | ||
let outputSource; | ||
let shebang; | ||
if (hasExtractedComments && hasBannerForExtractedComments && code.startsWith('#!')) { | ||
const firstNewlinePosition = code.indexOf('\n'); | ||
shebang = code.substring(0, firstNewlinePosition); | ||
code = code.substring(firstNewlinePosition + 1); | ||
compilation.assets[file] = outputSource; // Handling warnings | ||
if (warnings && warnings.length > 0) { | ||
warnings.forEach(warning => { | ||
const builtWarning = TerserPlugin.buildWarning(warning, file, sourceMap, new _RequestShortener.default(compiler.context), this.options.warningsFilter); | ||
if (builtWarning) { | ||
compilation.warnings.push(builtWarning); | ||
} | ||
}); | ||
} | ||
}; | ||
const task = { | ||
file, | ||
input, | ||
inputSourceMap, | ||
commentsFilename, | ||
extractComments: this.options.extractComments, | ||
terserOptions: this.options.terserOptions, | ||
minify: this.options.minify, | ||
callback | ||
}; | ||
if (TerserPlugin.isWebpack4()) { | ||
const { | ||
outputOptions: { | ||
hashSalt, | ||
hashDigest, | ||
hashDigestLength, | ||
hashFunction | ||
} | ||
} = compilation; | ||
if (map) { | ||
outputSource = new _webpackSources.SourceMapSource(code, file, map, input, inputSourceMap, true); | ||
} else { | ||
outputSource = new _webpackSources.RawSource(code); | ||
} // Write extracted comments to commentsFilename | ||
const hash = _webpack.util.createHash(hashFunction); | ||
if (hashSalt) { | ||
hash.update(hashSalt); | ||
} | ||
if (hasExtractedComments) { | ||
if (!allExtractedComments[commentsFilename]) { | ||
// eslint-disable-next-line no-param-reassign | ||
allExtractedComments[commentsFilename] = []; | ||
} // eslint-disable-next-line no-param-reassign | ||
hash.update(input); | ||
const digest = hash.digest(hashDigest); | ||
if (this.options.cache) { | ||
const defaultCacheKeys = { | ||
terser: _package.default.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: digest.substr(0, hashDigestLength) | ||
}; | ||
task.cacheKeys = this.options.cacheKeys(defaultCacheKeys, file); | ||
} | ||
} else { | ||
// For webpack@5 cache | ||
task.assetSource = assetSource; | ||
task.cacheKeys = { | ||
terser: _package.default.version, | ||
// eslint-disable-next-line global-require | ||
'terser-webpack-plugin': require('../package.json').version, | ||
'terser-webpack-plugin-options': this.options | ||
}; | ||
} | ||
allExtractedComments[commentsFilename] = allExtractedComments[commentsFilename].concat(extractedComments); // Add a banner to the original file | ||
yield task; | ||
} | ||
if (hasBannerForExtractedComments) { | ||
let banner = this.options.extractComments.banner || `For license information please see ${_path.default.relative(_path.default.dirname(file), commentsFilename).replace(/\\/g, '/')}`; | ||
async runTask(task) { | ||
if (this.worker) { | ||
return this.worker.transform((0, _serializeJavascript.default)(task)); | ||
} | ||
if (typeof banner === 'function') { | ||
banner = banner(commentsFilename); | ||
} | ||
return (0, _minify.minify)(task); | ||
} | ||
if (banner) { | ||
outputSource = new _webpackSources.ConcatSource(shebang ? `${shebang}\n` : '', `/*! ${banner} */\n`, outputSource); | ||
} | ||
} | ||
} // Updating assets | ||
// eslint-disable-next-line no-param-reassign | ||
async runTasks() { | ||
const availableNumberOfCores = TerserPlugin.getAvailableNumberOfCores(this.options.parallel); | ||
let concurrency = Infinity; | ||
if (availableNumberOfCores > 0) { | ||
// Do not create unnecessary workers when the number of files is less than the available cores, it saves memory | ||
const numWorkers = Math.min(this.assetNames.length, availableNumberOfCores); | ||
concurrency = numWorkers; | ||
this.worker = new _jestWorker.default(require.resolve('./minify'), { | ||
numWorkers | ||
}); // https://github.com/facebook/jest/issues/8872#issuecomment-524822081 | ||
compilation.assets[file] = outputSource; // Handling warnings | ||
const workerStdout = this.worker.getStdout(); | ||
if (warnings && warnings.length > 0) { | ||
warnings.forEach(warning => { | ||
const builtWarning = TerserPlugin.buildWarning(warning, file, sourceMap, new _RequestShortener.default(compiler.context), this.options.warningsFilter); | ||
if (workerStdout) { | ||
workerStdout.on('data', chunk => { | ||
return process.stdout.write(chunk); | ||
}); | ||
} | ||
if (builtWarning) { | ||
compilation.warnings.push(builtWarning); | ||
} | ||
}); | ||
const workerStderr = this.worker.getStderr(); | ||
if (workerStderr) { | ||
workerStderr.on('data', chunk => { | ||
return process.stderr.write(chunk); | ||
}); | ||
} | ||
} | ||
const limit = (0, _pLimit.default)(concurrency); | ||
const scheduledTasks = []; | ||
for (const assetName of this.assetNames) { | ||
const enqueue = async task => { | ||
let taskResult; | ||
try { | ||
taskResult = await this.runTask(task); | ||
} catch (error) { | ||
taskResult = { | ||
error | ||
}; | ||
} | ||
}; | ||
const task = { | ||
asset, | ||
file, | ||
input, | ||
inputSourceMap, | ||
commentsFilename, | ||
extractComments: this.options.extractComments, | ||
terserOptions: this.options.terserOptions, | ||
minify: this.options.minify, | ||
callback | ||
if (this.cache.isEnabled() && !taskResult.error) { | ||
taskResult = await this.cache.store(task, taskResult).then(() => taskResult, () => taskResult); | ||
} | ||
task.callback(taskResult); | ||
return taskResult; | ||
}; | ||
if (TerserPlugin.isWebpack4()) { | ||
const { | ||
outputOptions: { | ||
hashSalt, | ||
hashDigest, | ||
hashDigestLength, | ||
hashFunction | ||
} | ||
} = compilation; | ||
scheduledTasks.push(limit(() => { | ||
const task = this.getTaskForAsset(assetName).next().value; | ||
const hash = _webpack.util.createHash(hashFunction); | ||
if (!task) { | ||
// Something went wrong, for example the `cacheKeys` option throw an error | ||
return Promise.resolve(); | ||
} | ||
if (hashSalt) { | ||
hash.update(hashSalt); | ||
if (this.cache.isEnabled()) { | ||
return this.cache.get(task).then(taskResult => task.callback(taskResult), () => enqueue(task)); | ||
} | ||
hash.update(input); | ||
const digest = hash.digest(hashDigest); | ||
return enqueue(task); | ||
})); | ||
} | ||
if (this.options.cache) { | ||
const defaultCacheKeys = { | ||
terser: _package.default.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: digest.substr(0, hashDigestLength) | ||
}; | ||
task.cacheKeys = this.options.cacheKeys(defaultCacheKeys, file); | ||
} | ||
} else { | ||
task.cacheKeys = { | ||
terser: _package.default.version, | ||
// eslint-disable-next-line global-require | ||
'terser-webpack-plugin': require('../package.json').version, | ||
'terser-webpack-plugin-options': this.options | ||
}; | ||
} | ||
return Promise.all(scheduledTasks); | ||
} | ||
yield task; | ||
} catch (error) { | ||
compilation.errors.push(TerserPlugin.buildError(error, file, TerserPlugin.buildSourceMap(inputSourceMap), new _RequestShortener.default(compiler.context))); | ||
async exitTasks() { | ||
if (!this.worker) { | ||
return Promise.resolve(); | ||
} | ||
return this.worker.end(); | ||
} | ||
@@ -371,3 +459,3 @@ | ||
} = compiler.options; | ||
this.options.sourceMap = typeof this.options.sourceMap === 'undefined' ? devtool && !devtool.includes('eval') && !devtool.includes('cheap') && (devtool.includes('source-map') || // Todo remove when `webpack@5` support will be dropped | ||
this.options.sourceMap = typeof this.options.sourceMap === 'undefined' ? devtool && !devtool.includes('eval') && !devtool.includes('cheap') && (devtool.includes('source-map') || // Todo remove when `webpack@4` support will be dropped | ||
devtool.includes('sourcemap')) || plugins && plugins.some(plugin => plugin instanceof _webpack.SourceMapDevToolPlugin && plugin.options && plugin.options.columns) : Boolean(this.options.sourceMap); | ||
@@ -383,9 +471,13 @@ | ||
const optimizeFn = async (compilation, chunks) => { | ||
const optimizeFn = async (compilation, chunksOrAssets) => { | ||
const matchObject = _webpack.ModuleFilenameHelpers.matchObject.bind( // eslint-disable-next-line no-undefined | ||
undefined, this.options); | ||
const files = [].concat(Array.from(compilation.additionalChunkAssets || [])).concat(Array.from(chunks).filter(chunk => this.options.chunkFilter && this.options.chunkFilter(chunk)).reduce((acc, chunk) => acc.concat(Array.from(chunk.files || [])), [])).filter(file => matchObject(file)); | ||
if (TerserPlugin.isWebpack4()) { | ||
this.assetNames = [].concat(Array.from(compilation.additionalChunkAssets || [])).concat(Array.from(chunksOrAssets).reduce((acc, chunk) => acc.concat(Array.from(chunk.files || [])), [])).filter(file => matchObject(file)); | ||
} else { | ||
this.assetNames = [].concat(Object.keys(chunksOrAssets)).filter(file => matchObject(file)); | ||
} | ||
if (files.length === 0) { | ||
if (this.assetNames.length === 0) { | ||
return Promise.resolve(); | ||
@@ -397,12 +489,9 @@ } | ||
require('./Webpack5Cache').default; | ||
this.cache = new CacheEngine(compilation, { | ||
cache: this.options.cache | ||
}); | ||
const allExtractedComments = {}; | ||
const taskGenerator = this.taskGenerator.bind(this, compiler, compilation, allExtractedComments); | ||
const taskRunner = new _TaskRunner.default({ | ||
taskGenerator, | ||
files, | ||
cache: new CacheEngine(compiler, compilation, this.options), | ||
parallel: this.options.parallel | ||
}); | ||
await taskRunner.run(); | ||
await taskRunner.exit(); | ||
this.getTaskForAsset = this.taskGenerator.bind(this, compiler, compilation, allExtractedComments); | ||
await this.runTasks(); | ||
await this.exitTasks(); | ||
Object.keys(allExtractedComments).forEach(commentsFilename => { | ||
@@ -428,15 +517,3 @@ const extractedComments = new Set([...allExtractedComments[commentsFilename].sort()]); // eslint-disable-next-line no-param-reassign | ||
if (!TerserPlugin.isWebpack4()) { | ||
const hooks = _webpack.javascript.JavascriptModulesPlugin.getCompilationHooks(compilation); | ||
const data = (0, _serializeJavascript.default)({ | ||
terser: _package.default.version, | ||
terserOptions: this.options.terserOptions | ||
}); | ||
hooks.chunkHash.tap(plugin, (chunk, hash) => { | ||
hash.update('TerserPlugin'); | ||
hash.update(data); | ||
}); | ||
} else { | ||
// Todo remove after drop `webpack@4` compatibility | ||
if (TerserPlugin.isWebpack4()) { | ||
const { | ||
@@ -457,5 +534,17 @@ mainTemplate, | ||
} | ||
compilation.hooks.optimizeChunkAssets.tapPromise(plugin, optimizeFn.bind(this, compilation)); | ||
} else { | ||
const hooks = _webpack.javascript.JavascriptModulesPlugin.getCompilationHooks(compilation); | ||
const data = (0, _serializeJavascript.default)({ | ||
terser: _package.default.version, | ||
terserOptions: this.options.terserOptions | ||
}); | ||
hooks.chunkHash.tap(plugin, (chunk, hash) => { | ||
hash.update('TerserPlugin'); | ||
hash.update(data); | ||
}); | ||
compilation.hooks.optimizeAssets.tapPromise(plugin, optimizeFn.bind(this, compilation)); | ||
} | ||
compilation.hooks.optimizeChunkAssets.tapPromise(plugin, optimizeFn.bind(this, compilation)); | ||
}); | ||
@@ -462,0 +551,0 @@ } |
@@ -178,2 +178,17 @@ "use strict"; | ||
module.exports = minify; | ||
function transform(options) { | ||
// 'use strict' => this === undefined (Clean Scope) | ||
// Safer for possible security issues, albeit not critical at all here | ||
// eslint-disable-next-line no-new-func, no-param-reassign | ||
options = new Function('exports', 'require', 'module', '__filename', '__dirname', `'use strict'\nreturn ${options}`)(exports, require, module, __filename, __dirname); | ||
const result = minify(options); | ||
if (result.error) { | ||
throw result.error; | ||
} else { | ||
return result; | ||
} | ||
} | ||
module.exports.minify = minify; | ||
module.exports.transform = transform; |
{ | ||
"additionalProperties": false, | ||
"definitions": { | ||
"file-conditions": { | ||
"Rule": { | ||
"description": "Filtering rule as regex or string.", | ||
"anyOf": [ | ||
{ | ||
"instanceof": "RegExp" | ||
"instanceof": "RegExp", | ||
"tsType": "RegExp" | ||
}, | ||
{ | ||
"type": "string" | ||
"type": "string", | ||
"minLength": 1 | ||
} | ||
] | ||
} | ||
}, | ||
"properties": { | ||
"test": { | ||
}, | ||
"Rules": { | ||
"description": "Filtering rules.", | ||
"anyOf": [ | ||
{ | ||
"$ref": "#/definitions/file-conditions" | ||
}, | ||
{ | ||
"type": "array", | ||
"items": { | ||
"anyOf": [ | ||
"description": "A rule condition.", | ||
"oneOf": [ | ||
{ | ||
"$ref": "#/definitions/file-conditions" | ||
"$ref": "#/definitions/Rule" | ||
} | ||
] | ||
}, | ||
"type": "array" | ||
} | ||
}, | ||
{ | ||
"$ref": "#/definitions/Rule" | ||
} | ||
] | ||
} | ||
}, | ||
"title": "TerserPluginOptions", | ||
"type": "object", | ||
"additionalProperties": false, | ||
"properties": { | ||
"test": { | ||
"description": "Include all modules that pass test assertion.", | ||
"oneOf": [ | ||
{ | ||
"$ref": "#/definitions/Rules" | ||
} | ||
] | ||
}, | ||
"include": { | ||
"anyOf": [ | ||
"description": "Include all modules matching any of these conditions.", | ||
"oneOf": [ | ||
{ | ||
"$ref": "#/definitions/file-conditions" | ||
}, | ||
{ | ||
"items": { | ||
"anyOf": [ | ||
{ | ||
"$ref": "#/definitions/file-conditions" | ||
} | ||
] | ||
}, | ||
"type": "array" | ||
"$ref": "#/definitions/Rules" | ||
} | ||
@@ -51,22 +57,11 @@ ] | ||
"exclude": { | ||
"anyOf": [ | ||
"description": "Exclude all modules matching any of these conditions.", | ||
"oneOf": [ | ||
{ | ||
"$ref": "#/definitions/file-conditions" | ||
}, | ||
{ | ||
"items": { | ||
"anyOf": [ | ||
{ | ||
"$ref": "#/definitions/file-conditions" | ||
} | ||
] | ||
}, | ||
"type": "array" | ||
"$ref": "#/definitions/Rules" | ||
} | ||
] | ||
}, | ||
"chunkFilter": { | ||
"instanceof": "Function" | ||
}, | ||
"cache": { | ||
"description": "Enable file caching. Ignored in webpack 5, for webpack 5 please use https://webpack.js.org/configuration/other-options/#cache.", | ||
"anyOf": [ | ||
@@ -82,5 +77,7 @@ { | ||
"cacheKeys": { | ||
"description": "Allows you to override default cache keys. Ignored in webpack 5, for webpack 5 please use https://webpack.js.org/configuration/other-options/#cache.", | ||
"instanceof": "Function" | ||
}, | ||
"parallel": { | ||
"description": "Use multi-process parallel running to improve the build speed.", | ||
"anyOf": [ | ||
@@ -96,8 +93,11 @@ { | ||
"sourceMap": { | ||
"description": "Enables/Disables generation of source maps.", | ||
"type": "boolean" | ||
}, | ||
"minify": { | ||
"description": "Allows you to override default minify function.", | ||
"instanceof": "Function" | ||
}, | ||
"terserOptions": { | ||
"description": "Options for `terser`.", | ||
"additionalProperties": true, | ||
@@ -107,2 +107,3 @@ "type": "object" | ||
"extractComments": { | ||
"description": "Whether comments shall be extracted to a separate file.", | ||
"anyOf": [ | ||
@@ -169,6 +170,6 @@ { | ||
"warningsFilter": { | ||
"description": "Allow to filter `terser` warnings.", | ||
"instanceof": "Function" | ||
} | ||
}, | ||
"type": "object" | ||
} | ||
} |
@@ -19,4 +19,3 @@ "use strict"; | ||
class Webpack4Cache { | ||
constructor(compiler, compilation, options) { | ||
this.options = options; | ||
constructor(compilation, options) { | ||
this.cacheDir = options.cache === true ? Webpack4Cache.getCacheDirectory() : options.cache; | ||
@@ -32,3 +31,3 @@ } | ||
isEnabled() { | ||
return !!this.cacheDir; | ||
return Boolean(this.cacheDir); | ||
} | ||
@@ -35,0 +34,0 @@ |
@@ -18,10 +18,9 @@ "use strict"; | ||
class Cache { | ||
constructor(compiler, compilation, options) { | ||
this.compiler = compiler; | ||
// eslint-disable-next-line no-unused-vars | ||
constructor(compilation, ignored) { | ||
this.compilation = compilation; | ||
this.options = options; | ||
} | ||
isEnabled() { | ||
return !!this.compilation.cache; | ||
return Boolean(this.compilation.cache); | ||
} | ||
@@ -55,3 +54,3 @@ | ||
task.cacheETag = task.cacheETag || (0, _getLazyHashedEtag.default)(task.asset); | ||
task.cacheETag = task.cacheETag || (0, _getLazyHashedEtag.default)(task.assetSource); | ||
return new Promise((resolve, reject) => { | ||
@@ -58,0 +57,0 @@ this.compilation.cache.get(task.cacheIdent, task.cacheETag, (err, result) => { |
{ | ||
"name": "terser-webpack-plugin", | ||
"version": "2.3.6", | ||
"version": "3.0.0", | ||
"description": "Terser plugin for webpack", | ||
@@ -16,3 +16,3 @@ "license": "MIT", | ||
"engines": { | ||
"node": ">= 8.9.0" | ||
"node": ">= 10.13.0" | ||
}, | ||
@@ -45,5 +45,5 @@ "scripts": { | ||
"dependencies": { | ||
"cacache": "^13.0.1", | ||
"cacache": "^15.0.3", | ||
"find-cache-dir": "^3.3.1", | ||
"jest-worker": "^25.4.0", | ||
"jest-worker": "^25.5.0", | ||
"p-limit": "^2.3.0", | ||
@@ -53,3 +53,3 @@ "schema-utils": "^2.6.6", | ||
"source-map": "^0.6.1", | ||
"terser": "^4.6.12", | ||
"terser": "^4.6.13", | ||
"webpack-sources": "^1.4.3" | ||
@@ -59,10 +59,10 @@ }, | ||
"@babel/cli": "^7.8.4", | ||
"@babel/core": "^7.9.0", | ||
"@babel/preset-env": "^7.9.5", | ||
"@babel/core": "^7.9.6", | ||
"@babel/preset-env": "^7.9.6", | ||
"@commitlint/cli": "^8.3.5", | ||
"@commitlint/config-conventional": "^8.3.4", | ||
"@webpack-contrib/defaults": "^6.2.0", | ||
"@webpack-contrib/defaults": "^6.3.0", | ||
"@webpack-contrib/eslint-config-webpack": "^3.0.0", | ||
"babel-jest": "^25.4.0", | ||
"cross-env": "^6.0.3", | ||
"babel-jest": "^25.5.1", | ||
"cross-env": "^7.0.2", | ||
"del": "^5.1.0", | ||
@@ -74,7 +74,7 @@ "del-cli": "^3.0.0", | ||
"husky": "^4.2.5", | ||
"jest": "^25.4.0", | ||
"lint-staged": "^10.1.7", | ||
"jest": "^25.5.3", | ||
"lint-staged": "^10.2.2", | ||
"memfs": "^3.1.2", | ||
"npm-run-all": "^4.1.5", | ||
"prettier": "^1.19.1", | ||
"prettier": "^2.0.5", | ||
"standard-version": "^7.1.0", | ||
@@ -81,0 +81,0 @@ "uglify-js": "^3.9.1", |
@@ -112,35 +112,5 @@ <div align="center"> | ||
### `chunkFilter` | ||
Type: `Function<(chunk) -> boolean>` | ||
Default: `() => true` | ||
Allowing to filter which chunks should be uglified (by default all chunks are uglified). | ||
Return `true` to uglify the chunk, `false` otherwise. | ||
**webpack.config.js** | ||
```js | ||
module.exports = { | ||
optimization: { | ||
minimize: true, | ||
minimizer: [ | ||
new TerserPlugin({ | ||
chunkFilter: (chunk) => { | ||
// Exclude uglification for the `vendor` chunk | ||
if (chunk.name === 'vendor') { | ||
return false; | ||
} | ||
return true; | ||
}, | ||
}), | ||
], | ||
}, | ||
}; | ||
``` | ||
### `cache` | ||
> ⚠ Doesn't work with webpack 5! | ||
> ⚠ Ignored in webpack 5! Please use https://webpack.js.org/configuration/other-options/#cache. | ||
@@ -195,3 +165,3 @@ Type: `Boolean|String` | ||
> ⚠ Doesn't work with webpack 5! | ||
> ⚠ Ignored in webpack 5! Please use https://webpack.js.org/configuration/other-options/#cache. | ||
@@ -211,6 +181,3 @@ Type: `Function<(defaultCacheKeys, file) -> Object>` | ||
path: compiler.outputPath ? `${compiler.outputPath}/${file}` : file, // asset path | ||
hash: crypto | ||
.createHash('md4') | ||
.update(input) | ||
.digest('hex'), // source file hash | ||
hash: crypto.createHash('md4').update(input).digest('hex'), // source file hash | ||
}); | ||
@@ -502,9 +469,5 @@ ``` | ||
condition: /^\**!|@preserve|@license|@cc_on/i, | ||
filename: (file, fileData) => { | ||
// ⚠ webpack 5: there is only fileData parameter | ||
// A file can contain a query string (for example when you have `output.filename: '[name].js?[chunkhash]'`) | ||
// You must consider this | ||
// The "fileData" argument contains object with "filename", "basename", "query" | ||
return file.replace(/\.(\w+)($|\?)/, '.$1.LICENSE.txt$2'); | ||
filename: (fileData) => { | ||
// The "fileData" argument contains object with "filename", "basename", "query" and "hash" | ||
return `${fileData.filename}.LICENSE.txt${fileData.query}`; | ||
}, | ||
@@ -537,8 +500,5 @@ banner: (licenseFile) => { | ||
condition: 'some', | ||
filename: (file, fileData) => { | ||
// ⚠ webpack 5: there is only fileData parameter | ||
// A file can contain a query string (for example when you have `output.filename: '[name].js?[chunkhash]'`) | ||
// You must consider this | ||
return file.replace(/\.(\w+)($|\?)/, '.$1.LICENSE.txt$2'); | ||
filename: (fileData) => { | ||
// The "fileData" argument contains object with "filename", "basename", "query" and "hash" | ||
return `${fileData.filename}.LICENSE.txt${fileData.query}`; | ||
}, | ||
@@ -605,8 +565,5 @@ banner: (licenseFile) => { | ||
condition: true, | ||
filename: (file, fileData) => { | ||
// ⚠ webpack 5: there is only fileData parameter | ||
// A file can contain a query string (for example when you have `output.filename: '[name].js?[chunkhash]'`) | ||
// You must consider this | ||
return file.replace(/\.(\w+)($|\?)/, '.$1.LICENSE.txt$2'); | ||
filename: (fileData) => { | ||
// The "fileData" argument contains object with "filename", "basename", "query" and "hash" | ||
return `${fileData.filename}.LICENSE.txt${fileData.query}`; | ||
}, | ||
@@ -625,3 +582,3 @@ banner: (commentsFile) => { | ||
Type: `Function<(warning, source, file) -> Boolean>` | ||
Type: `Function<(warning, file, source) -> Boolean>` | ||
Default: `() => true` | ||
@@ -642,3 +599,3 @@ | ||
new TerserPlugin({ | ||
warningsFilter: (warning, source, file) => { | ||
warningsFilter: (warning, file, source) => { | ||
if (/Dropping unreachable code/i.test(warning)) { | ||
@@ -648,7 +605,7 @@ return true; | ||
if (/source\.js/i.test(source)) { | ||
if (/file\.js/i.test(file)) { | ||
return true; | ||
} | ||
if (/file\.js/i.test(file)) { | ||
if (/source\.js/i.test(source)) { | ||
return true; | ||
@@ -655,0 +612,0 @@ } |
65835
10
865
730
+ Added@gar/promisify@1.1.3(transitive)
+ Added@npmcli/fs@1.1.1(transitive)
+ Added@npmcli/move-file@1.1.2(transitive)
+ Added@types/node@20.12.12(transitive)
+ Addedcacache@15.3.0(transitive)
+ Addedcaniuse-lite@1.0.30001620(transitive)
+ Addedchownr@2.0.0(transitive)
+ Addedelectron-to-chromium@1.4.773(transitive)
+ Addedlru-cache@6.0.0(transitive)
+ Addedminipass@5.0.0(transitive)
+ Addedminizlib@2.1.2(transitive)
+ Addedmkdirp@1.0.4(transitive)
+ Addedp-map@4.0.0(transitive)
+ Addedpicocolors@1.0.1(transitive)
+ Addedrimraf@3.0.2(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedsemver@7.6.2(transitive)
+ Addedssri@8.0.1(transitive)
+ Addedtar@6.2.1(transitive)
+ Addedupdate-browserslist-db@1.0.16(transitive)
- Removed@types/node@20.12.11(transitive)
- Removedaproba@1.2.0(transitive)
- Removedcacache@13.0.1(transitive)
- Removedcaniuse-lite@1.0.30001616(transitive)
- Removedchownr@1.1.4(transitive)
- Removedcopy-concurrently@1.0.5(transitive)
- Removedcore-util-is@1.0.3(transitive)
- Removedelectron-to-chromium@1.4.763(transitive)
- Removedfiggy-pudding@3.5.2(transitive)
- Removedfs-write-stream-atomic@1.0.10(transitive)
- Removediferr@0.1.5(transitive)
- Removedisarray@1.0.0(transitive)
- Removedlru-cache@5.1.1(transitive)
- Removedminimist@1.2.8(transitive)
- Removedmkdirp@0.5.6(transitive)
- Removedmove-concurrently@1.0.1(transitive)
- Removedp-map@3.0.0(transitive)
- Removedpicocolors@1.0.0(transitive)
- Removedprocess-nextick-args@2.0.1(transitive)
- Removedreadable-stream@2.3.8(transitive)
- Removedrimraf@2.7.1(transitive)
- Removedrun-queue@1.0.3(transitive)
- Removedsafe-buffer@5.1.2(transitive)
- Removedssri@7.1.1(transitive)
- Removedstring_decoder@1.1.1(transitive)
- Removedupdate-browserslist-db@1.0.15(transitive)
- Removedutil-deprecate@1.0.2(transitive)
- Removedyallist@3.1.1(transitive)
Updatedcacache@^15.0.3
Updatedjest-worker@^25.5.0
Updatedterser@^4.6.13