uglifyjs-webpack-plugin
Advanced tools
Comparing version 1.3.0 to 2.0.0
@@ -5,2 +5,24 @@ # Change Log | ||
<a name="2.0.0"></a> | ||
# [2.0.0](https://github.com/webpack-contrib/uglifyjs-webpack-plugin/compare/v1.3.0...v2.0.0) (2018-09-14) | ||
### Bug Fixes | ||
* default extract comment condition is case insensitivity | ||
### Features | ||
* full coverage schema options validation | ||
* enable inline optimization by default | ||
### BREAKING CHANGES | ||
* Switch back to [uglify-js](https://github.com/mishoo/UglifyJS2) (`uglify-es` is abandoned, if you need uglify ES6 code please use [terser-webpack-plugin](https://github.com/webpack-contrib/terser-webpack-plugin)). | ||
* Changed function signature for `warningsFilter` option (now first argument is `warning`, second is `source`). | ||
* Enforces `peerDependencies` of `"webpack": "^4.3.0`. | ||
* Enforces `engines` of `"node": ">= 6.9.0 <7.0.0 || >= 8.9.0` | ||
<a name="1.3.0"></a> | ||
@@ -7,0 +29,0 @@ # [1.3.0](https://github.com/webpack-contrib/uglifyjs-webpack-plugin/compare/v1.2.7...v1.3.0) (2018-08-14) |
'use strict'; | ||
module.exports = require('./index').default; | ||
const plugin = require('./index'); | ||
module.exports = plugin.default; |
@@ -7,7 +7,2 @@ 'use strict'; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /* eslint-disable | ||
no-param-reassign | ||
*/ | ||
var _crypto = require('crypto'); | ||
@@ -41,45 +36,31 @@ | ||
var _Runner = require('./uglify/Runner'); | ||
var _TaskRunner = require('./TaskRunner'); | ||
var _Runner2 = _interopRequireDefault(_Runner); | ||
var _TaskRunner2 = _interopRequireDefault(_TaskRunner); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
const warningRegex = /\[.+:([0-9]+),([0-9]+)\]/; /* eslint-disable | ||
no-param-reassign | ||
*/ | ||
var warningRegex = /\[.+:([0-9]+),([0-9]+)\]/; | ||
var UglifyJsPlugin = function () { | ||
function UglifyJsPlugin() { | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
_classCallCheck(this, UglifyJsPlugin); | ||
class UglifyJsPlugin { | ||
constructor(options = {}) { | ||
(0, _schemaUtils2.default)(_options2.default, options, 'UglifyJs Plugin'); | ||
var minify = options.minify, | ||
_options$uglifyOption = options.uglifyOptions, | ||
uglifyOptions = _options$uglifyOption === undefined ? {} : _options$uglifyOption, | ||
_options$test = options.test, | ||
test = _options$test === undefined ? /\.js(\?.*)?$/i : _options$test, | ||
_options$warningsFilt = options.warningsFilter, | ||
warningsFilter = _options$warningsFilt === undefined ? function () { | ||
return true; | ||
} : _options$warningsFilt, | ||
_options$extractComme = options.extractComments, | ||
extractComments = _options$extractComme === undefined ? false : _options$extractComme, | ||
_options$sourceMap = options.sourceMap, | ||
sourceMap = _options$sourceMap === undefined ? false : _options$sourceMap, | ||
_options$cache = options.cache, | ||
cache = _options$cache === undefined ? false : _options$cache, | ||
_options$cacheKeys = options.cacheKeys, | ||
cacheKeys = _options$cacheKeys === undefined ? function (defaultCacheKeys) { | ||
return defaultCacheKeys; | ||
} : _options$cacheKeys, | ||
_options$parallel = options.parallel, | ||
parallel = _options$parallel === undefined ? false : _options$parallel, | ||
include = options.include, | ||
exclude = options.exclude; | ||
const { | ||
minify, | ||
uglifyOptions = {}, | ||
test = /\.js(\?.*)?$/i, | ||
warningsFilter = () => true, | ||
extractComments = false, | ||
sourceMap = false, | ||
cache = false, | ||
cacheKeys = defaultCacheKeys => defaultCacheKeys, | ||
parallel = false, | ||
include, | ||
exclude | ||
} = options; | ||
this.options = { | ||
@@ -97,7 +78,4 @@ test, | ||
uglifyOptions: Object.assign({ | ||
compress: { | ||
inline: 1 | ||
}, | ||
output: { | ||
comments: extractComments ? false : /^\**!|@preserve|@license|@cc_on/ | ||
comments: extractComments ? false : /^\**!|@preserve|@license|@cc_on/i | ||
} | ||
@@ -108,281 +86,250 @@ }, uglifyOptions) | ||
_createClass(UglifyJsPlugin, [{ | ||
key: 'apply', | ||
value: function apply(compiler) { | ||
var _this = this; | ||
static isSourceMap(input) { | ||
// All required options for `new SourceMapConsumer(...options)` | ||
// https://github.com/mozilla/source-map#new-sourcemapconsumerrawsourcemap | ||
return Boolean(input && input.version && input.sources && Array.isArray(input.sources) && typeof input.mappings === 'string'); | ||
} | ||
var buildModuleFn = function buildModuleFn(moduleArg) { | ||
// to get detailed location info about errors | ||
moduleArg.useSourceMap = true; | ||
}; | ||
static buildSourceMap(inputSourceMap) { | ||
if (!inputSourceMap || !UglifyJsPlugin.isSourceMap(inputSourceMap)) { | ||
return null; | ||
} | ||
var optimizeFn = function optimizeFn(compilation, chunks, callback) { | ||
var runner = new _Runner2.default({ | ||
cache: _this.options.cache, | ||
parallel: _this.options.parallel | ||
}); | ||
return new _sourceMap.SourceMapConsumer(inputSourceMap); | ||
} | ||
var uglifiedAssets = new WeakSet(); | ||
var tasks = []; | ||
static buildError(err, file, sourceMap, requestShortener) { | ||
// Handling error which should have line, col, filename and message | ||
if (err.line) { | ||
const original = sourceMap && sourceMap.originalPositionFor({ | ||
line: err.line, | ||
column: err.col | ||
}); | ||
chunks.reduce(function (acc, chunk) { | ||
return acc.concat(chunk.files || []); | ||
}, []).concat(compilation.additionalChunkAssets || []).filter(_ModuleFilenameHelpers2.default.matchObject.bind(null, _this.options)).forEach(function (file) { | ||
var inputSourceMap = void 0; | ||
if (original && original.source && requestShortener) { | ||
return new Error(`${file} from UglifyJs\n${err.message} [${requestShortener.shorten(original.source)}:${original.line},${original.column}][${file}:${err.line},${err.col}]`); | ||
} | ||
var asset = compilation.assets[file]; | ||
return new Error(`${file} from UglifyJs\n${err.message} [${file}:${err.line},${err.col}]`); | ||
} else if (err.stack) { | ||
return new Error(`${file} from UglifyJs\n${err.stack}`); | ||
} | ||
if (uglifiedAssets.has(asset)) { | ||
return; | ||
} | ||
return new Error(`${file} from UglifyJs\n${err.message}`); | ||
} | ||
try { | ||
var input = void 0; | ||
static buildWarning(warning, file, sourceMap, requestShortener, warningsFilter) { | ||
let warningMessage = warning; | ||
let locationMessage = ''; | ||
let source = null; | ||
if (_this.options.sourceMap && asset.sourceAndMap) { | ||
var _asset$sourceAndMap = asset.sourceAndMap(), | ||
source = _asset$sourceAndMap.source, | ||
map = _asset$sourceAndMap.map; | ||
if (sourceMap) { | ||
const match = warningRegex.exec(warning); | ||
input = source; | ||
if (match) { | ||
const line = +match[1]; | ||
const column = +match[2]; | ||
const original = sourceMap.originalPositionFor({ | ||
line, | ||
column | ||
}); | ||
if (UglifyJsPlugin.isSourceMap(map)) { | ||
inputSourceMap = map; | ||
} else { | ||
inputSourceMap = map; | ||
if (original && original.source && original.source !== file && requestShortener) { | ||
({ source } = original); | ||
warningMessage = `${warningMessage.replace(warningRegex, '')}`; | ||
compilation.warnings.push(new Error(`${file} contains invalid source map`)); | ||
} | ||
} else { | ||
input = asset.source(); | ||
inputSourceMap = null; | ||
} | ||
locationMessage = `[${requestShortener.shorten(original.source)}:${original.line},${original.column}]`; | ||
} | ||
} | ||
} | ||
// Handling comment extraction | ||
var commentsFile = false; | ||
if (warningsFilter && !warningsFilter(warning, source)) { | ||
return null; | ||
} | ||
if (_this.options.extractComments) { | ||
commentsFile = _this.options.extractComments.filename || `${file}.LICENSE`; | ||
return `UglifyJs Plugin: ${warningMessage}${locationMessage}`; | ||
} | ||
if (typeof commentsFile === 'function') { | ||
commentsFile = commentsFile(file); | ||
} | ||
} | ||
apply(compiler) { | ||
const buildModuleFn = moduleArg => { | ||
// to get detailed location info about errors | ||
moduleArg.useSourceMap = true; | ||
}; | ||
var task = { | ||
file, | ||
input, | ||
inputSourceMap, | ||
commentsFile, | ||
extractComments: _this.options.extractComments, | ||
uglifyOptions: _this.options.uglifyOptions, | ||
minify: _this.options.minify | ||
}; | ||
const optimizeFn = (compilation, chunks, callback) => { | ||
const taskRunner = new _TaskRunner2.default({ | ||
cache: this.options.cache, | ||
parallel: this.options.parallel | ||
}); | ||
if (_this.options.cache) { | ||
var defaultCacheKeys = { | ||
// eslint-disable-next-line global-require | ||
'uglify-es': require('uglify-es/package.json').version, | ||
// eslint-disable-next-line global-require | ||
'uglifyjs-webpack-plugin': require('../package.json').version, | ||
'uglifyjs-webpack-plugin-options': _this.options, | ||
path: compiler.outputPath ? `${compiler.outputPath}/${file}` : file, | ||
hash: _crypto2.default.createHash('md4').update(input).digest('hex') | ||
}; | ||
const processedAssets = new WeakSet(); | ||
const tasks = []; | ||
task.cacheKeys = _this.options.cacheKeys(defaultCacheKeys, file); | ||
} | ||
chunks.reduce((acc, chunk) => acc.concat(chunk.files || []), []).concat(compilation.additionalChunkAssets || []).filter(_ModuleFilenameHelpers2.default.matchObject.bind(null, this.options)).forEach(file => { | ||
let inputSourceMap; | ||
tasks.push(task); | ||
} catch (error) { | ||
compilation.errors.push(UglifyJsPlugin.buildError(error, file, UglifyJsPlugin.buildSourceMap(inputSourceMap), new _RequestShortener2.default(compiler.context))); | ||
} | ||
}); | ||
const asset = compilation.assets[file]; | ||
runner.runTasks(tasks, function (tasksError, results) { | ||
if (tasksError) { | ||
compilation.errors.push(tasksError); | ||
if (processedAssets.has(asset)) { | ||
return; | ||
} | ||
return; | ||
} | ||
try { | ||
let input; | ||
results.forEach(function (data, index) { | ||
var _tasks$index = tasks[index], | ||
file = _tasks$index.file, | ||
input = _tasks$index.input, | ||
inputSourceMap = _tasks$index.inputSourceMap, | ||
commentsFile = _tasks$index.commentsFile; | ||
var error = data.error, | ||
map = data.map, | ||
code = data.code, | ||
warnings = data.warnings, | ||
extractedComments = data.extractedComments; | ||
if (this.options.sourceMap && asset.sourceAndMap) { | ||
const { source, map } = asset.sourceAndMap(); | ||
input = source; | ||
var sourceMap = null; | ||
if (UglifyJsPlugin.isSourceMap(map)) { | ||
inputSourceMap = map; | ||
} else { | ||
inputSourceMap = map; | ||
if (error || warnings && warnings.length > 0) { | ||
sourceMap = UglifyJsPlugin.buildSourceMap(inputSourceMap); | ||
compilation.warnings.push(new Error(`${file} contains invalid source map`)); | ||
} | ||
} else { | ||
input = asset.source(); | ||
inputSourceMap = null; | ||
} | ||
// Handling results | ||
// Error case: add errors, and go to next file | ||
if (error) { | ||
compilation.errors.push(UglifyJsPlugin.buildError(error, file, sourceMap, new _RequestShortener2.default(compiler.context))); | ||
// Handling comment extraction | ||
let commentsFile = false; | ||
return; | ||
} | ||
if (this.options.extractComments) { | ||
commentsFile = this.options.extractComments.filename || `${file}.LICENSE`; | ||
var outputSource = void 0; | ||
if (map) { | ||
outputSource = new _webpackSources.SourceMapSource(code, file, JSON.parse(map), input, inputSourceMap); | ||
} else { | ||
outputSource = new _webpackSources.RawSource(code); | ||
if (typeof commentsFile === 'function') { | ||
commentsFile = commentsFile(file); | ||
} | ||
} | ||
// Write extracted comments to commentsFile | ||
if (commentsFile && extractedComments.length > 0) { | ||
// Add a banner to the original file | ||
if (_this.options.extractComments.banner !== false) { | ||
var banner = _this.options.extractComments.banner || `For license information please see ${_path2.default.posix.basename(commentsFile)}`; | ||
const task = { | ||
file, | ||
input, | ||
inputSourceMap, | ||
commentsFile, | ||
extractComments: this.options.extractComments, | ||
uglifyOptions: this.options.uglifyOptions, | ||
minify: this.options.minify | ||
}; | ||
if (typeof banner === 'function') { | ||
banner = banner(commentsFile); | ||
} | ||
if (this.options.cache) { | ||
const { outputPath } = compiler; | ||
const defaultCacheKeys = { | ||
// eslint-disable-next-line global-require | ||
'uglify-js': require('uglify-js/package.json').version, | ||
// eslint-disable-next-line global-require | ||
'uglifyjs-webpack-plugin': require('../package.json').version, | ||
'uglifyjs-webpack-plugin-options': this.options, | ||
path: `${outputPath ? `${outputPath}/` : ''}${file}`, | ||
hash: _crypto2.default.createHash('md4').update(input).digest('hex') | ||
}; | ||
if (banner) { | ||
outputSource = new _webpackSources.ConcatSource(`/*! ${banner} */\n`, outputSource); | ||
} | ||
} | ||
task.cacheKeys = this.options.cacheKeys(defaultCacheKeys, file); | ||
} | ||
var commentsSource = new _webpackSources.RawSource(`${extractedComments.join('\n\n')}\n`); | ||
tasks.push(task); | ||
} catch (error) { | ||
compilation.errors.push(UglifyJsPlugin.buildError(error, file, UglifyJsPlugin.buildSourceMap(inputSourceMap), new _RequestShortener2.default(compiler.context))); | ||
} | ||
}); | ||
if (commentsFile in compilation.assets) { | ||
// commentsFile already exists, append new comments... | ||
if (compilation.assets[commentsFile] instanceof _webpackSources.ConcatSource) { | ||
compilation.assets[commentsFile].add('\n'); | ||
compilation.assets[commentsFile].add(commentsSource); | ||
} else { | ||
compilation.assets[commentsFile] = new _webpackSources.ConcatSource(compilation.assets[commentsFile], '\n', commentsSource); | ||
} | ||
} else { | ||
compilation.assets[commentsFile] = commentsSource; | ||
} | ||
} | ||
taskRunner.run(tasks, (tasksError, results) => { | ||
if (tasksError) { | ||
compilation.errors.push(tasksError); | ||
// Updating assets | ||
uglifiedAssets.add(compilation.assets[file] = outputSource); | ||
return; | ||
} | ||
// Handling warnings | ||
if (warnings && warnings.length > 0) { | ||
warnings.forEach(function (warning) { | ||
var builtWarning = UglifyJsPlugin.buildWarning(warning, file, sourceMap, _this.options.warningsFilter, new _RequestShortener2.default(compiler.context)); | ||
results.forEach((data, index) => { | ||
const { file, input, inputSourceMap, commentsFile } = tasks[index]; | ||
const { error, map, code, warnings, extractedComments } = data; | ||
if (builtWarning) { | ||
compilation.warnings.push(builtWarning); | ||
} | ||
}); | ||
} | ||
}); | ||
let sourceMap = null; | ||
runner.exit(); | ||
if (error || warnings && warnings.length > 0) { | ||
sourceMap = UglifyJsPlugin.buildSourceMap(inputSourceMap); | ||
} | ||
callback(); | ||
}); | ||
}; | ||
// Handling results | ||
// Error case: add errors, and go to next file | ||
if (error) { | ||
compilation.errors.push(UglifyJsPlugin.buildError(error, file, sourceMap, new _RequestShortener2.default(compiler.context))); | ||
/* istanbul ignore if */ | ||
if (compiler.hooks) { | ||
var plugin = { name: 'UglifyJSPlugin' }; | ||
compiler.hooks.compilation.tap(plugin, function (compilation) { | ||
if (_this.options.sourceMap) { | ||
compilation.hooks.buildModule.tap(plugin, buildModuleFn); | ||
return; | ||
} | ||
compilation.hooks.optimizeChunkAssets.tapAsync(plugin, optimizeFn.bind(_this, compilation)); | ||
}); | ||
} else { | ||
compiler.plugin('compilation', function (compilation) { | ||
if (_this.options.sourceMap) { | ||
compilation.plugin('build-module', buildModuleFn); | ||
let outputSource; | ||
if (map) { | ||
outputSource = new _webpackSources.SourceMapSource(code, file, JSON.parse(map), input, inputSourceMap); | ||
} else { | ||
outputSource = new _webpackSources.RawSource(code); | ||
} | ||
compilation.plugin('optimize-chunk-assets', optimizeFn.bind(_this, compilation)); | ||
}); | ||
} | ||
} | ||
}], [{ | ||
key: 'isSourceMap', | ||
value: function isSourceMap(input) { | ||
// All required options for `new SourceMapConsumer(...options)` | ||
// https://github.com/mozilla/source-map#new-sourcemapconsumerrawsourcemap | ||
return Boolean(input && input.version && input.sources && Array.isArray(input.sources) && typeof input.mappings === 'string'); | ||
} | ||
}, { | ||
key: 'buildSourceMap', | ||
value: function buildSourceMap(inputSourceMap) { | ||
if (!inputSourceMap || !UglifyJsPlugin.isSourceMap(inputSourceMap)) { | ||
return null; | ||
} | ||
// Write extracted comments to commentsFile | ||
if (commentsFile && extractedComments.length > 0) { | ||
// Add a banner to the original file | ||
if (this.options.extractComments.banner !== false) { | ||
let banner = this.options.extractComments.banner || `For license information please see ${_path2.default.posix.basename(commentsFile)}`; | ||
return new _sourceMap.SourceMapConsumer(inputSourceMap); | ||
} | ||
}, { | ||
key: 'buildError', | ||
value: function buildError(err, file, sourceMap, requestShortener) { | ||
// Handling error which should have line, col, filename and message | ||
if (err.line) { | ||
var original = sourceMap && sourceMap.originalPositionFor({ | ||
line: err.line, | ||
column: err.col | ||
}); | ||
if (typeof banner === 'function') { | ||
banner = banner(commentsFile); | ||
} | ||
if (original && original.source && requestShortener) { | ||
return new Error(`${file} from UglifyJs\n${err.message} [${requestShortener.shorten(original.source)}:${original.line},${original.column}][${file}:${err.line},${err.col}]`); | ||
} | ||
if (banner) { | ||
outputSource = new _webpackSources.ConcatSource(`/*! ${banner} */\n`, outputSource); | ||
} | ||
} | ||
return new Error(`${file} from UglifyJs\n${err.message} [${file}:${err.line},${err.col}]`); | ||
} else if (err.stack) { | ||
return new Error(`${file} from UglifyJs\n${err.stack}`); | ||
} | ||
const commentsSource = new _webpackSources.RawSource(`${extractedComments.join('\n\n')}\n`); | ||
return new Error(`${file} from UglifyJs\n${err.message}`); | ||
} | ||
}, { | ||
key: 'buildWarning', | ||
value: function buildWarning(warning, file, sourceMap, warningsFilter, requestShortener) { | ||
if (!file || !sourceMap) { | ||
return `UglifyJs Plugin: ${warning}`; | ||
} | ||
if (commentsFile in compilation.assets) { | ||
// commentsFile already exists, append new comments... | ||
if (compilation.assets[commentsFile] instanceof _webpackSources.ConcatSource) { | ||
compilation.assets[commentsFile].add('\n'); | ||
compilation.assets[commentsFile].add(commentsSource); | ||
} else { | ||
compilation.assets[commentsFile] = new _webpackSources.ConcatSource(compilation.assets[commentsFile], '\n', commentsSource); | ||
} | ||
} else { | ||
compilation.assets[commentsFile] = commentsSource; | ||
} | ||
} | ||
var warningMessage = warning; | ||
// Updating assets | ||
processedAssets.add(compilation.assets[file] = outputSource); | ||
var match = warningRegex.exec(warning); | ||
// Handling warnings | ||
if (warnings && warnings.length > 0) { | ||
warnings.forEach(warning => { | ||
const builtWarning = UglifyJsPlugin.buildWarning(warning, file, sourceMap, new _RequestShortener2.default(compiler.context), this.options.warningsFilter); | ||
if (match) { | ||
var line = +match[1]; | ||
var column = +match[2]; | ||
var original = sourceMap.originalPositionFor({ | ||
line, | ||
column | ||
if (builtWarning) { | ||
compilation.warnings.push(builtWarning); | ||
} | ||
}); | ||
} | ||
}); | ||
if (warningsFilter && !warningsFilter(original.source)) { | ||
return null; | ||
} | ||
taskRunner.exit(); | ||
if (original && original.source && original.source !== file && requestShortener) { | ||
warningMessage = `${warningMessage.replace(warningRegex, '')}[${requestShortener.shorten(original.source)}:${original.line},${original.column}]`; | ||
} | ||
callback(); | ||
}); | ||
}; | ||
const plugin = { name: this.constructor.name }; | ||
compiler.hooks.compilation.tap(plugin, compilation => { | ||
if (this.options.sourceMap) { | ||
compilation.hooks.buildModule.tap(plugin, buildModuleFn); | ||
} | ||
return `UglifyJs Plugin: ${warningMessage} in ${file}`; | ||
} | ||
}]); | ||
compilation.hooks.optimizeChunkAssets.tapAsync(plugin, optimizeFn.bind(this, compilation)); | ||
}); | ||
} | ||
} | ||
return UglifyJsPlugin; | ||
}(); | ||
exports.default = UglifyJsPlugin; |
{ | ||
"type": "object", | ||
"additionalProperties": false, | ||
"definitions": { | ||
"file-conditions": { | ||
"anyOf": [ | ||
{ | ||
"instanceof": "RegExp" | ||
}, | ||
{ | ||
"type": "string" | ||
} | ||
] | ||
} | ||
}, | ||
"properties": { | ||
"test": {}, | ||
"include": {}, | ||
"exclude": {}, | ||
"test": { | ||
"anyOf": [ | ||
{ | ||
"$ref": "#/definitions/file-conditions" | ||
}, | ||
{ | ||
"items": { | ||
"anyOf": [ | ||
{ | ||
"$ref": "#/definitions/file-conditions" | ||
} | ||
] | ||
}, | ||
"type": "array" | ||
} | ||
] | ||
}, | ||
"include": { | ||
"anyOf": [ | ||
{ | ||
"$ref": "#/definitions/file-conditions" | ||
}, | ||
{ | ||
"items": { | ||
"anyOf": [ | ||
{ | ||
"$ref": "#/definitions/file-conditions" | ||
} | ||
] | ||
}, | ||
"type": "array" | ||
} | ||
] | ||
}, | ||
"exclude": { | ||
"anyOf": [ | ||
{ | ||
"$ref": "#/definitions/file-conditions" | ||
}, | ||
{ | ||
"items": { | ||
"anyOf": [ | ||
{ | ||
"$ref": "#/definitions/file-conditions" | ||
} | ||
] | ||
}, | ||
"type": "array" | ||
} | ||
] | ||
}, | ||
"cache": { | ||
"oneOf": [ | ||
{ "type": "boolean" }, | ||
{ "type": "string" } | ||
"anyOf": [ | ||
{ | ||
"type": "boolean" | ||
}, | ||
{ | ||
"type": "string" | ||
} | ||
] | ||
@@ -17,5 +81,9 @@ }, | ||
"parallel": { | ||
"oneOf": [ | ||
{ "type": "boolean" }, | ||
{ "type": "integer" } | ||
"anyOf": [ | ||
{ | ||
"type": "boolean" | ||
}, | ||
{ | ||
"type": "integer" | ||
} | ||
] | ||
@@ -31,46 +99,70 @@ }, | ||
"additionalProperties": true, | ||
"type": "object", | ||
"properties": { | ||
"ecma": { | ||
"type": "integer", | ||
"minimum": 5, | ||
"maximum": 8 | ||
"type": "object" | ||
}, | ||
"extractComments": { | ||
"anyOf": [ | ||
{ | ||
"type": "boolean" | ||
}, | ||
"warnings": { | ||
"type": ["boolean", "string"], | ||
"enum": [true, false, "verbose"] | ||
{ | ||
"type": "string" | ||
}, | ||
"ie8": { | ||
"type": "boolean" | ||
{ | ||
"instanceof": "RegExp" | ||
}, | ||
"parse": { | ||
"type": "object" | ||
{ | ||
"instanceof": "Function" | ||
}, | ||
"compress": { | ||
"type": ["boolean", "object"] | ||
}, | ||
"mangle": { | ||
"type": ["boolean", "object"], | ||
{ | ||
"additionalProperties": false, | ||
"properties": { | ||
"properties": { | ||
"type": ["boolean", "object"] | ||
"condition": { | ||
"anyOf": [ | ||
{ | ||
"type": "boolean" | ||
}, | ||
{ | ||
"type": "string" | ||
}, | ||
{ | ||
"instanceof": "RegExp" | ||
}, | ||
{ | ||
"instanceof": "Function" | ||
} | ||
] | ||
}, | ||
"filename": { | ||
"anyOf": [ | ||
{ | ||
"type": "string" | ||
}, | ||
{ | ||
"instanceof": "Function" | ||
} | ||
] | ||
}, | ||
"banner": { | ||
"anyOf": [ | ||
{ | ||
"type": "boolean" | ||
}, | ||
{ | ||
"type": "string" | ||
}, | ||
{ | ||
"instanceof": "Function" | ||
} | ||
] | ||
} | ||
} | ||
}, | ||
"output": { | ||
"type": ["object", "null"] | ||
}, | ||
"toplevel": { | ||
"type": "boolean" | ||
}, | ||
"nameCache": { | ||
"type": ["object", "null"] | ||
}, | ||
"type": "object" | ||
} | ||
} | ||
] | ||
}, | ||
"extractComments": {}, | ||
"warningsFilter": {} | ||
"warningsFilter": { | ||
"instanceof": "Function" | ||
} | ||
}, | ||
"additionalProperties": false | ||
"type": "object" | ||
} | ||
{ | ||
"name": "uglifyjs-webpack-plugin", | ||
"version": "1.3.0", | ||
"version": "2.0.0", | ||
"description": "UglifyJS plugin for webpack", | ||
"license": "MIT", | ||
"repository": "webpack-contrib/uglifyjs-webpack-plugin", | ||
"author": "webpack Contrib Team", | ||
"license": "MIT", | ||
"homepage": "https://github.com/webpack-contrib/uglifyjs-webpack-plugin", | ||
"bugs": "https://github.com/webpack-contrib/uglifyjs-webpack-plugin/issues", | ||
"bin": "", | ||
"main": "dist/cjs.js", | ||
"engines": { | ||
"node": ">= 4.8 < 5.0.0 || >= 5.10" | ||
"node": ">= 6.9.0 <7.0.0 || >= 8.9.0" | ||
}, | ||
"main": "dist/cjs.js", | ||
"files": [ | ||
"dist" | ||
], | ||
"scripts": { | ||
"start": "npm run build -- -w", | ||
"build": "cross-env NODE_ENV=production babel src -d dist --ignore 'src/**/*.test.js' --copy-files", | ||
"test": "jest", | ||
"test:watch": "jest --watch", | ||
"test:coverage": "jest --collectCoverageFrom='src/**/*.js' --coverage", | ||
"prebuild": "npm run clean", | ||
"clean": "del-cli dist", | ||
"commitlint": "commitlint", | ||
"commitmsg": "commitlint -e $GIT_PARAMS", | ||
"lint": "eslint --cache src test", | ||
"ci:lint:commits": "commitlint --from=${CIRCLE_BRANCH} --to=${CIRCLE_SHA1}", | ||
"lint-staged": "lint-staged", | ||
"prebuild": "npm run clean", | ||
"prepare": "npm run build", | ||
"release": "standard-version", | ||
"security": "nsp check", | ||
"release:ci": "conventional-github-releaser -p angular", | ||
"release:validate": "commitlint --from=$(git describe --tags --abbrev=0) --to=$(git rev-parse HEAD)", | ||
"security": "npm audit", | ||
"test": "jest", | ||
"test:watch": "jest --watch", | ||
"test:coverage": "jest --collectCoverageFrom='src/**/*.js' --coverage", | ||
"ci:lint": "npm run lint && npm run security", | ||
"ci:test": "npm run test -- --runInBand", | ||
"ci:coverage": "npm run test:coverage -- --runInBand", | ||
"appveyor:test": "npm run test", | ||
"webpack-defaults": "webpack-defaults" | ||
"defaults": "webpack-defaults" | ||
}, | ||
"files": [ | ||
"dist" | ||
], | ||
"peerDependencies": { | ||
"webpack": "^4.3.0" | ||
}, | ||
"dependencies": { | ||
"cacache": "^10.0.4", | ||
"find-cache-dir": "^1.0.0", | ||
"cacache": "^11.2.0", | ||
"find-cache-dir": "^2.0.0", | ||
"schema-utils": "^1.0.0", | ||
"serialize-javascript": "^1.4.0", | ||
"schema-utils": "^0.4.5", | ||
"source-map": "^0.6.1", | ||
"uglify-es": "^3.3.4", | ||
"uglify-js": "^3.4.9", | ||
"webpack-sources": "^1.1.0", | ||
@@ -44,26 +55,29 @@ "worker-farm": "^1.5.2" | ||
"devDependencies": { | ||
"@commitlint/cli": "^7.1.2", | ||
"@commitlint/config-conventional": "^7.1.2", | ||
"@webpack-contrib/eslint-config-webpack": "^2.0.4", | ||
"babel-cli": "^6.26.0", | ||
"babel-jest": "^22.4.3", | ||
"babel-jest": "^23.4.2", | ||
"babel-plugin-transform-object-rest-spread": "^6.26.0", | ||
"babel-polyfill": "^6.26.0", | ||
"babel-preset-env": "^1.6.1", | ||
"conventional-github-releaser": "^3.1.2", | ||
"cross-env": "^5.1.3", | ||
"del": "^3.0.0", | ||
"del-cli": "^1.1.0", | ||
"eslint": "^4.14.0", | ||
"eslint": "^5.5.0", | ||
"eslint-config-webpack": "^1.2.5", | ||
"eslint-plugin-import": "^2.8.0", | ||
"jest": "^22.4.3", | ||
"lint-staged": "^6.0.0", | ||
"eslint-plugin-prettier": "^2.6.2", | ||
"husky": "^0.14.3", | ||
"jest": "^23.5.0", | ||
"lint-staged": "^7.2.2", | ||
"memory-fs": "^0.4.1", | ||
"nsp": "^3.1.0", | ||
"pre-commit": "^1.2.2", | ||
"prettier": "^1.14.2", | ||
"standard-version": "^4.3.0", | ||
"terser": "^3.7.6", | ||
"uglify-js": "^3.4.3", | ||
"webpack": "^3.10.0", | ||
"webpack-defaults": "^1.6.0" | ||
"webpack": "^4.17.2", | ||
"webpack-defaults": "^2.3.0" | ||
}, | ||
"peerDependencies": { | ||
"webpack": "^2.0.0 || ^3.0.0 || ^4.0.0" | ||
}, | ||
"keywords": [ | ||
@@ -76,5 +90,5 @@ "uglify", | ||
], | ||
"bugs": "https://github.com/webpack-contrib/uglifyjs-webpack-plugin/issues", | ||
"homepage": "https://github.com/webpack-contrib/uglifyjs-webpack-plugin", | ||
"repository": "https://github.com/webpack-contrib/uglifyjs-webpack-plugin.git", | ||
"jest": { | ||
"testEnvironment": "node" | ||
}, | ||
"pre-commit": "lint-staged", | ||
@@ -86,6 +100,3 @@ "lint-staged": { | ||
] | ||
}, | ||
"jest": { | ||
"testEnvironment": "node" | ||
} | ||
} |
702
README.md
@@ -0,31 +1,37 @@ | ||
<div align="center"> | ||
<a href="https://github.com/webpack/webpack"> | ||
<img width="200" height="200" src="https://webpack.js.org/assets/icon-square-big.svg"> | ||
</a> | ||
</div> | ||
[![npm][npm]][npm-url] | ||
[![node][node]][node-url] | ||
[![deps][deps]][deps-url] | ||
[![test][test]][test-url] | ||
[![coverage][cover]][cover-url] | ||
[![tests][tests]][tests-url] | ||
[![cover][cover]][cover-url] | ||
[![chat][chat]][chat-url] | ||
[![size][size]][size-url] | ||
# UglifyJS Webpack Plugin | ||
<div align="center"> | ||
<a href="https://github.com/webpack/webpack"> | ||
<img width="200" height="200" | ||
src="https://cdn.rawgit.com/webpack/media/e7485eb2/logo/icon.svg"> | ||
</a> | ||
<h1>UglifyJS Webpack Plugin</h1> | ||
<p>This plugin uses <a href="https://github.com/mishoo/UglifyJS2/tree/harmony">UglifyJS v3 </a><a href="https://npmjs.com/package/uglify-es">(`uglify-es`)</a> to minify your JavaScript</p> | ||
</div> | ||
This plugin uses [uglify-js](https://github.com/mishoo/UglifyJS2) to minify your JavaScript. | ||
> ℹ️ `webpack < v4.0.0` currently contains [`v0.4.6`](https://github.com/webpack-contrib/uglifyjs-webpack-plugin/tree/version-0.4) of this plugin under `webpack.optimize.UglifyJsPlugin` as an alias. For usage of the latest version (`v1.0.0`), please follow the instructions below. Aliasing `v1.0.0` as `webpack.optimize.UglifyJsPlugin` is scheduled for `webpack v4.0.0` | ||
## Requirements | ||
<h2 align="center">Install</h2> | ||
This module requires a minimum of Node v6.9.0 and Webpack v4.0.0. | ||
```bash | ||
npm i -D uglifyjs-webpack-plugin | ||
## Getting Started | ||
To begin, you'll need to install `uglifyjs-webpack-plugin`: | ||
```console | ||
$ npm install uglifyjs-webpack-plugin --save-dev | ||
``` | ||
<h2 align="center">Usage</h2> | ||
Then add the plugin to your `webpack` config. For example: | ||
**webpack.config.js** | ||
```js | ||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin') | ||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); | ||
@@ -35,34 +41,23 @@ module.exports = { | ||
optimization: { | ||
minimizer: [ | ||
new UglifyJsPlugin() | ||
] | ||
minimizer: [new UglifyJsPlugin()] | ||
} | ||
} | ||
}; | ||
``` | ||
<h2 align="center">Options</h2> | ||
And run `webpack` via your preferred method. | ||
|Name|Type|Default|Description| | ||
|:--:|:--:|:-----:|:----------| | ||
|**`test`**|`{RegExp\|Array<RegExp>}`| <code>/\\.js$/i</code>|Test to match files against| | ||
|**`include`**|`{RegExp\|Array<RegExp>}`|`undefined`|Files to `include`| | ||
|**`exclude`**|`{RegExp\|Array<RegExp>}`|`undefined`|Files to `exclude`| | ||
|**`cache`**|`{Boolean\|String}`|`false`|Enable file caching| | ||
|**`cacheKeys`**|`{Function(defaultCacheKeys, file) -> {Object}}`|`defaultCacheKeys => defaultCacheKeys`|Allows you to override default cache keys| | ||
|**`parallel`**|`{Boolean\|Number}`|`false`|Use multi-process parallel running to improve the build speed| | ||
|**`sourceMap`**|`{Boolean}`|`false`|Use source maps to map error message locations to modules (This slows down the compilation) ⚠️ **`cheap-source-map` options don't work with this plugin**| | ||
|**`minify`**|`{Function}`|`undefined`|Allows you to override default minify function| | ||
|**`uglifyOptions`**|`{Object}`|[`{...defaults}`](https://github.com/webpack-contrib/uglifyjs-webpack-plugin/tree/master#uglifyoptions)|`uglify` [Options](https://github.com/mishoo/UglifyJS2/tree/harmony#minify-options)| | ||
|**`extractComments`**|`{Boolean\|RegExp\|Function<(node, comment) -> {Boolean\|Object}>}`|`false`|Whether comments shall be extracted to a separate file, (see [details](https://github.com/webpack/webpack/commit/71933e979e51c533b432658d5e37917f9e71595a) (`webpack >= 2.3.0`)| | ||
|**`warningsFilter`**|`{Function(source) -> {Boolean}}`|`() => true`|Allow to filter uglify warnings| | ||
## Options | ||
### `test` | ||
**webpack.config.js** | ||
Type: `String|RegExp|Array<String|RegExp>` | ||
Default: `/\.js(\?.*)?$/i` | ||
Test to match files against. | ||
```js | ||
[ | ||
new UglifyJsPlugin({ | ||
test: /\.js($|\?)/i | ||
}) | ||
] | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
test: /\.js(\?.*)?$/i | ||
}) | ||
``` | ||
@@ -72,9 +67,12 @@ | ||
**webpack.config.js** | ||
Type: `String|RegExp|Array<String|RegExp>` | ||
Default: `undefined` | ||
Files to include. | ||
```js | ||
[ | ||
new UglifyJsPlugin({ | ||
include: /\/includes/ | ||
}) | ||
] | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
include: /\/includes/ | ||
}) | ||
``` | ||
@@ -84,9 +82,12 @@ | ||
**webpack.config.js** | ||
Type: `String|RegExp|Array<String|RegExp>` | ||
Default: `undefined` | ||
Files to exclude. | ||
```js | ||
[ | ||
new UglifyJsPlugin({ | ||
exclude: /\/excludes/ | ||
}) | ||
] | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
exclude: /\/excludes/ | ||
}) | ||
``` | ||
@@ -96,343 +97,452 @@ | ||
If you use your own `minify` function please read the `minify` section for cache invalidation correctly. | ||
Type: `Boolean|String` | ||
Default: `false` | ||
#### `{Boolean}` | ||
Enable file caching. | ||
Default path to cache directory: `node_modules/.cache/uglifyjs-webpack-plugin`. | ||
**webpack.config.js** | ||
```js | ||
[ | ||
new UglifyJsPlugin({ | ||
cache: true | ||
}) | ||
] | ||
``` | ||
> ℹ️ If you use your own `minify` function please read the `minify` section for cache invalidation correctly. | ||
Enable file caching. | ||
Default path to cache directory: `node_modules/.cache/uglifyjs-webpack-plugin`. | ||
#### `Boolean` | ||
#### `{String}` | ||
Enable/disable file caching. | ||
**webpack.config.js** | ||
```js | ||
[ | ||
new UglifyJsPlugin({ | ||
cache: 'path/to/cache' | ||
}) | ||
] | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
cache: true | ||
}) | ||
``` | ||
Path to cache directory. | ||
#### `String` | ||
### `cacheKeys` | ||
Enable file caching and set path to cache directory. | ||
**webpack.config.js** | ||
```js | ||
[ | ||
new UglifyJsPlugin({ | ||
cache: true, | ||
cacheKeys: (defaultCacheKeys, file) => { | ||
defaultCacheKeys.myCacheKey = 'myCacheKeyValue'; | ||
return defaultCacheKeys; | ||
}, | ||
}) | ||
] | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
cache: 'path/to/cache' | ||
}) | ||
``` | ||
### `cacheKeys` | ||
Type: `Function<(defaultCacheKeys, file) -> Object>` | ||
Default: `defaultCacheKeys => defaultCacheKeys` | ||
Allows you to override default cache keys. | ||
Default keys: | ||
Default cache keys: | ||
```js | ||
{ | ||
'uglify-es': versions.uglify, // uglify version | ||
'uglifyjs-webpack-plugin': versions.plugin, // plugin version | ||
({ | ||
'uglify-js': require('uglify-js/package.json').version, // uglify version | ||
'uglifyjs-webpack-plugin': require('../package.json').version, // plugin version | ||
'uglifyjs-webpack-plugin-options': this.options, // plugin options | ||
path: compiler.outputPath ? `${compiler.outputPath}/${file}` : file, // asset path | ||
hash: crypto.createHash('md4').update(input).digest('hex'), // source file hash | ||
} | ||
}); | ||
``` | ||
```js | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
cache: true, | ||
cacheKeys: (defaultCacheKeys, file) => { | ||
defaultCacheKeys.myCacheKey = 'myCacheKeyValue'; | ||
return defaultCacheKeys; | ||
}, | ||
}) | ||
``` | ||
### `parallel` | ||
#### `{Boolean}` | ||
Type: `Boolean|Number` | ||
Default: `false` | ||
**webpack.config.js** | ||
Use multi-process parallel running to improve the build speed. | ||
Default number of concurrent runs: `os.cpus().length - 1`. | ||
> ℹ️ Parallelization can speedup your build significantly and is therefore **highly recommended**. | ||
#### `Boolean` | ||
Enable/disable multi-process parallel running. | ||
```js | ||
[ | ||
new UglifyJsPlugin({ | ||
parallel: true | ||
}) | ||
] | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
parallel: true | ||
}) | ||
``` | ||
Enable parallelization. | ||
Default number of concurrent runs: `os.cpus().length - 1`. | ||
#### `Number` | ||
#### `{Number}` | ||
Enable multi-process parallel running and set number of concurrent runs. | ||
**webpack.config.js** | ||
```js | ||
[ | ||
new UglifyJsPlugin({ | ||
parallel: 4 | ||
}) | ||
] | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
parallel: 4 | ||
}) | ||
``` | ||
Number of concurrent runs. | ||
### `sourceMap` | ||
> ℹ️ Parallelization can speedup your build significantly and is therefore **highly recommended** | ||
Type: `Boolean` | ||
Default: `false` | ||
### `sourceMap` | ||
Use source maps to map error message locations to modules (this slows down the compilation). | ||
If you use your own `minify` function please read the `minify` section for handling source maps correctly. | ||
**webpack.config.js** | ||
> ⚠️ **`cheap-source-map` options don't work with this plugin**. | ||
```js | ||
[ | ||
new UglifyJsPlugin({ | ||
sourceMap: true | ||
}) | ||
] | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
sourceMap: true | ||
}) | ||
``` | ||
> ⚠️ **`cheap-source-map` options don't work with this plugin** | ||
### `minify` | ||
> ⚠️ **Always use `require` inside `minify` function when `parallel` option enabled** | ||
Type: `Function` | ||
Default: `undefined` | ||
**webpack.config.js** | ||
Allows you to override default minify function. | ||
By default plugin uses [uglify-js](https://github.com/mishoo/UglifyJS2) package. | ||
Useful for using and testing unpublished versions or forks. | ||
> ⚠️ **Always use `require` inside `minify` function when `parallel` option enabled**. | ||
```js | ||
[ | ||
new UglifyJsPlugin({ | ||
minify(file, sourceMap) { | ||
const extractedComments = []; | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
minify(file, sourceMap) { | ||
const extractedComments = []; | ||
// Custom logic for extract comments | ||
const { error, map, code, warnings } = require('uglify-module') // Or require('./path/to/uglify-module') | ||
.minify( | ||
file, | ||
{ /* Your options for minification */ }, | ||
); | ||
// Custom logic for extract comments | ||
return { error, map, code, warnings, extractedComments }; | ||
} | ||
}) | ||
] | ||
const { error, map, code, warnings } = require('uglify-module') // Or require('./path/to/uglify-module') | ||
.minify(file, { | ||
/* Your options for minification */ | ||
}); | ||
return { error, map, code, warnings, extractedComments }; | ||
} | ||
}) | ||
``` | ||
By default plugin uses `uglify-es` package. | ||
### `uglifyOptions` | ||
Examples: | ||
Type: `Object` | ||
Default: [default](https://github.com/mishoo/UglifyJS2#minify-options) | ||
#### `uglify-js` | ||
UglifyJS minify options. | ||
```bash | ||
npm i -D uglify-js | ||
```js | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
uglifyOptions: { | ||
warnings: false, | ||
parse: {}, | ||
compress: {}, | ||
mangle: true, // Note `mangle.properties` is `false` by default. | ||
output: null, | ||
toplevel: false, | ||
nameCache: null, | ||
ie8: false, | ||
keep_fnames: false, | ||
} | ||
}) | ||
``` | ||
**webpack.config.js** | ||
### `extractComments` | ||
Type: `Boolean|String|RegExp|Function<(node, comment) -> Boolean|Object>` | ||
Default: `false` | ||
Whether comments shall be extracted to a separate file, (see [details](https://github.com/webpack/webpack/commit/71933e979e51c533b432658d5e37917f9e71595a)). | ||
By default extract only comments using `/^\**!|@preserve|@license|@cc_on/i` regexp condition and remove remaining comments. | ||
If the original file is named `foo.js`, then the comments will be stored to `foo.js.LICENSE`. | ||
The `uglifyOptions.output.comments` option specifies whether the comment will be preserved, i.e. it is possible to preserve some comments (e.g. annotations) while extracting others or even preserving comments that have been extracted. | ||
#### `Boolean` | ||
Enable/disable extracting comments. | ||
```js | ||
[ | ||
new UglifyJsPlugin({ | ||
// Uncomment lines below for cache invalidation correctly | ||
// cache: true, | ||
// cacheKeys(defaultCacheKeys) { | ||
// return Object.assign( | ||
// {}, | ||
// defaultCacheKeys, | ||
// { 'uglify-js': require('uglify-js/package.json').version }, | ||
// ); | ||
// }, | ||
minify(file, sourceMap) { | ||
// https://github.com/mishoo/UglifyJS2#minify-options | ||
const uglifyJsOptions = { /* your `uglify-js` package options */ }; | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
extractComments: true | ||
}) | ||
``` | ||
if (sourceMap) { | ||
uglifyJsOptions.sourceMap = { | ||
content: sourceMap, | ||
}; | ||
} | ||
#### `String` | ||
return require('uglify-js').minify(file, uglifyJsOptions); | ||
} | ||
}) | ||
] | ||
Extract `all` or `some` (use `/^\**!|@preserve|@license|@cc_on/i` RegExp) comments. | ||
```js | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
extractComments: 'all' | ||
}) | ||
``` | ||
#### `terser` | ||
#### `RegExp` | ||
```bash | ||
npm i -D terser | ||
All comments that match the given expression will be extracted to the separate file. | ||
```js | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
extractComments: /@extract/i | ||
}) | ||
``` | ||
**webpack.config.js** | ||
#### `Function<(node, comment) -> Boolean>` | ||
All comments that match the given expression will be extracted to the separate file. | ||
```js | ||
[ | ||
new UglifyJsPlugin({ | ||
// Uncomment lines below for cache invalidation correctly | ||
// cache: true, | ||
// cacheKeys(defaultCacheKeys) { | ||
// return Object.assign( | ||
// {}, | ||
// defaultCacheKeys, | ||
// { terser: require('terser/package.json').version }, | ||
// ); | ||
// }, | ||
minify(file, sourceMap) { | ||
// https://github.com/fabiosantoscode/terser#minify-options | ||
const terserOptions = { /* your `terser` package options */ }; | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
extractComments: function (astNode, comment) { | ||
if (/@extract/i.test(comment.value)) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
}) | ||
``` | ||
if (sourceMap) { | ||
terserOption.sourceMap = { | ||
content: sourceMap, | ||
}; | ||
} | ||
#### `Object` | ||
return require('terser').minify(file, terserOptions); | ||
Allow to customize condition for extract comments, specify extracted file name and banner. | ||
```js | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
extractComments: { | ||
condition: /^\**!|@preserve|@license|@cc_on/i, | ||
filename(file) { | ||
return `${file}.LICENSE`; | ||
}, | ||
banner(licenseFile) { | ||
return `License information can be found in ${licenseFile}`; | ||
} | ||
}) | ||
] | ||
} | ||
}) | ||
``` | ||
### [`uglifyOptions`](https://github.com/mishoo/UglifyJS2/tree/harmony#minify-options) | ||
##### `condition` | ||
|Name|Type|Default|Description| | ||
|:--:|:--:|:-----:|:----------| | ||
|**`ecma`**|`{Number}`|`undefined`|Supported ECMAScript Version (`5`, `6`, `7` or `8`). Affects `parse`, `compress` && `output` options| | ||
|**`warnings`**|`{Boolean}`|`false`|Display Warnings| | ||
|**[`parse`](https://github.com/mishoo/UglifyJS2/tree/harmony#parse-options)**|`{Object}`|`{}`|Additional Parse Options| | ||
|**[`compress`](https://github.com/mishoo/UglifyJS2/tree/harmony#compress-options)**|`{Boolean\|Object}`|`true`|Additional Compress Options| | ||
|**[`mangle`](https://github.com/mishoo/UglifyJS2/tree/harmony#mangle-options)**|`{Boolean\|Object}`|`{inline: false}`|Enable Name Mangling (See [Mangle Properties](https://github.com/mishoo/UglifyJS2/tree/harmony#mangle-properties-options) for advanced setups, use with ⚠️)| | ||
|**[`output`](https://github.com/mishoo/UglifyJS2/tree/harmony#output-options)**|`{Object}`|`{comments: extractComments ? false : /^\**!\|@preserve\|@license\|@cc_on/,}`|Additional Output Options (The defaults are optimized for best compression)| | ||
|**`toplevel`**|`{Boolean}`|`false`|Enable top level variable and function name mangling and to drop unused variables and functions| | ||
|**`nameCache`**|`{Object}`|`null`|Enable cache of mangled variable and property names across multiple invocations| | ||
|**`ie8`**|`{Boolean}`|`false`|Enable IE8 Support| | ||
|**`keep_classnames`**|`{Boolean}`|`undefined`|Enable prevent discarding or mangling of class names| | ||
|**`keep_fnames`**|`{Boolean}`|`false`| Enable prevent discarding or mangling of function names. Useful for code relying on `Function.prototype.name`. If the top level minify option `keep_classnames` is `undefined` it will be overriden with the value of the top level minify option `keep_fnames`| | ||
|**`safari10`**|`{Boolean}`|`false`|Enable work around Safari 10/11 bugs in loop scoping and `await`| | ||
Type: `Boolean|String|RegExp|Function<(node, comment) -> Boolean|Object>` | ||
**webpack.config.js** | ||
Condition what comments you need extract. | ||
```js | ||
[ | ||
new UglifyJsPlugin({ | ||
uglifyOptions: { | ||
ecma: 8, | ||
warnings: false, | ||
parse: {...options}, | ||
compress: {...options}, | ||
mangle: { | ||
...options, | ||
properties: { | ||
// mangle property options | ||
} | ||
}, | ||
output: { | ||
comments: false, | ||
beautify: false, | ||
...options | ||
}, | ||
toplevel: false, | ||
nameCache: null, | ||
ie8: false, | ||
keep_classnames: undefined, | ||
keep_fnames: false, | ||
safari10: false, | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
extractComments: { | ||
condition: 'some', | ||
filename(file) { | ||
return `${file}.LICENSE`; | ||
}, | ||
banner(licenseFile) { | ||
return `License information can be found in ${licenseFile}`; | ||
} | ||
}) | ||
] | ||
} | ||
}) | ||
``` | ||
### `extractComments` | ||
##### `filename` | ||
#### `{Boolean}` | ||
Type: `Regex|Function<(string) -> String>` | ||
Default: `${file}.LICENSE` | ||
All comments that normally would be preserved by the `comments` option will be moved to a separate file. If the original file is named `foo.js`, then the comments will be stored to `foo.js.LICENSE`. | ||
The file where the extracted comments will be stored. | ||
Default is to append the suffix `.LICENSE` to the original filename. | ||
#### `{RegExp|String}` or `{Function<(node, comment) -> {Boolean}>}` | ||
```js | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
extractComments: { | ||
condition: /^\**!|@preserve|@license|@cc_on/i, | ||
filename: 'extracted-comments.js', | ||
banner(licenseFile) { | ||
return `License information can be found in ${licenseFile}`; | ||
} | ||
} | ||
}) | ||
``` | ||
All comments that match the given expression (resp. are evaluated to `true` by the function) will be extracted to the separate file. The `comments` option specifies whether the comment will be preserved, i.e. it is possible to preserve some comments (e.g. annotations) while extracting others or even preserving comments that have been extracted. | ||
##### `banner` | ||
#### `{Object}` | ||
Type: `Boolean|String|Function<(string) -> String>` | ||
Default: `/*! For license information please see ${commentsFile} */` | ||
|Name|Type|Default|Description| | ||
|:--:|:--:|:-----:|:----------| | ||
|**`condition`**|`{Regex\|Function}`|``|Regular Expression or function (see previous point)| | ||
|**`filename`**|`{String\|Function}`|`${file}.LICENSE`|The file where the extracted comments will be stored. Can be either a `{String}` or a `{Function<(string) -> {String}>}`, which will be given the original filename. Default is to append the suffix `.LICENSE` to the original filename| | ||
|**`banner`**|`{Boolean\|String\|Function}`|`/*! For license information please see ${filename}.js.LICENSE */`|The banner text that points to the extracted file and will be added on top of the original file. Can be `false` (no banner), a `{String}`, or a `{Function<(string) -> {String}` that will be called with the filename where extracted comments have been stored. Will be wrapped into comment| | ||
The banner text that points to the extracted file and will be added on top of the original file. | ||
Can be `false` (no banner), a `String`, or a `Function<(string) -> String>` that will be called with the filename where extracted comments have been stored. | ||
Will be wrapped into comment. | ||
```js | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
extractComments: { | ||
condition: true, | ||
filename(file) { | ||
return `${file}.LICENSE`; | ||
}, | ||
banner(commentsFile) { | ||
return `My custom banner about license information ${commentsFile}`; | ||
} | ||
} | ||
}) | ||
``` | ||
### `warningsFilter` | ||
**webpack.config.js** | ||
Type: `Function<(warning, source) -> Boolean>` | ||
Default: `() => true` | ||
Allow to filter [uglify-js](https://github.com/mishoo/UglifyJS2) warnings. | ||
Return `true` to keep the warning, `false` otherwise. | ||
```js | ||
[ | ||
new UglifyJsPlugin({ | ||
warningsFilter: (src) => true | ||
}) | ||
] | ||
// in your webpack.config.js | ||
new UglifyJsPlugin({ | ||
warningsFilter: (warning, source) => { | ||
if (/Dropping unreachable code/i.test(warning)) { | ||
return true; | ||
} | ||
if (/filename\.js/i.test(source)) { | ||
return true; | ||
} | ||
return false; | ||
}, | ||
}) | ||
``` | ||
<h2 align="center">Maintainers</h2> | ||
## Examples | ||
<table> | ||
<tbody> | ||
<tr> | ||
<td align="center"> | ||
<a href="https://github.com/hulkish"> | ||
<img width="150" height="150" src="https://github.com/hulkish.png?size=150"> | ||
</br> | ||
Steven Hargrove | ||
</a> | ||
</td> | ||
<td align="center"> | ||
<a href="https://github.com/bebraw"> | ||
<img width="150" height="150" src="https://github.com/bebraw.png?v=3&s=150"> | ||
</br> | ||
Juho Vepsäläinen | ||
</a> | ||
</td> | ||
<td align="center"> | ||
<a href="https://github.com/d3viant0ne"> | ||
<img width="150" height="150" src="https://github.com/d3viant0ne.png?v=3&s=150"> | ||
</br> | ||
Joshua Wiens | ||
</a> | ||
</td> | ||
<td align="center"> | ||
<a href="https://github.com/michael-ciniawsky"> | ||
<img width="150" height="150" src="https://github.com/michael-ciniawsky.png?v=3&s=150"> | ||
</br> | ||
Michael Ciniawsky | ||
</a> | ||
</td> | ||
<td align="center"> | ||
<a href="https://github.com/evilebottnawi"> | ||
<img width="150" height="150" src="https://github.com/evilebottnawi.png?v=3&s=150"> | ||
</br> | ||
Alexander Krasnoyarov | ||
</a> | ||
</td> | ||
</tr> | ||
<tbody> | ||
</table> | ||
### Cache And Parallel | ||
Enable cache and multi-process parallel running. | ||
```js | ||
// in your webpack.config.js | ||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); | ||
module.exports = { | ||
//... | ||
optimization: { | ||
minimizer: [ | ||
new UglifyJsPlugin({ | ||
cache: true, | ||
parallel: true | ||
}) | ||
] | ||
} | ||
}; | ||
``` | ||
### Preserve Comments | ||
Extract all legal comments (i.e. `/^\**!|@preserve|@license|@cc_on/i`) and preserve `/@license/i` comments. | ||
```js | ||
// in your webpack.config.js | ||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); | ||
module.exports = { | ||
//... | ||
optimization: { | ||
minimizer: [ | ||
new UglifyJsPlugin({ | ||
uglifyOptions: { | ||
output: { | ||
comments: /@license/i | ||
} | ||
}, | ||
extractComments: true | ||
}) | ||
] | ||
} | ||
}; | ||
``` | ||
### Custom Minify Function | ||
Override default minify function - use [terser](https://github.com/fabiosantoscode/terser) for minification. | ||
```js | ||
// in your webpack.config.js | ||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); | ||
module.exports = { | ||
//... | ||
optimization: { | ||
minimizer: [ | ||
new UglifyJsPlugin({ | ||
// Uncomment lines below for cache invalidation correctly | ||
// cache: true, | ||
// cacheKeys(defaultCacheKeys) { | ||
// delete defaultCacheKeys['uglify-js']; | ||
// | ||
// return Object.assign( | ||
// {}, | ||
// defaultCacheKeys, | ||
// { 'uglify-js': require('uglify-js/package.json').version }, | ||
// ); | ||
// }, | ||
minify(file, sourceMap) { | ||
// https://github.com/mishoo/UglifyJS2#minify-options | ||
const uglifyJsOptions = { | ||
/* your `uglify-js` package options */ | ||
}; | ||
if (sourceMap) { | ||
uglifyJsOptions.sourceMap = { | ||
content: sourceMap, | ||
}; | ||
} | ||
return require('terser').minify(file, uglifyJsOptions); | ||
}, | ||
}) | ||
] | ||
} | ||
}; | ||
``` | ||
## Contributing | ||
Please take a moment to read our contributing guidelines if you haven't yet done so. | ||
[CONTRIBUTING](./.github/CONTRIBUTING.md) | ||
## License | ||
[MIT](./LICENSE) | ||
[npm]: https://img.shields.io/npm/v/uglifyjs-webpack-plugin.svg | ||
[npm-url]: https://npmjs.com/package/uglifyjs-webpack-plugin | ||
[node]: https://img.shields.io/node/v/uglifyjs-webpack-plugin.svg | ||
[node-url]: https://nodejs.org | ||
[deps]: https://david-dm.org/webpack-contrib/uglifyjs-webpack-plugin.svg | ||
[deps-url]: https://david-dm.org/webpack-contrib/uglifyjs-webpack-plugin | ||
[test]: https://img.shields.io/circleci/project/github/webpack-contrib/uglifyjs-webpack-plugin.svg | ||
[test-url]: https://circleci.com/gh/webpack-contrib/uglifyjs-webpack-plugin | ||
[tests]: https://img.shields.io/circleci/project/github/webpack-contrib/uglifyjs-webpack-plugin.svg | ||
[tests-url]: https://circleci.com/gh/webpack-contrib/uglifyjs-webpack-plugin | ||
[cover]: https://codecov.io/gh/webpack-contrib/uglifyjs-webpack-plugin/branch/master/graph/badge.svg | ||
[cover-url]: https://codecov.io/gh/webpack-contrib/uglifyjs-webpack-plugin | ||
[chat]: https://img.shields.io/badge/gitter-webpack%2Fwebpack-brightgreen.svg | ||
[chat-url]: https://gitter.im/webpack/webpack | ||
[size]: https://packagephobia.now.sh/badge?p=uglifyjs-webpack-plugin | ||
[size-url]: https://packagephobia.now.sh/result?p=uglifyjs-webpack-plugin |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
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
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
646
545
56348
26
2
+ Addeduglify-js@^3.4.9
+ Addedcacache@11.3.3(transitive)
+ Addeduglify-js@3.19.3(transitive)
- Removeduglify-es@^3.3.4
- Removedcacache@10.0.4(transitive)
- Removedcommander@2.14.1(transitive)
- Removedfind-cache-dir@1.0.0(transitive)
- Removedfind-up@2.1.0(transitive)
- Removedlocate-path@2.0.0(transitive)
- Removedlru-cache@4.1.5(transitive)
- Removedmake-dir@1.3.0(transitive)
- Removedmississippi@2.0.0(transitive)
- Removedp-limit@1.3.0(transitive)
- Removedp-locate@2.0.0(transitive)
- Removedp-try@1.0.0(transitive)
- Removedpify@3.0.0(transitive)
- Removedpkg-dir@2.0.0(transitive)
- Removedpseudomap@1.0.2(transitive)
- Removedschema-utils@0.4.7(transitive)
- Removedssri@5.3.0(transitive)
- Removeduglify-es@3.3.10(transitive)
- Removedyallist@2.1.2(transitive)
Updatedcacache@^11.2.0
Updatedfind-cache-dir@^2.0.0
Updatedschema-utils@^1.0.0