UNPKG

13.3 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _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
8 no-param-reassign
9 */
10
11
12var _crypto = require('crypto');
13
14var _crypto2 = _interopRequireDefault(_crypto);
15
16var _sourceMap = require('source-map');
17
18var _webpackSources = require('webpack-sources');
19
20var _RequestShortener = require('webpack/lib/RequestShortener');
21
22var _RequestShortener2 = _interopRequireDefault(_RequestShortener);
23
24var _ModuleFilenameHelpers = require('webpack/lib/ModuleFilenameHelpers');
25
26var _ModuleFilenameHelpers2 = _interopRequireDefault(_ModuleFilenameHelpers);
27
28var _schemaUtils = require('schema-utils');
29
30var _schemaUtils2 = _interopRequireDefault(_schemaUtils);
31
32var _serializeJavascript = require('serialize-javascript');
33
34var _serializeJavascript2 = _interopRequireDefault(_serializeJavascript);
35
36var _options = require('./options.json');
37
38var _options2 = _interopRequireDefault(_options);
39
40var _uglify = require('./uglify');
41
42var _uglify2 = _interopRequireDefault(_uglify);
43
44var _versions = require('./uglify/versions');
45
46var _versions2 = _interopRequireDefault(_versions);
47
48function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
49
50function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
51
52var warningRegex = /\[.+:([0-9]+),([0-9]+)\]/;
53
54var UglifyJsPlugin = function () {
55 function UglifyJsPlugin() {
56 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
57
58 _classCallCheck(this, UglifyJsPlugin);
59
60 (0, _schemaUtils2.default)(_options2.default, options, 'UglifyJs Plugin');
61
62 var _options$uglifyOption = options.uglifyOptions,
63 uglifyOptions = _options$uglifyOption === undefined ? {} : _options$uglifyOption,
64 _options$test = options.test,
65 test = _options$test === undefined ? /\.js$/i : _options$test,
66 _options$warningsFilt = options.warningsFilter,
67 warningsFilter = _options$warningsFilt === undefined ? function () {
68 return true;
69 } : _options$warningsFilt,
70 _options$extractComme = options.extractComments,
71 extractComments = _options$extractComme === undefined ? false : _options$extractComme,
72 _options$sourceMap = options.sourceMap,
73 sourceMap = _options$sourceMap === undefined ? false : _options$sourceMap,
74 _options$cache = options.cache,
75 cache = _options$cache === undefined ? false : _options$cache,
76 _options$parallel = options.parallel,
77 parallel = _options$parallel === undefined ? false : _options$parallel,
78 include = options.include,
79 exclude = options.exclude;
80
81
82 this.options = {
83 test,
84 warningsFilter,
85 extractComments,
86 sourceMap,
87 cache,
88 parallel,
89 include,
90 exclude,
91 uglifyOptions: Object.assign({
92 output: {
93 comments: false
94 }
95 }, uglifyOptions)
96 };
97 }
98
99 _createClass(UglifyJsPlugin, [{
100 key: 'apply',
101 value: function apply(compiler) {
102 var _this = this;
103
104 var requestShortener = new _RequestShortener2.default(compiler.context);
105
106 var buildModuleFn = function buildModuleFn(moduleArg) {
107 // to get detailed location info about errors
108 moduleArg.useSourceMap = true;
109 };
110
111 var optimizeFn = function optimizeFn(compilation, chunks, callback) {
112 var uglify = new _uglify2.default({
113 cache: _this.options.cache,
114 parallel: _this.options.parallel
115 });
116
117 var uglifiedAssets = new WeakSet();
118 var tasks = [];
119
120 chunks.reduce(function (acc, chunk) {
121 return acc.concat(chunk.files || []);
122 }, []).concat(compilation.additionalChunkAssets || []).filter(_ModuleFilenameHelpers2.default.matchObject.bind(null, _this.options)).forEach(function (file) {
123 var sourceMap = void 0;
124 var asset = compilation.assets[file];
125 if (uglifiedAssets.has(asset)) {
126 return;
127 }
128
129 try {
130 var input = void 0;
131 var inputSourceMap = void 0;
132
133 if (_this.options.sourceMap && asset.sourceAndMap) {
134 var _asset$sourceAndMap = asset.sourceAndMap(),
135 source = _asset$sourceAndMap.source,
136 map = _asset$sourceAndMap.map;
137
138 input = source;
139 inputSourceMap = map;
140
141 sourceMap = new _sourceMap.SourceMapConsumer(inputSourceMap);
142 } else {
143 input = asset.source();
144 inputSourceMap = null;
145 }
146
147 // Handling comment extraction
148 var commentsFile = false;
149 if (_this.options.extractComments) {
150 commentsFile = _this.options.extractComments.filename || `${file}.LICENSE`;
151 if (typeof commentsFile === 'function') {
152 commentsFile = commentsFile(file);
153 }
154 }
155
156 var task = {
157 file,
158 input,
159 sourceMap,
160 inputSourceMap,
161 commentsFile,
162 extractComments: _this.options.extractComments,
163 uglifyOptions: _this.options.uglifyOptions
164 };
165
166 if (_this.options.cache) {
167 task.cacheKey = (0, _serializeJavascript2.default)({
168 'uglify-es': _versions2.default.uglify,
169 'uglifyjs-webpack-plugin': _versions2.default.plugin,
170 'uglifyjs-webpack-plugin-options': _this.options,
171 path: compiler.outputPath ? `${compiler.outputPath}/${file}` : file,
172 hash: _crypto2.default.createHash('md5').update(input).digest('hex')
173 });
174 }
175
176 tasks.push(task);
177 } catch (error) {
178 compilation.errors.push(UglifyJsPlugin.buildError(error, file, sourceMap, requestShortener));
179 }
180 });
181
182 uglify.runTasks(tasks, function (tasksError, results) {
183 if (tasksError) {
184 compilation.errors.push(tasksError);
185 return;
186 }
187
188 results.forEach(function (data, index) {
189 var _tasks$index = tasks[index],
190 file = _tasks$index.file,
191 input = _tasks$index.input,
192 sourceMap = _tasks$index.sourceMap,
193 inputSourceMap = _tasks$index.inputSourceMap,
194 commentsFile = _tasks$index.commentsFile;
195 var error = data.error,
196 map = data.map,
197 code = data.code,
198 warnings = data.warnings,
199 extractedComments = data.extractedComments;
200
201 // Handling results
202 // Error case: add errors, and go to next file
203
204 if (error) {
205 compilation.errors.push(UglifyJsPlugin.buildError(error, file, sourceMap, requestShortener));
206
207 return;
208 }
209
210 var outputSource = void 0;
211 if (map) {
212 outputSource = new _webpackSources.SourceMapSource(code, file, JSON.parse(map), input, inputSourceMap);
213 } else {
214 outputSource = new _webpackSources.RawSource(code);
215 }
216
217 // Write extracted comments to commentsFile
218 if (commentsFile && extractedComments.length > 0) {
219 // Add a banner to the original file
220 if (_this.options.extractComments.banner !== false) {
221 var banner = _this.options.extractComments.banner || `For license information please see ${commentsFile}`;
222
223 if (typeof banner === 'function') {
224 banner = banner(commentsFile);
225 }
226
227 if (banner) {
228 outputSource = new _webpackSources.ConcatSource(`/*! ${banner} */\n`, outputSource);
229 }
230 }
231
232 var commentsSource = new _webpackSources.RawSource(`${extractedComments.join('\n\n')}\n`);
233
234 if (commentsFile in compilation.assets) {
235 // commentsFile already exists, append new comments...
236 if (compilation.assets[commentsFile] instanceof _webpackSources.ConcatSource) {
237 compilation.assets[commentsFile].add('\n');
238 compilation.assets[commentsFile].add(commentsSource);
239 } else {
240 compilation.assets[commentsFile] = new _webpackSources.ConcatSource(compilation.assets[commentsFile], '\n', commentsSource);
241 }
242 } else {
243 compilation.assets[commentsFile] = commentsSource;
244 }
245 }
246
247 // Updating assets
248 uglifiedAssets.add(compilation.assets[file] = outputSource);
249
250 // Handling warnings
251 if (warnings) {
252 var warnArr = UglifyJsPlugin.buildWarnings(warnings, file, sourceMap, _this.options.warningsFilter, requestShortener);
253
254 if (warnArr.length > 0) {
255 compilation.warnings.push(new Error(`${file} from UglifyJs\n${warnArr.join('\n')}`));
256 }
257 }
258 });
259
260 uglify.exit();
261
262 callback();
263 });
264 };
265
266 if (compiler.hooks) {
267 var plugin = { name: 'UglifyJSPlugin' };
268
269 compiler.hooks.compilation.tap(plugin, function (compilation) {
270 if (_this.options.sourceMap) {
271 compilation.hooks.buildModule.tap(plugin, buildModuleFn);
272 }
273
274 compilation.hooks.optimizeChunkAssets.tapAsync(plugin, optimizeFn.bind(_this, compilation));
275 });
276 } else {
277 compiler.plugin('compilation', function (compilation) {
278 if (_this.options.sourceMap) {
279 compilation.plugin('build-module', buildModuleFn);
280 }
281
282 compilation.plugin('optimize-chunk-assets', optimizeFn.bind(_this, compilation));
283 });
284 }
285 }
286 }], [{
287 key: 'buildError',
288 value: function buildError(err, file, sourceMap, requestShortener) {
289 // Handling error which should have line, col, filename and message
290 if (err.line) {
291 var original = sourceMap && sourceMap.originalPositionFor({
292 line: err.line,
293 column: err.col
294 });
295 if (original && original.source) {
296 return new Error(`${file} from UglifyJs\n${err.message} [${requestShortener.shorten(original.source)}:${original.line},${original.column}][${file}:${err.line},${err.col}]`);
297 }
298 return new Error(`${file} from UglifyJs\n${err.message} [${file}:${err.line},${err.col}]`);
299 } else if (err.stack) {
300 return new Error(`${file} from UglifyJs\n${err.stack}`);
301 }
302 return new Error(`${file} from UglifyJs\n${err.message}`);
303 }
304 }, {
305 key: 'buildWarnings',
306 value: function buildWarnings(warnings, file, sourceMap, warningsFilter, requestShortener) {
307 if (!sourceMap) {
308 return warnings;
309 }
310 return warnings.reduce(function (accWarnings, warning) {
311 var match = warningRegex.exec(warning);
312 var line = +match[1];
313 var column = +match[2];
314 var original = sourceMap.originalPositionFor({
315 line,
316 column
317 });
318
319 if (original && original.source && original.source !== file && warningsFilter(original.source)) {
320 accWarnings.push(`${warning.replace(warningRegex, '')}[${requestShortener.shorten(original.source)}:${original.line},${original.column}]`);
321 }
322
323 return accWarnings;
324 }, []);
325 }
326 }]);
327
328 return UglifyJsPlugin;
329}();
330
331exports.default = UglifyJsPlugin;
\No newline at end of file