terser-webpack-plugin
Advanced tools
Comparing version 5.1.4 to 5.2.0
@@ -18,4 +18,2 @@ "use strict"; | ||
var terserPackageJson = _interopRequireWildcard(require("terser/package.json")); | ||
var _pLimit = _interopRequireDefault(require("p-limit")); | ||
@@ -25,2 +23,4 @@ | ||
var _utils = require("./utils"); | ||
var schema = _interopRequireWildcard(require("./options.json")); | ||
@@ -48,14 +48,16 @@ | ||
/** @typedef {import("terser").MinifyOptions} TerserMinifyOptions */ | ||
/** @typedef {import("terser").MinifyOptions} TerserOptions */ | ||
/** @typedef {import("jest-worker").Worker} JestWorker */ | ||
/** @typedef {import("uglify-js").MinifyOptions} UglifyJSOptions */ | ||
/** @typedef {import("source-map").RawSourceMap} RawSourceMap */ | ||
/** @typedef {import("@swc/core").JsMinifyOptions} SwcOptions */ | ||
/** @typedef {import("./minify.js").InternalMinifyOptions} InternalMinifyOptions */ | ||
/** @typedef {import("esbuild").TransformOptions} EsbuildOptions */ | ||
/** @typedef {import("./minify.js").InternalMinifyResult} InternalMinifyResult */ | ||
/** @typedef {Object.<any, any>} CustomOptions */ | ||
/** @typedef {import("./minify.js").CustomMinifyOptions} CustomMinifyOptions */ | ||
/** @typedef {import("jest-worker").Worker} JestWorker */ | ||
/** @typedef {import("source-map").RawSourceMap} RawSourceMap */ | ||
/** @typedef {RegExp | string} Rule */ | ||
@@ -65,4 +67,2 @@ | ||
/** @typedef {JestWorker & { transform: (options: string) => InternalMinifyResult, minify: (options: InternalMinifyOptions) => InternalMinifyResult }} MinifyWorker */ | ||
/** | ||
@@ -76,3 +76,3 @@ * @callback ExtractCommentsFunction | ||
/** | ||
* @typedef {boolean | string | RegExp | ExtractCommentsFunction} ExtractCommentsCondition | ||
* @typedef {boolean | 'all' | 'some' | RegExp | ExtractCommentsFunction} ExtractCommentsCondition | ||
*/ | ||
@@ -96,45 +96,122 @@ | ||
/** | ||
* @callback CustomMinifyFunction | ||
* @param {{ [file: string]: string }} fileAndCode | ||
* @param {RawSourceMap} [sourceMap] | ||
* @param {Object.<any, any>} minifyOptions | ||
* @typedef {ExtractCommentsCondition | ExtractCommentsObject} ExtractCommentsOptions | ||
*/ | ||
/** | ||
* @typedef {ExtractCommentsCondition | ExtractCommentsObject} ExtractCommentsOptions | ||
* @typedef {{ [file: string]: string }} Input | ||
*/ | ||
/** | ||
* @typedef {Object} PluginWithTerserOptions | ||
* @property {Rules} [test] | ||
* @property {Rules} [include] | ||
* @property {Rules} [exclude] | ||
* @property {TerserMinifyOptions} [terserOptions] | ||
* @property {ExtractCommentsOptions} [extractComments] | ||
* @property {boolean} [parallel] | ||
* @property {CustomMinifyFunction} [minify] | ||
* @typedef {Object} MinimizedResult | ||
* @property {string} code | ||
* @property {RawSourceMap} [map] | ||
* @property {Array<Error | string>} [errors] | ||
* @property {Array<Error | string>} [warnings] | ||
* @property {Array<string>} [extractedComments] | ||
*/ | ||
/** | ||
* @typedef {Object} PluginWithCustomMinifyOptions | ||
* @typedef {Object} PredefinedOptions | ||
* @property {boolean} [module] | ||
* @property {5 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | number | string} [ecma] | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {Object} MinimizerImplementationAndOptions | ||
* @property {MinimizerImplementation<ThirdArgument<T>>} implementation | ||
* @property {PredefinedOptions & ThirdArgument<T>} options | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {Object} InternalOptions | ||
* @property {string} name | ||
* @property {string} input | ||
* @property {RawSourceMap | undefined} inputSourceMap | ||
* @property {ExtractCommentsOptions | undefined} extractComments | ||
* @property {MinimizerImplementationAndOptions<T>} minimizer | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {JestWorker & { transform: (options: string) => MinimizedResult, minify: (options: InternalOptions<T>) => MinimizedResult }} MinimizerWorker | ||
*/ | ||
/** | ||
* @template T | ||
* @callback BasicMinimizerImplementation | ||
* @param {Input} input | ||
* @param {RawSourceMap | undefined} sourceMap | ||
* @param {T} minifyOptions | ||
* @param {ExtractCommentsOptions | undefined} extractComments | ||
* @returns {Promise<MinimizedResult>} | ||
*/ | ||
/** | ||
* @typedef {object} MinimizeFunctionHelpers | ||
* @property {() => string | undefined} [getMinimizerVersion] | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {BasicMinimizerImplementation<T> & MinimizeFunctionHelpers } MinimizerImplementation | ||
*/ | ||
/** | ||
* @typedef {MinimizerImplementation<TerserOptions>} TerserMinimizer | ||
*/ | ||
/** | ||
* @typedef {MinimizerImplementation<UglifyJSOptions>} UglifyJSMinimizer | ||
*/ | ||
/** | ||
* @typedef {MinimizerImplementation<SwcOptions>} SwcMinimizer | ||
*/ | ||
/** | ||
* @typedef {MinimizerImplementation<EsbuildOptions>} EsbuildMinimizer | ||
*/ | ||
/** | ||
* @typedef {MinimizerImplementation<CustomOptions>} CustomMinimizer | ||
*/ | ||
/** | ||
* @typedef {Object} BasePluginOptions | ||
* @property {Rules} [test] | ||
* @property {Rules} [include] | ||
* @property {Rules} [exclude] | ||
* @property {Object.<any, any>} [terserOptions] | ||
* @property {ExtractCommentsOptions} [extractComments] | ||
* @property {boolean} [parallel] | ||
* @property {CustomMinifyFunction} [minify] | ||
*/ | ||
/** | ||
* @typedef {PluginWithTerserOptions | PluginWithCustomMinifyOptions} TerserPluginOptions | ||
* @template T | ||
* @typedef {T extends (arg1: any, arg2: any, arg3: infer U, ...args: any[]) => any ? U: never} ThirdArgument | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {Object} DefaultMinimizerImplementationAndOptions | ||
* @property {undefined | MinimizerImplementation<ThirdArgument<T>>} [minify] | ||
* @property {ThirdArgument<T> | undefined} [terserOptions] | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {T extends MinimizerImplementation<TerserOptions> ? DefaultMinimizerImplementationAndOptions<T> : { minify: MinimizerImplementation<ThirdArgument<T>>, terserOptions?: ThirdArgument<T> | undefined}} PickMinimizerImplementationAndOptions | ||
*/ | ||
// TODO please add manually `T extends ... = TerserMinimizer`, because typescript is not supported default value for templates yet | ||
/** | ||
* @template {TerserMinimizer | UglifyJSMinimizer | SwcMinimizer | EsbuildMinimizer | CustomMinimizer} T=TerserMinimizer | ||
*/ | ||
class TerserPlugin { | ||
/** | ||
* @param {TerserPluginOptions} options | ||
* @param {BasePluginOptions & PickMinimizerImplementationAndOptions<T>} [options] | ||
*/ | ||
constructor(options = {}) { | ||
(0, _schemaUtils.validate)( | ||
/** @type {Schema} */ | ||
schema, options, { | ||
constructor(options) { | ||
(0, _schemaUtils.validate)(schema, options || {}, { | ||
name: "Terser Plugin", | ||
@@ -144,3 +221,3 @@ baseDataPath: "options" | ||
const { | ||
minify, | ||
minify = _utils.terserMinify, | ||
terserOptions = {}, | ||
@@ -152,3 +229,7 @@ test = /\.[cm]?js(\?.*)?$/i, | ||
exclude | ||
} = options; | ||
} = options || {}; | ||
/** | ||
* @type {BasePluginOptions & { minify: MinimizerImplementation<ThirdArgument<T>>, terserOptions: ThirdArgument<T>}} | ||
*/ | ||
this.options = { | ||
@@ -178,7 +259,27 @@ test, | ||
* @private | ||
* @param {Error & { line: number, col: number}} error | ||
* @param {Error | string} warning | ||
* @param {string} file | ||
* @returns {WebpackError} | ||
*/ | ||
static buildWarning(warning, file) { | ||
/** | ||
* @type {Error & { hideStack: true, file: string }} | ||
*/ | ||
// @ts-ignore | ||
const builtWarning = new Error(warning.toString()); | ||
builtWarning.name = "Warning"; | ||
builtWarning.hideStack = true; | ||
builtWarning.file = file; // @ts-ignore | ||
return builtWarning; | ||
} | ||
/** | ||
* @private | ||
* @param {any} error | ||
* @param {string} file | ||
* @param {Compilation["requestShortener"]} [requestShortener] | ||
* @param {SourceMapConsumer} [sourceMap] | ||
* @returns {Error} | ||
* @returns {WebpackError} | ||
*/ | ||
@@ -188,2 +289,16 @@ | ||
static buildError(error, file, requestShortener, sourceMap) { | ||
/** | ||
* @type {Error & { file: string }} | ||
*/ | ||
// @ts-ignore | ||
let builtError; | ||
if (typeof error === "string") { | ||
// @ts-ignore | ||
builtError = new Error(`${file} from Terser plugin\n${error}`); | ||
builtError.file = file; // @ts-ignore | ||
return builtError; | ||
} | ||
if (error.line) { | ||
@@ -196,17 +311,33 @@ const original = sourceMap && sourceMap.originalPositionFor({ | ||
if (original && original.source && requestShortener) { | ||
return new Error(`${file} from Terser\n${error.message} [${requestShortener.shorten(original.source)}:${original.line},${original.column}][${file}:${error.line},${error.col}]${error.stack ? `\n${error.stack.split("\n").slice(1).join("\n")}` : ""}`); | ||
} | ||
// @ts-ignore | ||
builtError = new Error(`${file} from Terser plugin\n${error.message} [${requestShortener.shorten(original.source)}:${original.line},${original.column}][${file}:${error.line},${error.col}]${error.stack ? `\n${error.stack.split("\n").slice(1).join("\n")}` : ""}`); | ||
builtError.file = file; // @ts-ignore | ||
return new Error(`${file} from Terser\n${error.message} [${file}:${error.line},${error.col}]${error.stack ? `\n${error.stack.split("\n").slice(1).join("\n")}` : ""}`); | ||
return builtError; | ||
} // @ts-ignore | ||
builtError = new Error(`${file} from Terser plugin\n${error.message} [${file}:${error.line},${error.col}]${error.stack ? `\n${error.stack.split("\n").slice(1).join("\n")}` : ""}`); | ||
builtError.file = file; // @ts-ignore | ||
return builtError; | ||
} | ||
if (error.stack) { | ||
return new Error(`${file} from Terser\n${error.stack}`); | ||
} | ||
// @ts-ignore | ||
builtError = new Error(`${file} from Terser plugin\n${typeof error.message !== "undefined" ? error.message : ""}\n${error.stack}`); | ||
builtError.file = file; // @ts-ignore | ||
return new Error(`${file} from Terser\n${error.message}`); | ||
return builtError; | ||
} // @ts-ignore | ||
builtError = new Error(`${file} from Terser plugin\n${error.message}`); | ||
builtError.file = file; // @ts-ignore | ||
return builtError; | ||
} | ||
/** | ||
* @private | ||
* @param {boolean} parallel | ||
* @param {boolean | undefined} parallel | ||
* @returns {number} | ||
@@ -225,2 +356,3 @@ */ | ||
/** | ||
* @private | ||
* @param {Compiler} compiler | ||
@@ -236,9 +368,7 @@ * @param {Compilation} compilation | ||
const cache = compilation.getCache("TerserWebpackPlugin"); | ||
let numberOfAssetsForMinify = 0; | ||
const assetsForMinify = await Promise.all(Object.keys(assets).filter(name => { | ||
let numberOfAssets = 0; | ||
const assetsForJob = await Promise.all(Object.keys(assets).filter(name => { | ||
const { | ||
info | ||
} = | ||
/** @type {Asset} */ | ||
compilation.getAsset(name); | ||
} = compilation.getAsset(name); | ||
@@ -261,5 +391,3 @@ if ( // Skip double minimize assets from child compilation | ||
source | ||
} = | ||
/** @type {Asset} */ | ||
compilation.getAsset(name); | ||
} = compilation.getAsset(name); | ||
const eTag = cache.getLazyHashedEtag(source); | ||
@@ -270,3 +398,3 @@ const cacheItem = cache.getItemCache(name, eTag); | ||
if (!output) { | ||
numberOfAssetsForMinify += 1; | ||
numberOfAssets += 1; | ||
} | ||
@@ -282,6 +410,6 @@ | ||
})); | ||
/** @type {undefined | (() => MinifyWorker)} */ | ||
/** @type {undefined | (() => MinimizerWorker<T>)} */ | ||
let getWorker; | ||
/** @type {undefined | MinifyWorker} */ | ||
/** @type {undefined | MinimizerWorker<T>} */ | ||
@@ -295,3 +423,3 @@ let initializedWorker; | ||
// Do not create unnecessary workers when the number of files is less than the available cores, it saves memory | ||
numberOfWorkers = Math.min(numberOfAssetsForMinify, optimizeOptions.availableNumberOfCores); // eslint-disable-next-line consistent-return | ||
numberOfWorkers = Math.min(numberOfAssets, optimizeOptions.availableNumberOfCores); // eslint-disable-next-line consistent-return | ||
@@ -303,5 +431,3 @@ getWorker = () => { | ||
initializedWorker = | ||
/** @type {MinifyWorker} */ | ||
new _jestWorker.Worker(require.resolve("./minify"), { | ||
initializedWorker = new _jestWorker.Worker(require.resolve("./minify"), { | ||
numWorkers: numberOfWorkers, | ||
@@ -327,5 +453,3 @@ enableWorkerThreads: true | ||
const limit = (0, _pLimit.default)(getWorker && numberOfAssetsForMinify > 0 ? | ||
/** @type {number} */ | ||
numberOfWorkers : Infinity); | ||
const limit = (0, _pLimit.default)(getWorker && numberOfAssets > 0 ? numberOfWorkers : Infinity); | ||
const { | ||
@@ -343,3 +467,3 @@ SourceMapSource, | ||
for (const asset of assetsForMinify) { | ||
for (const asset of assetsForJob) { | ||
scheduledTasks.push(limit(async () => { | ||
@@ -369,12 +493,6 @@ const { | ||
if (TerserPlugin.isSourceMap(map)) { | ||
inputSourceMap = | ||
/** @type {RawSourceMap} */ | ||
map; | ||
inputSourceMap = map; | ||
} else { | ||
inputSourceMap = | ||
/** @type {RawSourceMap} */ | ||
map; | ||
compilation.warnings.push( | ||
/** @type {WebpackError} */ | ||
new Error(`${name} contains invalid source map`)); | ||
inputSourceMap = map; | ||
compilation.warnings.push(new Error(`${name} contains invalid source map`)); | ||
} | ||
@@ -386,3 +504,3 @@ } | ||
} | ||
/** @type {InternalMinifyOptions} */ | ||
/** @type {InternalOptions<T>} */ | ||
@@ -394,4 +512,7 @@ | ||
inputSourceMap, | ||
minify: this.options.minify, | ||
minifyOptions: { ...this.options.terserOptions | ||
// TODO make `minimizer` option instead `minify` and `terserOptions` in the next major release, also rename `terserMinify` to `terserMinimize` | ||
minimizer: { | ||
implementation: this.options.minify, | ||
options: { ...this.options.terserOptions | ||
} | ||
}, | ||
@@ -401,12 +522,16 @@ extractComments: this.options.extractComments | ||
if (typeof options.minifyOptions.module === "undefined") { | ||
if (typeof options.minimizer.options.module === "undefined") { | ||
if (typeof info.javascriptModule !== "undefined") { | ||
options.minifyOptions.module = info.javascriptModule; | ||
options.minimizer.options.module = info.javascriptModule; | ||
} else if (/\.mjs(\?.*)?$/i.test(name)) { | ||
options.minifyOptions.module = true; | ||
options.minimizer.options.module = true; | ||
} else if (/\.cjs(\?.*)?$/i.test(name)) { | ||
options.minifyOptions.module = false; | ||
options.minimizer.options.module = false; | ||
} | ||
} | ||
if (typeof options.minimizer.options.ecma === "undefined") { | ||
options.minimizer.options.ecma = TerserPlugin.getEcmaVersion(compiler.options.output.environment || {}); | ||
} | ||
try { | ||
@@ -416,8 +541,4 @@ output = await (getWorker ? getWorker().transform((0, _serializeJavascript.default)(options)) : (0, _minify.minify)(options)); | ||
const hasSourceMap = inputSourceMap && TerserPlugin.isSourceMap(inputSourceMap); | ||
compilation.errors.push( | ||
/** @type {WebpackError} */ | ||
TerserPlugin.buildError(error, name, // eslint-disable-next-line no-undefined | ||
hasSourceMap ? compilation.requestShortener : undefined, hasSourceMap ? new _sourceMap.SourceMapConsumer( | ||
/** @type {RawSourceMap} */ | ||
inputSourceMap) : // eslint-disable-next-line no-undefined | ||
compilation.errors.push(TerserPlugin.buildError(error, name, // eslint-disable-next-line no-undefined | ||
hasSourceMap ? compilation.requestShortener : undefined, hasSourceMap ? new _sourceMap.SourceMapConsumer(inputSourceMap) : // eslint-disable-next-line no-undefined | ||
undefined)); | ||
@@ -427,2 +548,26 @@ return; | ||
if (typeof output.code === "undefined") { | ||
compilation.errors.push(new Error(`${name} from Terser plugin\nMinimizer doesn't return result`)); | ||
return; | ||
} | ||
if (output.warnings && output.warnings.length > 0) { | ||
output.warnings = output.warnings.map( | ||
/** | ||
* @param {Error | string} item | ||
*/ | ||
item => TerserPlugin.buildWarning(item, name)); | ||
} | ||
if (output.errors && output.errors.length > 0) { | ||
const hasSourceMap = inputSourceMap && TerserPlugin.isSourceMap(inputSourceMap); | ||
output.errors = output.errors.map( | ||
/** | ||
* @param {Error | string} item | ||
*/ | ||
item => TerserPlugin.buildError(item, name, // eslint-disable-next-line no-undefined | ||
hasSourceMap ? compilation.requestShortener : undefined, hasSourceMap ? new _sourceMap.SourceMapConsumer(inputSourceMap) : // eslint-disable-next-line no-undefined | ||
undefined)); | ||
} | ||
let shebang; | ||
@@ -439,5 +584,3 @@ | ||
if (output.map) { | ||
output.source = new SourceMapSource(output.code, name, output.map, input, | ||
/** @type {RawSourceMap} */ | ||
inputSourceMap, true); | ||
output.source = new SourceMapSource(output.code, name, output.map, input, inputSourceMap, true); | ||
} else { | ||
@@ -492,2 +635,4 @@ output.source = new RawSource(output.code); | ||
source: output.source, | ||
errors: output.errors, | ||
warnings: output.warnings, | ||
commentsFilename: output.commentsFilename, | ||
@@ -497,2 +642,22 @@ extractedCommentsSource: output.extractedCommentsSource | ||
} | ||
if (output.warnings && output.warnings.length > 0) { | ||
output.warnings.forEach( | ||
/** | ||
* @param {Error} warning | ||
*/ | ||
warning => { | ||
compilation.warnings.push(warning); | ||
}); | ||
} | ||
if (output.errors && output.errors.length > 0) { | ||
output.errors.forEach( | ||
/** | ||
* @param {Error & { filename?: string }} error | ||
*/ | ||
error => { | ||
compilation.errors.push(error); | ||
}); | ||
} | ||
/** @type {Record<string, any>} */ | ||
@@ -541,5 +706,3 @@ | ||
async (previousPromise, [from, value]) => { | ||
const previous = | ||
/** @type {ExtractedCommentsInfoWIthFrom | undefined} **/ | ||
await previousPromise; | ||
const previous = await previousPromise; | ||
const { | ||
@@ -595,5 +758,3 @@ commentsFilename, | ||
}; | ||
}, | ||
/** @type {Promise<unknown>} */ | ||
Promise.resolve()); | ||
}, Promise.resolve()); | ||
} | ||
@@ -627,10 +788,2 @@ /** | ||
apply(compiler) { | ||
const { | ||
output | ||
} = compiler.options; | ||
if (typeof this.options.terserOptions.ecma === "undefined") { | ||
this.options.terserOptions.ecma = TerserPlugin.getEcmaVersion(output.environment || {}); | ||
} | ||
const pluginName = this.constructor.name; | ||
@@ -641,4 +794,4 @@ const availableNumberOfCores = TerserPlugin.getAvailableNumberOfCores(this.options.parallel); | ||
const data = (0, _serializeJavascript.default)({ | ||
terser: terserPackageJson.version, | ||
terserOptions: this.options.terserOptions | ||
minimizer: typeof this.options.minify.getMinimizerVersion !== "undefined" ? this.options.minify.getMinimizerVersion() || "0.0.0" : "0.0.0", | ||
options: this.options.terserOptions | ||
}); | ||
@@ -671,3 +824,7 @@ hooks.chunkHash.tap(pluginName, (chunk, hash) => { | ||
TerserPlugin.terserMinify = _utils.terserMinify; | ||
TerserPlugin.uglifyJsMinify = _utils.uglifyJsMinify; | ||
TerserPlugin.swcMinify = _utils.swcMinify; | ||
TerserPlugin.esbuildMinify = _utils.esbuildMinify; | ||
var _default = TerserPlugin; | ||
exports.default = _default; |
"use strict"; | ||
const { | ||
minify: terserMinify | ||
} = require("terser"); | ||
/** @typedef {import("source-map").RawSourceMap} RawSourceMap */ | ||
/** @typedef {import("./index.js").MinimizedResult} MinimizedResult */ | ||
/** @typedef {import("./index.js").ExtractCommentsOptions} ExtractCommentsOptions */ | ||
/** @typedef {import("./index.js").CustomMinifyFunction} CustomMinifyFunction */ | ||
/** @typedef {import("terser").MinifyOptions} TerserMinifyOptions */ | ||
/** @typedef {import("terser").MinifyOutput} MinifyOutput */ | ||
/** @typedef {import("terser").FormatOptions} FormatOptions */ | ||
/** @typedef {import("terser").MangleOptions} MangleOptions */ | ||
/** @typedef {import("./index.js").ExtractCommentsFunction} ExtractCommentsFunction */ | ||
/** @typedef {import("./index.js").ExtractCommentsCondition} ExtractCommentsCondition */ | ||
/** | ||
* @typedef {Object.<any, any>} CustomMinifyOptions | ||
* @template T | ||
* @param {import("./index.js").InternalOptions<T>} options | ||
* @returns {Promise<MinimizedResult>} | ||
*/ | ||
/** | ||
* @typedef {Object} InternalMinifyOptions | ||
* @property {string} name | ||
* @property {string} input | ||
* @property {RawSourceMap} [inputSourceMap] | ||
* @property {ExtractCommentsOptions} extractComments | ||
* @property {CustomMinifyFunction} [minify] | ||
* @property {TerserMinifyOptions | CustomMinifyOptions} minifyOptions | ||
*/ | ||
/** | ||
* @typedef {Array<string>} ExtractedComments | ||
*/ | ||
/** | ||
* @typedef {Promise<MinifyOutput & { extractedComments?: ExtractedComments}>} InternalMinifyResult | ||
*/ | ||
/** | ||
* @typedef {TerserMinifyOptions & { sourceMap: undefined } & ({ output: FormatOptions & { beautify: boolean } } | { format: FormatOptions & { beautify: boolean } })} NormalizedTerserMinifyOptions | ||
*/ | ||
/** | ||
* @param {TerserMinifyOptions} [terserOptions={}] | ||
* @returns {NormalizedTerserMinifyOptions} | ||
*/ | ||
function buildTerserOptions(terserOptions = {}) { | ||
// Need deep copy objects to avoid https://github.com/terser/terser/issues/366 | ||
return { ...terserOptions, | ||
compress: typeof terserOptions.compress === "boolean" ? terserOptions.compress : { ...terserOptions.compress | ||
}, | ||
// ecma: terserOptions.ecma, | ||
// ie8: terserOptions.ie8, | ||
// keep_classnames: terserOptions.keep_classnames, | ||
// keep_fnames: terserOptions.keep_fnames, | ||
mangle: terserOptions.mangle == null ? true : typeof terserOptions.mangle === "boolean" ? terserOptions.mangle : { ...terserOptions.mangle | ||
}, | ||
// module: terserOptions.module, | ||
// nameCache: { ...terserOptions.toplevel }, | ||
// the `output` option is deprecated | ||
...(terserOptions.format ? { | ||
format: { | ||
beautify: false, | ||
...terserOptions.format | ||
} | ||
} : { | ||
output: { | ||
beautify: false, | ||
...terserOptions.output | ||
} | ||
}), | ||
parse: { ...terserOptions.parse | ||
}, | ||
// safari10: terserOptions.safari10, | ||
// Ignoring sourceMap from options | ||
// eslint-disable-next-line no-undefined | ||
sourceMap: undefined // toplevel: terserOptions.toplevel | ||
}; | ||
} | ||
/** | ||
* @param {any} value | ||
* @returns {boolean} | ||
*/ | ||
function isObject(value) { | ||
const type = typeof value; | ||
return value != null && (type === "object" || type === "function"); | ||
} | ||
/** | ||
* @param {ExtractCommentsOptions} extractComments | ||
* @param {NormalizedTerserMinifyOptions} terserOptions | ||
* @param {ExtractedComments} extractedComments | ||
* @returns {ExtractCommentsFunction} | ||
*/ | ||
function buildComments(extractComments, terserOptions, extractedComments) { | ||
/** @type {{ [index: string]: ExtractCommentsCondition }} */ | ||
const condition = {}; | ||
let comments; | ||
if (terserOptions.format) { | ||
({ | ||
comments | ||
} = terserOptions.format); | ||
} else if (terserOptions.output) { | ||
({ | ||
comments | ||
} = terserOptions.output); | ||
} | ||
condition.preserve = typeof comments !== "undefined" ? comments : false; | ||
if (typeof extractComments === "boolean" && extractComments) { | ||
condition.extract = "some"; | ||
} else if (typeof extractComments === "string" || extractComments instanceof RegExp) { | ||
condition.extract = extractComments; | ||
} else if (typeof extractComments === "function") { | ||
condition.extract = extractComments; | ||
} else if (extractComments && isObject(extractComments)) { | ||
condition.extract = typeof extractComments.condition === "boolean" && extractComments.condition ? "some" : typeof extractComments.condition !== "undefined" ? extractComments.condition : "some"; | ||
} else { | ||
// No extract | ||
// Preserve using "commentsOpts" or "some" | ||
condition.preserve = typeof comments !== "undefined" ? comments : "some"; | ||
condition.extract = false; | ||
} // Ensure that both conditions are functions | ||
["preserve", "extract"].forEach(key => { | ||
/** @type {undefined | string} */ | ||
let regexStr; | ||
/** @type {undefined | RegExp} */ | ||
let regex; | ||
switch (typeof condition[key]) { | ||
case "boolean": | ||
condition[key] = condition[key] ? () => true : () => false; | ||
break; | ||
case "function": | ||
break; | ||
case "string": | ||
if (condition[key] === "all") { | ||
condition[key] = () => true; | ||
break; | ||
} | ||
if (condition[key] === "some") { | ||
condition[key] = | ||
/** @type {ExtractCommentsFunction} */ | ||
(astNode, comment) => (comment.type === "comment2" || comment.type === "comment1") && /@preserve|@lic|@cc_on|^\**!/i.test(comment.value); | ||
break; | ||
} | ||
regexStr = | ||
/** @type {string} */ | ||
condition[key]; | ||
condition[key] = | ||
/** @type {ExtractCommentsFunction} */ | ||
(astNode, comment) => new RegExp( | ||
/** @type {string} */ | ||
regexStr).test(comment.value); | ||
break; | ||
default: | ||
regex = | ||
/** @type {RegExp} */ | ||
condition[key]; | ||
condition[key] = | ||
/** @type {ExtractCommentsFunction} */ | ||
(astNode, comment) => | ||
/** @type {RegExp} */ | ||
regex.test(comment.value); | ||
} | ||
}); // Redefine the comments function to extract and preserve | ||
// comments according to the two conditions | ||
return (astNode, comment) => { | ||
if ( | ||
/** @type {{ extract: ExtractCommentsFunction }} */ | ||
condition.extract(astNode, comment)) { | ||
const commentText = comment.type === "comment2" ? `/*${comment.value}*/` : `//${comment.value}`; // Don't include duplicate comments | ||
if (!extractedComments.includes(commentText)) { | ||
extractedComments.push(commentText); | ||
} | ||
} | ||
return ( | ||
/** @type {{ preserve: ExtractCommentsFunction }} */ | ||
condition.preserve(astNode, comment) | ||
); | ||
}; | ||
} | ||
/** | ||
* @param {InternalMinifyOptions} options | ||
* @returns {InternalMinifyResult} | ||
*/ | ||
async function minify(options) { | ||
@@ -226,55 +15,23 @@ const { | ||
inputSourceMap, | ||
minify: minifyFn, | ||
minifyOptions | ||
extractComments | ||
} = options; | ||
if (minifyFn) { | ||
return minifyFn({ | ||
[name]: input | ||
}, inputSourceMap, minifyOptions); | ||
} // Copy terser options | ||
const terserOptions = buildTerserOptions(minifyOptions); // Let terser generate a SourceMap | ||
if (inputSourceMap) { | ||
// @ts-ignore | ||
terserOptions.sourceMap = { | ||
asObject: true | ||
}; | ||
} | ||
/** @type {ExtractedComments} */ | ||
const extractedComments = []; | ||
const { | ||
extractComments | ||
} = options; | ||
if (terserOptions.output) { | ||
terserOptions.output.comments = buildComments(extractComments, terserOptions, extractedComments); | ||
} else if (terserOptions.format) { | ||
terserOptions.format.comments = buildComments(extractComments, terserOptions, extractedComments); | ||
} | ||
const result = await terserMinify({ | ||
implementation, | ||
options: minimizerOptions | ||
} = options.minimizer; | ||
return implementation({ | ||
[name]: input | ||
}, terserOptions); | ||
return { ...result, | ||
extractedComments | ||
}; | ||
}, inputSourceMap, minimizerOptions, extractComments); | ||
} | ||
/** | ||
* @param {string} options | ||
* @returns {InternalMinifyResult} | ||
* @returns {Promise<MinimizedResult>} | ||
*/ | ||
function transform(options) { | ||
async 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-param-reassign | ||
const evaluatedOptions = | ||
/** @type {InternalMinifyOptions} */ | ||
// eslint-disable-next-line no-new-func | ||
const evaluatedOptions = // eslint-disable-next-line no-new-func | ||
new Function("exports", "require", "module", "__filename", "__dirname", `'use strict'\nreturn ${options}`)(exports, require, module, __filename, __dirname); | ||
@@ -281,0 +38,0 @@ return minify(evaluatedOptions); |
@@ -42,2 +42,3 @@ { | ||
"description": "Include all modules that pass test assertion.", | ||
"link": "https://github.com/webpack-contrib/terser-webpack-plugin#test", | ||
"oneOf": [ | ||
@@ -51,2 +52,3 @@ { | ||
"description": "Include all modules matching any of these conditions.", | ||
"link": "https://github.com/webpack-contrib/terser-webpack-plugin#include", | ||
"oneOf": [ | ||
@@ -60,2 +62,3 @@ { | ||
"description": "Exclude all modules matching any of these conditions.", | ||
"link": "https://github.com/webpack-contrib/terser-webpack-plugin#exclude", | ||
"oneOf": [ | ||
@@ -68,3 +71,4 @@ { | ||
"terserOptions": { | ||
"description": "Options for `terser`.", | ||
"description": "Options for `terser` (by default) or custom `minify` function.", | ||
"link": "https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions", | ||
"additionalProperties": true, | ||
@@ -75,2 +79,3 @@ "type": "object" | ||
"description": "Whether comments shall be extracted to a separate file.", | ||
"link": "https://github.com/webpack-contrib/terser-webpack-plugin#extractcomments", | ||
"anyOf": [ | ||
@@ -108,3 +113,5 @@ { | ||
} | ||
] | ||
], | ||
"description": "Condition what comments you need extract.", | ||
"link": "https://github.com/webpack-contrib/terser-webpack-plugin#condition" | ||
}, | ||
@@ -120,3 +127,5 @@ "filename": { | ||
} | ||
] | ||
], | ||
"description": "The file where the extracted comments will be stored. Default is to append the suffix .LICENSE.txt to the original filename.", | ||
"link": "https://github.com/webpack-contrib/terser-webpack-plugin#filename" | ||
}, | ||
@@ -135,3 +144,5 @@ "banner": { | ||
} | ||
] | ||
], | ||
"description": "The banner text that points to the extracted file and will be added on top of the original file", | ||
"link": "https://github.com/webpack-contrib/terser-webpack-plugin#banner" | ||
} | ||
@@ -145,2 +156,3 @@ }, | ||
"description": "Use multi-process parallel running to improve the build speed.", | ||
"link": "https://github.com/webpack-contrib/terser-webpack-plugin#parallel", | ||
"anyOf": [ | ||
@@ -157,2 +169,3 @@ { | ||
"description": "Allows you to override default minify function.", | ||
"link": "https://github.com/webpack-contrib/terser-webpack-plugin#number", | ||
"instanceof": "Function" | ||
@@ -159,0 +172,0 @@ } |
{ | ||
"name": "terser-webpack-plugin", | ||
"version": "5.1.4", | ||
"version": "5.2.0", | ||
"description": "Terser plugin for webpack", | ||
@@ -15,2 +15,3 @@ "license": "MIT", | ||
"main": "dist/cjs.js", | ||
"types": "types/index.d.ts", | ||
"engines": { | ||
@@ -23,3 +24,3 @@ "node": ">= 10.13.0" | ||
"prebuild": "npm run clean", | ||
"_build:types": "tsc --declaration --emitDeclarationOnly --outDir types && prettier \"types/**/*.ts\" --write", | ||
"build:types": "tsc --declaration --emitDeclarationOnly --outDir types && prettier \"types/**/*.ts\" --write && prettier types --write", | ||
"build:code": "cross-env NODE_ENV=production babel src -d dist --copy-files", | ||
@@ -48,37 +49,51 @@ "build": "npm-run-all -p \"build:**\"", | ||
}, | ||
"peerDependenciesMeta": { | ||
"@swc/core": { | ||
"optional": true | ||
}, | ||
"uglify-js": { | ||
"optional": true | ||
}, | ||
"esbuild": { | ||
"optional": true | ||
} | ||
}, | ||
"dependencies": { | ||
"jest-worker": "^27.0.2", | ||
"jest-worker": "^27.0.6", | ||
"p-limit": "^3.1.0", | ||
"schema-utils": "^3.0.0", | ||
"schema-utils": "^3.1.1", | ||
"serialize-javascript": "^6.0.0", | ||
"source-map": "^0.6.1", | ||
"terser": "^5.7.0" | ||
"terser": "^5.7.2" | ||
}, | ||
"devDependencies": { | ||
"@babel/cli": "^7.14.5", | ||
"@babel/core": "^7.14.6", | ||
"@babel/preset-env": "^7.14.7", | ||
"@commitlint/cli": "^12.1.4", | ||
"@commitlint/config-conventional": "^12.1.4", | ||
"@types/serialize-javascript": "^5.0.0", | ||
"@babel/cli": "^7.14.8", | ||
"@babel/core": "^7.14.8", | ||
"@babel/preset-env": "^7.14.9", | ||
"@commitlint/cli": "^13.1.0", | ||
"@commitlint/config-conventional": "^13.1.0", | ||
"@swc/core": "^1.2.82", | ||
"@types/serialize-javascript": "^5.0.1", | ||
"@types/uglify-js": "^3.13.1", | ||
"@webpack-contrib/eslint-config-webpack": "^3.0.0", | ||
"babel-jest": "^27.0.2", | ||
"copy-webpack-plugin": "^9.0.0", | ||
"babel-jest": "^27.0.6", | ||
"copy-webpack-plugin": "^9.0.1", | ||
"cross-env": "^7.0.3", | ||
"del": "^6.0.0", | ||
"del-cli": "^3.0.1", | ||
"eslint": "^7.29.0", | ||
"esbuild": "^0.12.23", | ||
"eslint": "^7.32.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"eslint-plugin-import": "^2.22.1", | ||
"eslint-plugin-import": "^2.24.2", | ||
"file-loader": "^6.2.0", | ||
"husky": "^6.0.0", | ||
"jest": "^27.0.5", | ||
"lint-staged": "^11.0.0", | ||
"husky": "^7.0.2", | ||
"jest": "^27.0.6", | ||
"lint-staged": "^11.0.1", | ||
"memfs": "^3.2.2", | ||
"npm-run-all": "^4.1.5", | ||
"prettier": "^2.3.1", | ||
"standard-version": "^9.3.0", | ||
"typescript": "^4.3.4", | ||
"uglify-js": "^3.13.9", | ||
"webpack": "^5.40.0", | ||
"prettier": "^2.3.2", | ||
"standard-version": "^9.3.1", | ||
"typescript": "^4.3.5", | ||
"uglify-js": "^3.14.1", | ||
"webpack": "^5.48.0", | ||
"worker-loader": "^3.0.8" | ||
@@ -85,0 +100,0 @@ }, |
189
README.md
@@ -17,7 +17,7 @@ <div align="center"> | ||
This plugin uses [terser](https://github.com/terser-js/terser) to minify your JavaScript. | ||
This plugin uses [terser](https://github.com/terser-js/terser) to minify/minimize your JavaScript. | ||
## Getting Started | ||
If you are using webpack v5 or above you do not need to install this plugin. Webpack v5 comes with the latest `terser-webpack-plugin` out of the box. Using Webpack v4, you have to install `terser-webpack-plugin` v4. | ||
Webpack v5 comes with the latest `terser-webpack-plugin` out of the box. If you are using Webpack v5 or above and wish to customize the options, you will still need to install `terser-webpack-plugin`. Using Webpack v4, you have to install `terser-webpack-plugin` v4. | ||
@@ -60,2 +60,12 @@ To begin, you'll need to install `terser-webpack-plugin`: | ||
| Name | Type | Default | Description | | ||
| :---------------------------------------: | :-----------------------------------------------------------------------------: | :-------------------------------------------------------------: | :--------------------------------------------------------------------------- | | ||
| **[`test`](#test)** | `String\|RegExp\|Array<String\|RegExp>` | `/\.m?js(\?.*)?$/i` | Test to match files against. | | ||
| **[`include`](#include)** | `String\|RegExp\|Array<String\|RegExp>` | `undefined` | Files to include. | | ||
| **[`exclude`](#exclude)** | `String\|RegExp\|Array<String\|RegExp>` | `undefined` | Files to exclude. | | ||
| **[`parallel`](#parallel)** | `Boolean\|Number` | `true` | Use multi-process parallel running to improve the build speed. | | ||
| **[`minify`](#minify)** | `Function` | `TerserPlugin.terserMinify` | Allows you to override default minify function. | | ||
| **[`terserOptions`](#terseroptions)** | `Object` | [`default`](https://github.com/terser-js/terser#minify-options) | Terser [minify options](https://github.com/terser-js/terser#minify-options). | | ||
| **[`extractComments`](#extractcomments)** | `Boolean\|String\|RegExp\|Function<(node, comment) -> Boolean\|Object>\|Object` | `true` | Whether comments shall be extracted to a separate file. | | ||
### `test` | ||
@@ -180,3 +190,3 @@ | ||
Type: `Function` | ||
Default: `undefined` | ||
Default: `TerserPlugin.terserMinify` | ||
@@ -192,2 +202,33 @@ Allows you to override default minify function. | ||
```js | ||
// Can be async | ||
const minify = (input, sourceMap, minimizerOptions, extractsComments) => { | ||
// The `minimizerOptions` option contains option from the `terserOptions` option | ||
// You can use `minimizerOptions.myCustomOption` | ||
// Custom logic for extract comments | ||
const { map, code } = require("uglify-module") // Or require('./path/to/uglify-module') | ||
.minify(input, { | ||
/* Your options for minification */ | ||
}); | ||
return { map, code, warnings: [], errors: [], extractedComments: [] }; | ||
}; | ||
// Used to regenerate `fullhash`/`chunkhash` between different implementation | ||
// Example: you fix a bug in custom minimizer/custom function, but unfortunately webpack doesn't know about it, so you will get the same fullhash/chunkhash | ||
// to avoid this you can provide version of your custom minimizer | ||
// You don't need if you use only `contenthash` | ||
minify.getMinimizerVersion = () => { | ||
let packageJson; | ||
try { | ||
// eslint-disable-next-line global-require, import/no-extraneous-dependencies | ||
packageJson = require("uglify-module/package.json"); | ||
} catch (error) { | ||
// Ignore | ||
} | ||
return packageJson && packageJson.version; | ||
}; | ||
module.exports = { | ||
@@ -201,17 +242,3 @@ optimization: { | ||
}, | ||
// Can be async | ||
minify: (file, sourceMap, minimizerOptions) => { | ||
// The `minimizerOptions` option contains option from the `terserOptions` option | ||
// You can use `minimizerOptions.myCustomOption` | ||
const extractedComments = []; | ||
// Custom logic for extract comments | ||
const { map, code } = require("uglify-module") // Or require('./path/to/uglify-module') | ||
.minify(file, { | ||
/* Your options for minification */ | ||
}); | ||
return { map, code, extractedComments }; | ||
}, | ||
minify, | ||
}), | ||
@@ -228,3 +255,3 @@ ], | ||
Terser minify [options](https://github.com/terser-js/terser#minify-options). | ||
Terser [options](https://github.com/terser-js/terser#minify-options). | ||
@@ -527,2 +554,79 @@ **webpack.config.js** | ||
### [`uglify-js`](https://github.com/mishoo/UglifyJS) | ||
[`UglifyJS`](https://github.com/mishoo/UglifyJS) is a JavaScript parser, minifier, compressor and beautifier toolkit. | ||
**webpack.config.js** | ||
```js | ||
module.exports = { | ||
optimization: { | ||
minimize: true, | ||
minimizer: [ | ||
new TerserPlugin({ | ||
minify: TerserPlugin.uglifyJsMinify, | ||
// `terserOptions` options will be passed to `uglify-js` | ||
// Link to options - https://github.com/mishoo/UglifyJS#minify-options | ||
terserOptions: {}, | ||
}), | ||
], | ||
}, | ||
}; | ||
``` | ||
### [`swc`](https://github.com/swc-project/swc) | ||
[`swc`](https://github.com/swc-project/swc) is a super-fast compiler written in rust; producing widely-supported javascript from modern standards and typescript. | ||
> ⚠ the `extractComments` option is not supported and all comments will be removed by default, it will be fixed in future | ||
**webpack.config.js** | ||
```js | ||
module.exports = { | ||
optimization: { | ||
minimize: true, | ||
minimizer: [ | ||
new TerserPlugin({ | ||
minify: TerserPlugin.swcMinify, | ||
// `terserOptions` options will be passed to `swc` (`@swc/core`) | ||
// Link to options - https://swc.rs/docs/config-js-minify | ||
terserOptions: {}, | ||
}), | ||
], | ||
}, | ||
}; | ||
``` | ||
### [`esbuild`](https://github.com/evanw/esbuild) | ||
[`esbuild`](https://github.com/evanw/esbuild) is an extremely fast JavaScript bundler and minifier. | ||
> ⚠ the `extractComments` option is not supported and all legal comments (i.e. copyright, licenses and etc) will be preserved | ||
**webpack.config.js** | ||
```js | ||
module.exports = { | ||
optimization: { | ||
minimize: true, | ||
minimizer: [ | ||
new TerserPlugin({ | ||
minify: TerserPlugin.esbuildMinify, | ||
// `terserOptions` options will be passed to `esbuild` | ||
// Link to options - https://esbuild.github.io/api/#minify | ||
// Note: the `minify` options is true by default (and override other `minify*` options), so if you want to disable the `minifyIdentifiers` option (or other `minify*` options) please use: | ||
// terserOptions: { | ||
// minify: false, | ||
// minifyWhitespace: true, | ||
// minifyIdentifiers: false, | ||
// minifySyntax: true, | ||
// }, | ||
terserOptions: {}, | ||
}), | ||
], | ||
}, | ||
}; | ||
``` | ||
### Custom Minify Function | ||
@@ -560,2 +664,49 @@ | ||
### Typescript | ||
With default terser minify function: | ||
```ts | ||
module.exports = { | ||
optimization: { | ||
minimize: true, | ||
minimizer: [ | ||
new TerserPlugin({ | ||
terserOptions: { | ||
compress: true, | ||
}, | ||
}), | ||
], | ||
}, | ||
}; | ||
``` | ||
With built-in minify functions: | ||
```ts | ||
import type { SwcMinifyFunction } from "terser-webpack-plugin"; | ||
module.exports = { | ||
optimization: { | ||
minimize: true, | ||
minimizer: [ | ||
new TerserPlugin<SwcMinimizer>({ | ||
minify: TerserPlugin.swcMinify, | ||
terserOptions: { | ||
compress: true, | ||
}, | ||
}), | ||
// Alternative: | ||
new TerserPlugin<typeof TerserPlugin.swcMinify>({ | ||
minify: TerserPlugin.swcMinify, | ||
terserOptions: { | ||
compress: true, | ||
}, | ||
}), | ||
], | ||
}, | ||
}; | ||
``` | ||
## Contributing | ||
@@ -562,0 +713,0 @@ |
export default TerserPlugin; | ||
export type ExtractedCommentsInfo = { | ||
extractedCommentsSource: import("webpack").sources.RawSource; | ||
commentsFilename: string; | ||
}; | ||
export type Schema = import("schema-utils/declarations/validate").Schema; | ||
@@ -12,11 +8,11 @@ export type Compiler = import("webpack").Compiler; | ||
export type TerserECMA = import("terser").ECMA; | ||
export type TerserMinifyOptions = import("terser").MinifyOptions; | ||
export type JestWorker = import("jest-worker").default; | ||
export type TerserOptions = import("terser").MinifyOptions; | ||
export type UglifyJSOptions = import("uglify-js").MinifyOptions; | ||
export type SwcOptions = import("@swc/core").JsMinifyOptions; | ||
export type EsbuildOptions = import("esbuild").TransformOptions; | ||
export type CustomOptions = any; | ||
export type JestWorker = import("jest-worker").Worker; | ||
export type RawSourceMap = import("source-map").RawSourceMap; | ||
export type InternalMinifyOptions = import("./minify.js").InternalMinifyOptions; | ||
export type InternalMinifyResult = import("./minify.js").InternalMinifyResult; | ||
export type CustomMinifyOptions = import("./minify.js").CustomMinifyOptions; | ||
export type Rule = RegExp | string; | ||
export type Rules = Rule[] | Rule; | ||
export type MinifyWorker = MinifyWorker; | ||
export type ExtractCommentsFunction = ( | ||
@@ -34,3 +30,4 @@ astNode: any, | ||
| boolean | ||
| string | ||
| "all" | ||
| "some" | ||
| RegExp | ||
@@ -48,33 +45,76 @@ | ExtractCommentsFunction; | ||
}; | ||
export type CustomMinifyFunction = ( | ||
fileAndCode: { | ||
[file: string]: string; | ||
}, | ||
sourceMap?: import("source-map").RawSourceMap | undefined, | ||
minifyOptions: any | ||
) => any; | ||
export type ExtractCommentsOptions = | ||
| ExtractCommentsCondition | ||
| ExtractCommentsObject; | ||
export type PluginWithTerserOptions = { | ||
test?: Rules | undefined; | ||
include?: Rules | undefined; | ||
exclude?: Rules | undefined; | ||
terserOptions?: import("terser").MinifyOptions | undefined; | ||
extractComments?: ExtractCommentsOptions | undefined; | ||
parallel?: boolean | undefined; | ||
minify?: CustomMinifyFunction | undefined; | ||
export type Input = { | ||
[file: string]: string; | ||
}; | ||
export type PluginWithCustomMinifyOptions = { | ||
export type MinimizedResult = { | ||
code: string; | ||
map?: import("source-map").RawSourceMap | undefined; | ||
errors?: (string | Error)[] | undefined; | ||
warnings?: (string | Error)[] | undefined; | ||
extractedComments?: string[] | undefined; | ||
}; | ||
export type PredefinedOptions = { | ||
module?: boolean | undefined; | ||
ecma?: string | number | undefined; | ||
}; | ||
export type MinimizerImplementationAndOptions<T> = { | ||
implementation: MinimizerImplementation<ThirdArgument<T>>; | ||
options: PredefinedOptions & ThirdArgument<T>; | ||
}; | ||
export type InternalOptions<T> = { | ||
name: string; | ||
input: string; | ||
inputSourceMap: RawSourceMap | undefined; | ||
extractComments: ExtractCommentsOptions | undefined; | ||
minimizer: MinimizerImplementationAndOptions<T>; | ||
}; | ||
export type MinimizerWorker<T> = Worker & { | ||
transform: (options: string) => MinimizedResult; | ||
minify: (options: InternalOptions<T>) => MinimizedResult; | ||
}; | ||
export type BasicMinimizerImplementation<T> = ( | ||
input: Input, | ||
sourceMap: RawSourceMap | undefined, | ||
minifyOptions: T, | ||
extractComments: ExtractCommentsOptions | undefined | ||
) => Promise<MinimizedResult>; | ||
export type MinimizeFunctionHelpers = { | ||
getMinimizerVersion?: (() => string | undefined) | undefined; | ||
}; | ||
export type MinimizerImplementation<T> = BasicMinimizerImplementation<T> & | ||
MinimizeFunctionHelpers; | ||
export type TerserMinimizer = MinimizerImplementation<TerserOptions>; | ||
export type UglifyJSMinimizer = MinimizerImplementation<UglifyJSOptions>; | ||
export type SwcMinimizer = MinimizerImplementation<SwcOptions>; | ||
export type EsbuildMinimizer = MinimizerImplementation<EsbuildOptions>; | ||
export type CustomMinimizer = MinimizerImplementation<CustomOptions>; | ||
export type BasePluginOptions = { | ||
test?: Rules | undefined; | ||
include?: Rules | undefined; | ||
exclude?: Rules | undefined; | ||
terserOptions?: any; | ||
extractComments?: ExtractCommentsOptions | undefined; | ||
parallel?: boolean | undefined; | ||
minify?: CustomMinifyFunction | undefined; | ||
}; | ||
export type TerserPluginOptions = | ||
| PluginWithTerserOptions | ||
| PluginWithCustomMinifyOptions; | ||
export type ThirdArgument<T> = T extends ( | ||
arg1: any, | ||
arg2: any, | ||
arg3: infer U, | ||
...args: any[] | ||
) => any | ||
? U | ||
: never; | ||
export type DefaultMinimizerImplementationAndOptions<T> = { | ||
minify?: undefined | MinimizerImplementation<ThirdArgument<T>>; | ||
terserOptions?: ThirdArgument<T> | undefined; | ||
}; | ||
export type PickMinimizerImplementationAndOptions<T> = | ||
T extends MinimizerImplementation<TerserOptions> | ||
? DefaultMinimizerImplementationAndOptions<T> | ||
: { | ||
minify: MinimizerImplementation<ThirdArgument<T>>; | ||
terserOptions?: ThirdArgument<T> | undefined; | ||
}; | ||
/** @typedef {import("schema-utils/declarations/validate").Schema} Schema */ | ||
@@ -86,11 +126,11 @@ /** @typedef {import("webpack").Compiler} Compiler */ | ||
/** @typedef {import("terser").ECMA} TerserECMA */ | ||
/** @typedef {import("terser").MinifyOptions} TerserMinifyOptions */ | ||
/** @typedef {import("jest-worker").default} JestWorker */ | ||
/** @typedef {import("terser").MinifyOptions} TerserOptions */ | ||
/** @typedef {import("uglify-js").MinifyOptions} UglifyJSOptions */ | ||
/** @typedef {import("@swc/core").JsMinifyOptions} SwcOptions */ | ||
/** @typedef {import("esbuild").TransformOptions} EsbuildOptions */ | ||
/** @typedef {Object.<any, any>} CustomOptions */ | ||
/** @typedef {import("jest-worker").Worker} JestWorker */ | ||
/** @typedef {import("source-map").RawSourceMap} RawSourceMap */ | ||
/** @typedef {import("./minify.js").InternalMinifyOptions} InternalMinifyOptions */ | ||
/** @typedef {import("./minify.js").InternalMinifyResult} InternalMinifyResult */ | ||
/** @typedef {import("./minify.js").CustomMinifyOptions} CustomMinifyOptions */ | ||
/** @typedef {RegExp | string} Rule */ | ||
/** @typedef {Rule[] | Rule} Rules */ | ||
/** @typedef {JestWorker & { transform: (options: string) => InternalMinifyResult, minify: (options: InternalMinifyOptions) => InternalMinifyResult }} MinifyWorker */ | ||
/** | ||
@@ -103,3 +143,3 @@ * @callback ExtractCommentsFunction | ||
/** | ||
* @typedef {boolean | string | RegExp | ExtractCommentsFunction} ExtractCommentsCondition | ||
* @typedef {boolean | 'all' | 'some' | RegExp | ExtractCommentsFunction} ExtractCommentsCondition | ||
*/ | ||
@@ -119,34 +159,104 @@ /** | ||
/** | ||
* @callback CustomMinifyFunction | ||
* @param {{ [file: string]: string }} fileAndCode | ||
* @param {RawSourceMap} [sourceMap] | ||
* @param {Object.<any, any>} minifyOptions | ||
* @typedef {ExtractCommentsCondition | ExtractCommentsObject} ExtractCommentsOptions | ||
*/ | ||
/** | ||
* @typedef {ExtractCommentsCondition | ExtractCommentsObject} ExtractCommentsOptions | ||
* @typedef {{ [file: string]: string }} Input | ||
*/ | ||
/** | ||
* @typedef {Object} PluginWithTerserOptions | ||
* @property {Rules} [test] | ||
* @property {Rules} [include] | ||
* @property {Rules} [exclude] | ||
* @property {TerserMinifyOptions} [terserOptions] | ||
* @property {ExtractCommentsOptions} [extractComments] | ||
* @property {boolean} [parallel] | ||
* @property {CustomMinifyFunction} [minify] | ||
* @typedef {Object} MinimizedResult | ||
* @property {string} code | ||
* @property {RawSourceMap} [map] | ||
* @property {Array<Error | string>} [errors] | ||
* @property {Array<Error | string>} [warnings] | ||
* @property {Array<string>} [extractedComments] | ||
*/ | ||
/** | ||
* @typedef {Object} PluginWithCustomMinifyOptions | ||
* @typedef {Object} PredefinedOptions | ||
* @property {boolean} [module] | ||
* @property {5 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | number | string} [ecma] | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {Object} MinimizerImplementationAndOptions | ||
* @property {MinimizerImplementation<ThirdArgument<T>>} implementation | ||
* @property {PredefinedOptions & ThirdArgument<T>} options | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {Object} InternalOptions | ||
* @property {string} name | ||
* @property {string} input | ||
* @property {RawSourceMap | undefined} inputSourceMap | ||
* @property {ExtractCommentsOptions | undefined} extractComments | ||
* @property {MinimizerImplementationAndOptions<T>} minimizer | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {JestWorker & { transform: (options: string) => MinimizedResult, minify: (options: InternalOptions<T>) => MinimizedResult }} MinimizerWorker | ||
*/ | ||
/** | ||
* @template T | ||
* @callback BasicMinimizerImplementation | ||
* @param {Input} input | ||
* @param {RawSourceMap | undefined} sourceMap | ||
* @param {T} minifyOptions | ||
* @param {ExtractCommentsOptions | undefined} extractComments | ||
* @returns {Promise<MinimizedResult>} | ||
*/ | ||
/** | ||
* @typedef {object} MinimizeFunctionHelpers | ||
* @property {() => string | undefined} [getMinimizerVersion] | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {BasicMinimizerImplementation<T> & MinimizeFunctionHelpers } MinimizerImplementation | ||
*/ | ||
/** | ||
* @typedef {MinimizerImplementation<TerserOptions>} TerserMinimizer | ||
*/ | ||
/** | ||
* @typedef {MinimizerImplementation<UglifyJSOptions>} UglifyJSMinimizer | ||
*/ | ||
/** | ||
* @typedef {MinimizerImplementation<SwcOptions>} SwcMinimizer | ||
*/ | ||
/** | ||
* @typedef {MinimizerImplementation<EsbuildOptions>} EsbuildMinimizer | ||
*/ | ||
/** | ||
* @typedef {MinimizerImplementation<CustomOptions>} CustomMinimizer | ||
*/ | ||
/** | ||
* @typedef {Object} BasePluginOptions | ||
* @property {Rules} [test] | ||
* @property {Rules} [include] | ||
* @property {Rules} [exclude] | ||
* @property {Object.<any, any>} [terserOptions] | ||
* @property {ExtractCommentsOptions} [extractComments] | ||
* @property {boolean} [parallel] | ||
* @property {CustomMinifyFunction} [minify] | ||
*/ | ||
/** | ||
* @typedef {PluginWithTerserOptions | PluginWithCustomMinifyOptions} TerserPluginOptions | ||
* @template T | ||
* @typedef {T extends (arg1: any, arg2: any, arg3: infer U, ...args: any[]) => any ? U: never} ThirdArgument | ||
*/ | ||
declare class TerserPlugin { | ||
/** | ||
* @template T | ||
* @typedef {Object} DefaultMinimizerImplementationAndOptions | ||
* @property {undefined | MinimizerImplementation<ThirdArgument<T>>} [minify] | ||
* @property {ThirdArgument<T> | undefined} [terserOptions] | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {T extends MinimizerImplementation<TerserOptions> ? DefaultMinimizerImplementationAndOptions<T> : { minify: MinimizerImplementation<ThirdArgument<T>>, terserOptions?: ThirdArgument<T> | undefined}} PickMinimizerImplementationAndOptions | ||
*/ | ||
/** | ||
* @template {TerserMinimizer | UglifyJSMinimizer | SwcMinimizer | EsbuildMinimizer | CustomMinimizer} T=TerserMinimizer | ||
*/ | ||
declare class TerserPlugin< | ||
T extends | ||
| TerserMinimizer | ||
| UglifyJSMinimizer | ||
| SwcMinimizer | ||
| EsbuildMinimizer | ||
| CustomMinimizer | ||
> { | ||
/** | ||
@@ -160,7 +270,14 @@ * @private | ||
* @private | ||
* @param {Error & { line: number, col: number}} error | ||
* @param {Error | string} warning | ||
* @param {string} file | ||
* @returns {WebpackError} | ||
*/ | ||
private static buildWarning; | ||
/** | ||
* @private | ||
* @param {any} error | ||
* @param {string} file | ||
* @param {Compilation["requestShortener"]} [requestShortener] | ||
* @param {SourceMapConsumer} [sourceMap] | ||
* @returns {Error} | ||
* @returns {WebpackError} | ||
*/ | ||
@@ -170,3 +287,3 @@ private static buildError; | ||
* @private | ||
* @param {boolean} parallel | ||
* @param {boolean | undefined} parallel | ||
* @returns {number} | ||
@@ -182,15 +299,18 @@ */ | ||
/** | ||
* @param {TerserPluginOptions} options | ||
* @param {BasePluginOptions & PickMinimizerImplementationAndOptions<T>} [options] | ||
*/ | ||
constructor(options?: TerserPluginOptions); | ||
options: { | ||
test: Rules; | ||
extractComments: ExtractCommentsOptions; | ||
parallel: boolean; | ||
include: Rules | undefined; | ||
exclude: Rules | undefined; | ||
minify: CustomMinifyFunction | undefined; | ||
terserOptions: any; | ||
constructor( | ||
options?: | ||
| (BasePluginOptions & PickMinimizerImplementationAndOptions<T>) | ||
| undefined | ||
); | ||
/** | ||
* @type {BasePluginOptions & { minify: MinimizerImplementation<ThirdArgument<T>>, terserOptions: ThirdArgument<T>}} | ||
*/ | ||
options: BasePluginOptions & { | ||
minify: MinimizerImplementation<ThirdArgument<T>>; | ||
terserOptions: ThirdArgument<T>; | ||
}; | ||
/** | ||
* @private | ||
* @param {Compiler} compiler | ||
@@ -202,10 +322,3 @@ * @param {Compilation} compilation | ||
*/ | ||
optimize( | ||
compiler: Compiler, | ||
compilation: Compilation, | ||
assets: Record<string, import("webpack").sources.Source>, | ||
optimizeOptions: { | ||
availableNumberOfCores: number; | ||
} | ||
): Promise<void>; | ||
private optimize; | ||
/** | ||
@@ -217,1 +330,12 @@ * @param {Compiler} compiler | ||
} | ||
declare namespace TerserPlugin { | ||
export { terserMinify }; | ||
export { uglifyJsMinify }; | ||
export { swcMinify }; | ||
export { esbuildMinify }; | ||
} | ||
import { Worker } from "jest-worker"; | ||
import { terserMinify } from "./utils"; | ||
import { uglifyJsMinify } from "./utils"; | ||
import { swcMinify } from "./utils"; | ||
import { esbuildMinify } from "./utils"; |
@@ -1,51 +0,15 @@ | ||
export type RawSourceMap = import("source-map").RawSourceMap; | ||
export type ExtractCommentsOptions = | ||
import("./index.js").ExtractCommentsOptions; | ||
export type CustomMinifyFunction = import("./index.js").CustomMinifyFunction; | ||
export type TerserMinifyOptions = import("terser").MinifyOptions; | ||
export type MinifyOutput = import("terser").MinifyOutput; | ||
export type FormatOptions = import("terser").FormatOptions; | ||
export type MangleOptions = import("terser").MangleOptions; | ||
export type ExtractCommentsFunction = | ||
import("./index.js").ExtractCommentsFunction; | ||
export type ExtractCommentsCondition = | ||
import("./index.js").ExtractCommentsCondition; | ||
export type CustomMinifyOptions = any; | ||
export type InternalMinifyOptions = { | ||
name: string; | ||
input: string; | ||
inputSourceMap?: import("source-map").RawSourceMap | undefined; | ||
extractComments: ExtractCommentsOptions; | ||
minify?: import("./index.js").CustomMinifyFunction | undefined; | ||
minifyOptions: TerserMinifyOptions | CustomMinifyOptions; | ||
}; | ||
export type ExtractedComments = Array<string>; | ||
export type InternalMinifyResult = Promise< | ||
MinifyOutput & { | ||
extractedComments?: string[]; | ||
} | ||
>; | ||
export type NormalizedTerserMinifyOptions = TerserMinifyOptions & { | ||
sourceMap: undefined; | ||
} & ( | ||
| { | ||
output: FormatOptions & { | ||
beautify: boolean; | ||
}; | ||
} | ||
| { | ||
format: FormatOptions & { | ||
beautify: boolean; | ||
}; | ||
} | ||
); | ||
export type MinimizedResult = import("./index.js").MinimizedResult; | ||
/** @typedef {import("./index.js").MinimizedResult} MinimizedResult */ | ||
/** | ||
* @param {InternalMinifyOptions} options | ||
* @returns {InternalMinifyResult} | ||
* @template T | ||
* @param {import("./index.js").InternalOptions<T>} options | ||
* @returns {Promise<MinimizedResult>} | ||
*/ | ||
export function minify(options: InternalMinifyOptions): InternalMinifyResult; | ||
export function minify<T>( | ||
options: import("./index.js").InternalOptions<T> | ||
): Promise<MinimizedResult>; | ||
/** | ||
* @param {string} options | ||
* @returns {InternalMinifyResult} | ||
* @returns {Promise<MinimizedResult>} | ||
*/ | ||
export function transform(options: string): InternalMinifyResult; | ||
export function transform(options: string): Promise<MinimizedResult>; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses eval() which is a dangerous function. This prevents the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
90331
12
1812
728
30
+ Added@types/node@20.12.11(transitive)
+ Addedcaniuse-lite@1.0.30001616(transitive)
+ Addedelectron-to-chromium@1.4.763(transitive)
+ Addedupdate-browserslist-db@1.0.15(transitive)
- Removed@types/node@20.12.12(transitive)
- Removedcaniuse-lite@1.0.30001620(transitive)
- Removedelectron-to-chromium@1.4.773(transitive)
- Removedupdate-browserslist-db@1.0.16(transitive)
Updatedjest-worker@^27.0.6
Updatedschema-utils@^3.1.1
Updatedterser@^5.7.2