From dc315e5f6d601d7b0f39d8ca6b85f791aef28f1b Mon Sep 17 00:00:00 2001 From: Sean Larkin Date: Wed, 7 Jun 2017 12:35:50 -0500 Subject: [PATCH] feat(uglify): move uglify to external plugin from webpack-contrib --- lib/optimize/UglifyJsPlugin.js | 229 +-------------------------------- package.json | 2 +- yarn.lock | 18 +++ 3 files changed, 20 insertions(+), 229 deletions(-) diff --git a/lib/optimize/UglifyJsPlugin.js b/lib/optimize/UglifyJsPlugin.js index 14652cf19..b1bd4d2a9 100644 --- a/lib/optimize/UglifyJsPlugin.js +++ b/lib/optimize/UglifyJsPlugin.js @@ -4,233 +4,6 @@ */ "use strict"; -const SourceMapConsumer = require("source-map").SourceMapConsumer; -const SourceMapSource = require("webpack-sources").SourceMapSource; -const RawSource = require("webpack-sources").RawSource; -const ConcatSource = require("webpack-sources").ConcatSource; -const RequestShortener = require("../RequestShortener"); -const ModuleFilenameHelpers = require("../ModuleFilenameHelpers"); -const uglify = require("uglify-js"); - -class UglifyJsPlugin { - constructor(options) { - if(typeof options !== "object" || Array.isArray(options)) options = {}; - if(typeof options.compressor !== "undefined") options.compress = options.compressor; - this.options = options; - } - - apply(compiler) { - const options = this.options; - options.test = options.test || /\.js($|\?)/i; - const warningsFilter = options.warningsFilter || (() => true); - - const requestShortener = new RequestShortener(compiler.context); - compiler.plugin("compilation", (compilation) => { - if(options.sourceMap) { - compilation.plugin("build-module", (module) => { - // to get detailed location info about errors - module.useSourceMap = true; - }); - } - compilation.plugin("optimize-chunk-assets", (chunks, callback) => { - const files = []; - chunks.forEach((chunk) => files.push.apply(files, chunk.files)); - files.push.apply(files, compilation.additionalChunkAssets); - const filterdFiles = files.filter(ModuleFilenameHelpers.matchObject.bind(undefined, options)); - filterdFiles.forEach((file) => { - const oldWarnFunction = uglify.AST_Node.warn_function; - const warnings = []; - let sourceMap; - try { - const asset = compilation.assets[file]; - if(asset.__UglifyJsPlugin) { - compilation.assets[file] = asset.__UglifyJsPlugin; - return; - } - let input; - let inputSourceMap; - if(options.sourceMap) { - if(asset.sourceAndMap) { - const sourceAndMap = asset.sourceAndMap(); - inputSourceMap = sourceAndMap.map; - input = sourceAndMap.source; - } else { - inputSourceMap = asset.map(); - input = asset.source(); - } - sourceMap = new SourceMapConsumer(inputSourceMap); - uglify.AST_Node.warn_function = (warning) => { // eslint-disable-line camelcase - const match = /\[.+:([0-9]+),([0-9]+)\]/.exec(warning); - const line = +match[1]; - const column = +match[2]; - const original = sourceMap.originalPositionFor({ - line: line, - column: column - }); - if(!original || !original.source || original.source === file) return; - if(!warningsFilter(original.source)) return; - warnings.push(warning.replace(/\[.+:([0-9]+),([0-9]+)\]/, "") + - "[" + requestShortener.shorten(original.source) + ":" + original.line + "," + original.column + "]"); - }; - } else { - input = asset.source(); - uglify.AST_Node.warn_function = (warning) => { // eslint-disable-line camelcase - warnings.push(warning); - }; - } - uglify.base54.reset(); - let ast = uglify.parse(input, { - filename: file - }); - if(options.compress !== false) { - ast.figure_out_scope(); - const compress = uglify.Compressor(options.compress || { - warnings: false - }); // eslint-disable-line new-cap - ast = compress.compress(ast); - } - if(options.mangle !== false) { - ast.figure_out_scope(options.mangle || {}); - ast.compute_char_frequency(options.mangle || {}); - ast.mangle_names(options.mangle || {}); - if(options.mangle && options.mangle.props) { - uglify.mangle_properties(ast, options.mangle.props); - } - } - const output = {}; - output.comments = Object.prototype.hasOwnProperty.call(options, "comments") ? options.comments : /^\**!|@preserve|@license/; - output.beautify = options.beautify; - for(let k in options.output) { - output[k] = options.output[k]; - } - const extractedComments = []; - if(options.extractComments) { - const condition = {}; - if(typeof options.extractComments === "string" || options.extractComments instanceof RegExp) { - // extractComments specifies the extract condition and output.comments specifies the preserve condition - condition.preserve = output.comments; - condition.extract = options.extractComments; - } else if(Object.prototype.hasOwnProperty.call(options.extractComments, "condition")) { - // Extract condition is given in extractComments.condition - condition.preserve = output.comments; - condition.extract = options.extractComments.condition; - } else { - // No extract condition is given. Extract comments that match output.comments instead of preserving them - condition.preserve = false; - condition.extract = output.comments; - } - - // Ensure that both conditions are functions - ["preserve", "extract"].forEach(key => { - switch(typeof condition[key]) { - case "boolean": - var b = condition[key]; - condition[key] = () => b; - break; - case "function": - break; - case "string": - if(condition[key] === "all") { - condition[key] = () => true; - break; - } - var regex = new RegExp(condition[key]); - condition[key] = (astNode, comment) => regex.test(comment.value); - break; - default: - regex = condition[key]; - condition[key] = (astNode, comment) => regex.test(comment.value); - } - }); - - // Redefine the comments function to extract and preserve - // comments according to the two conditions - output.comments = (astNode, comment) => { - if(condition.extract(astNode, comment)) { - extractedComments.push( - comment.type === "comment2" ? "/*" + comment.value + "*/" : "//" + comment.value - ); - } - return condition.preserve(astNode, comment); - }; - } - let map; - if(options.sourceMap) { - map = uglify.SourceMap({ // eslint-disable-line new-cap - file: file, - root: "" - }); - output.source_map = map; // eslint-disable-line camelcase - } - const stream = uglify.OutputStream(output); // eslint-disable-line new-cap - ast.print(stream); - if(map) map = map + ""; - const stringifiedStream = stream + ""; - let outputSource = (map ? - new SourceMapSource(stringifiedStream, file, JSON.parse(map), input, inputSourceMap) : - new RawSource(stringifiedStream)); - if(extractedComments.length > 0) { - let commentsFile = options.extractComments.filename || file + ".LICENSE"; - if(typeof commentsFile === "function") { - commentsFile = commentsFile(file); - } - - // Write extracted comments to commentsFile - const commentsSource = new RawSource(extractedComments.join("\n\n") + "\n"); - if(commentsFile in compilation.assets) { - // commentsFile already exists, append new comments... - if(compilation.assets[commentsFile] instanceof ConcatSource) { - compilation.assets[commentsFile].add("\n"); - compilation.assets[commentsFile].add(commentsSource); - } else { - compilation.assets[commentsFile] = new ConcatSource( - compilation.assets[commentsFile], "\n", commentsSource - ); - } - } else { - compilation.assets[commentsFile] = commentsSource; - } - - // Add a banner to the original file - if(options.extractComments.banner !== false) { - let banner = options.extractComments.banner || "For license information please see " + commentsFile; - if(typeof banner === "function") { - banner = banner(commentsFile); - } - if(banner) { - outputSource = new ConcatSource( - "/*! " + banner + " */\n", outputSource - ); - } - } - } - asset.__UglifyJsPlugin = compilation.assets[file] = outputSource; - if(warnings.length > 0) { - compilation.warnings.push(new Error(file + " from UglifyJs\n" + warnings.join("\n"))); - } - } catch(err) { - if(err.line) { - const original = sourceMap && sourceMap.originalPositionFor({ - line: err.line, - column: err.col - }); - if(original && original.source) { - compilation.errors.push(new Error(file + " from UglifyJs\n" + err.message + " [" + requestShortener.shorten(original.source) + ":" + original.line + "," + original.column + "][" + file + ":" + err.line + "," + err.col + "]")); - } else { - compilation.errors.push(new Error(file + " from UglifyJs\n" + err.message + " [" + file + ":" + err.line + "," + err.col + "]")); - } - } else if(err.msg) { - compilation.errors.push(new Error(file + " from UglifyJs\n" + err.msg)); - } else - compilation.errors.push(new Error(file + " from UglifyJs\n" + err.stack)); - } finally { - uglify.AST_Node.warn_function = oldWarnFunction; // eslint-disable-line camelcase - } - }); - callback(); - }); - }); - } -} +const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); module.exports = UglifyJsPlugin; diff --git a/package.json b/package.json index 221566e29..c44bded30 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "source-map": "^0.5.3", "supports-color": "^3.1.0", "tapable": "~0.2.5", - "uglify-js": "^2.8.27", + "uglifyjs-webpack-plugin": "^0.4.3", "watchpack": "^1.3.1", "webpack-sources": "^1.0.1", "yargs": "^6.0.0" diff --git a/yarn.lock b/yarn.lock index 4b530d5a5..b54d71a99 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3722,6 +3722,10 @@ source-list-map@^0.1.7, source-list-map@~0.1.7: version "0.1.8" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106" +source-list-map@^1.1.1: + version "1.1.2" + resolved "https://registry.npmjs.org/source-list-map/-/source-list-map-1.1.2.tgz#9889019d1024cce55cdc069498337ef6186a11a1" + source-list-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" @@ -4073,6 +4077,13 @@ uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" +uglifyjs-webpack-plugin@^0.4.3: + version "0.4.3" + resolved "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.3.tgz#a672a7d6655f94dfa7e09670d48030f37cc93267" + dependencies: + source-map "^0.5.6" + webpack-sources "^0.2.3" + uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" @@ -4200,6 +4211,13 @@ webpack-sources@^0.1.0: source-list-map "~0.1.7" source-map "~0.5.3" +webpack-sources@^0.2.3: + version "0.2.3" + resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-0.2.3.tgz#17c62bfaf13c707f9d02c479e0dcdde8380697fb" + dependencies: + source-list-map "^1.1.1" + source-map "~0.5.3" + webpack-sources@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.0.1.tgz#c7356436a4d13123be2e2426a05d1dad9cbe65cf"