From 876119d9d6fce58db471cb2371a9e126881183f4 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Tue, 3 Jul 2018 17:40:23 +0300 Subject: [PATCH] feat: support `minify` function option --- README.md | 101 +++++++++++ package-lock.json | 109 +++++++---- package.json | 2 + src/index.js | 11 +- src/options.json | 3 + src/uglify/{index.js => Runner.js} | 2 +- src/uglify/minify.js | 7 +- test/__snapshots__/minify.test.js.snap | 238 +++++++++++++++++++++++++ test/fixtures/minify/es5.js | 7 + test/fixtures/minify/es6.js | 15 ++ test/minify.test.js | 170 ++++++++++++++++++ 11 files changed, 628 insertions(+), 37 deletions(-) rename src/uglify/{index.js => Runner.js} (98%) create mode 100644 test/__snapshots__/minify.test.js.snap create mode 100644 test/fixtures/minify/es5.js create mode 100644 test/fixtures/minify/es6.js create mode 100644 test/minify.test.js diff --git a/README.md b/README.md index 57eae925..f836ad56 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ module.exports = { |**`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| @@ -89,6 +90,8 @@ module.exports = { ### `cache` +If you use your own `minify` function please read the `minify` section for cache invalidation correctly. + #### `{Boolean}` **webpack.config.js** @@ -178,6 +181,8 @@ Number of concurrent runs. ### `sourceMap` +If you use your own `minify` function please read the `minify` section for handling source maps correctly. + **webpack.config.js** ```js [ @@ -189,6 +194,102 @@ Number of concurrent runs. > ⚠️ **`cheap-source-map` options don't work with this plugin** +### `minify` + +**webpack.config.js** +```js +[ + new UglifyJsPlugin({ + minify(file, sourceMap) { + const extractedComments = []; + + // Custom logic for extract comments + + const { error, map, code, warnings } = minify( + file, + { /* Your options for minification */ }, + ); + + return { error, map, code, warnings, extractedComments }; + } + }) +] +``` + +By default plugin uses `uglify-es` package. + +Examples: + +#### `uglify-js` + +```bash +npm i -D uglify-js +``` + +**webpack.config.js** +```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 */ }; + + if (sourceMap) { + uglifyJsOptions.sourceMap = { + content: sourceMap, + }; + } + + return require('uglify-js').minify(file, uglifyJsOptions); + } + }) +] +``` + +#### `terser` + +```bash +npm i -D terser +``` + +**webpack.config.js** +```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 */ }; + + if (sourceMap) { + terserOption.sourceMap = { + content: sourceMap, + }; + } + + return require('terser').minify(file, terserOptions); + } + }) +] +``` + ### [`uglifyOptions`](https://github.com/mishoo/UglifyJS2/tree/harmony#minify-options) |Name|Type|Default|Description| diff --git a/package-lock.json b/package-lock.json index c6a361a3..fc579467 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,18 +5,18 @@ "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.0.0-beta.51", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.51.tgz", - "integrity": "sha1-vXHZsZKvl435FYKdOdQJRFZDmgw=", + "version": "7.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.52.tgz", + "integrity": "sha1-GSSDv6DR5GfBAVccIQKcy3SvKAE=", "dev": true, "requires": { - "@babel/highlight": "7.0.0-beta.51" + "@babel/highlight": "7.0.0-beta.52" } }, "@babel/highlight": { - "version": "7.0.0-beta.51", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.51.tgz", - "integrity": "sha1-6IRK4loVlcz9QriWI7Q3bKBtIl0=", + "version": "7.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.52.tgz", + "integrity": "sha1-7ySTFDLwYVXnvDnNuKaze0oos9A=", "dev": true, "requires": { "chalk": "^2.0.0", @@ -121,18 +121,18 @@ } }, "agent-base": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz", - "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", "dev": true, "requires": { "es6-promisify": "^5.0.0" } }, "ajv": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.1.tgz", - "integrity": "sha512-pgZos1vgOHDiC7gKNbZW8eKvCnNXARv2oqrGQT7Hzbq5Azp7aZG6DJzADnkuSq7RH6qkXp4J/m68yPX/2uBHyQ==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.2.tgz", + "integrity": "sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA==", "requires": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", @@ -1606,9 +1606,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000861", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000861.tgz", - "integrity": "sha512-aeEQ4kyd41qCl8XFbCjWgVBI3EOd66M9sC43MFn0kuD/vcrNqvoIAlKon4xdp8yMCYvVjdCltI3lgArj8I6cNA==", + "version": "1.0.30000864", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000864.tgz", + "integrity": "sha512-8fuGh8n3MIQ7oBkO/ck7J4LXhV5Sz5aLyFmfpChWpK+rJhqYrOsGDdbBVDdyKIRBWamZpy6iM4OmLCFVudOOhg==", "dev": true }, "capture-exit": { @@ -2636,9 +2636,9 @@ "dev": true }, "cssom": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.3.tgz", - "integrity": "sha512-pjE/I/NSp3iyeoxXN5QaoJpgzYUMj2dJHx9OSufoTliJLDx+kuOQaMCJW8OwvrKJswhXUHnHN6eUmUSETN0msg==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz", + "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==", "dev": true }, "cssstyle": { @@ -2999,9 +2999,9 @@ } }, "electron-to-chromium": { - "version": "1.3.50", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.50.tgz", - "integrity": "sha1-dDi3b5K0G5GfP73TUPvQdX2s3fc=", + "version": "1.3.51", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.51.tgz", + "integrity": "sha1-akK0nar38ipbN7mR2vlJ8029ubU=", "dev": true }, "elegant-spinner": { @@ -5227,9 +5227,9 @@ } }, "hosted-git-info": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.1.tgz", - "integrity": "sha512-Ba4+0M4YvIDUUsprMjhVTU1yN9F2/LJSAl69ZpzaLT4l4j5mwTS6jqqW9Ojvj6lKz/veqPzpJBqGbXspOb533A==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, "html-encoding-sniffer": { @@ -5490,9 +5490,9 @@ } }, "is-callable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", - "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", "dev": true }, "is-ci": { @@ -8851,9 +8851,9 @@ "dev": true }, "realpath-native": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.0.0.tgz", - "integrity": "sha512-XJtlRJ9jf0E1H1SLeJyQ9PGzQD7S65h1pRXEcAeK48doKOnKxcgPeNohJvD5u/2sI9J1oke6E8bZHS/fmW1UiQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.0.1.tgz", + "integrity": "sha512-W14EcXuqUvKP8dkWkD7B95iMy77lpMnlFXbbk409bQtNCbeu0kvRE5reo+yIZ3JXxg6frbGsz2DLQ39lrCB40g==", "dev": true, "requires": { "util.promisify": "^1.0.0" @@ -10417,6 +10417,35 @@ "execa": "^0.7.0" } }, + "terser": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/terser/-/terser-3.7.7.tgz", + "integrity": "sha512-RRLIxE7S52vSOI9cEbOaisgBd2y6MNgfg2ihUkidsFnuP1eDmZ79+lBWbyvgfFTAc/r8nSjL0k3cpZDDIYiYiA==", + "dev": true, + "requires": { + "commander": "~2.14.1", + "source-map": "~0.6.1", + "source-map-support": "~0.5.6" + }, + "dependencies": { + "commander": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", + "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==", + "dev": true + }, + "source-map-support": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz", + "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, "test-exclude": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.1.tgz", @@ -10913,6 +10942,24 @@ "source-map": "~0.6.1" } }, + "uglify-js": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.4.tgz", + "integrity": "sha512-RiB1kNcC9RMyqwRrjXC+EjgLoXULoDnCaOnEDzUCHkBN0bHwmtF5rzDMiDWU29gu0kXCRRWwtcTAVFWRECmU2Q==", + "dev": true, + "requires": { + "commander": "~2.16.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz", + "integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==", + "dev": true + } + } + }, "uglify-to-browserify": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", diff --git a/package.json b/package.json index 7480ea1c..1b8d9875 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,8 @@ "nsp": "^3.1.0", "pre-commit": "^1.2.2", "standard-version": "^4.3.0", + "terser": "^3.7.6", + "uglify-js": "^3.4.3", "webpack": "^3.10.0", "webpack-defaults": "^1.6.0" }, diff --git a/src/index.js b/src/index.js index 026dc236..b16fbbc5 100644 --- a/src/index.js +++ b/src/index.js @@ -9,7 +9,7 @@ import RequestShortener from 'webpack/lib/RequestShortener'; import ModuleFilenameHelpers from 'webpack/lib/ModuleFilenameHelpers'; import validateOptions from 'schema-utils'; import schema from './options.json'; -import Uglify from './uglify'; +import Runner from './uglify/Runner'; import versions from './uglify/versions'; import utils from './utils'; @@ -20,6 +20,7 @@ class UglifyJsPlugin { validateOptions(schema, options, 'UglifyJs Plugin'); const { + minify, uglifyOptions = {}, test = /\.js(\?.*)?$/i, warningsFilter = () => true, @@ -42,6 +43,7 @@ class UglifyJsPlugin { parallel, include, exclude, + minify, uglifyOptions: { compress: { inline: 1, @@ -114,7 +116,7 @@ class UglifyJsPlugin { }; const optimizeFn = (compilation, chunks, callback) => { - const uglify = new Uglify({ + const runner = new Runner({ cache: this.options.cache, parallel: this.options.parallel, }); @@ -169,6 +171,7 @@ class UglifyJsPlugin { commentsFile, extractComments: this.options.extractComments, uglifyOptions: this.options.uglifyOptions, + minify: this.options.minify, }; if (this.options.cache) { @@ -196,7 +199,7 @@ class UglifyJsPlugin { } }); - uglify.runTasks(tasks, (tasksError, results) => { + runner.runTasks(tasks, (tasksError, results) => { if (tasksError) { compilation.errors.push(tasksError); return; @@ -294,7 +297,7 @@ class UglifyJsPlugin { } }); - uglify.exit(); + runner.exit(); callback(); }); diff --git a/src/options.json b/src/options.json index cb6d17fb..76a09d25 100644 --- a/src/options.json +++ b/src/options.json @@ -24,6 +24,9 @@ "sourceMap": { "type": "boolean" }, + "minify": { + "instanceof": "Function" + }, "uglifyOptions": { "additionalProperties": true, "type": "object", diff --git a/src/uglify/index.js b/src/uglify/Runner.js similarity index 98% rename from src/uglify/index.js rename to src/uglify/Runner.js index ca99f210..c9c22667 100644 --- a/src/uglify/index.js +++ b/src/uglify/Runner.js @@ -12,7 +12,7 @@ try { workerFile = require.resolve('../../dist/uglify/worker'); } catch (e) { } // eslint-disable-line no-empty -export default class { +export default class Runner { constructor(options = {}) { const { cache, parallel } = options; this.cacheDir = cache === true ? findCacheDir({ name: 'uglifyjs-webpack-plugin' }) : cache; diff --git a/src/uglify/minify.js b/src/uglify/minify.js index 5993a31c..5e56b077 100644 --- a/src/uglify/minify.js +++ b/src/uglify/minify.js @@ -127,7 +127,12 @@ const buildComments = (options, uglifyOptions, extractedComments) => { }; const minify = (options) => { - const { file, input, inputSourceMap, extractComments } = options; + const { file, input, inputSourceMap, extractComments, minify: minifyFn } = options; + + if (minifyFn) { + return minifyFn({ [file]: input }, inputSourceMap); + } + // Copy uglify options const uglifyOptions = buildUglifyOptions(options.uglifyOptions); diff --git a/test/__snapshots__/minify.test.js.snap b/test/__snapshots__/minify.test.js.snap new file mode 100644 index 00000000..e5fc9aab --- /dev/null +++ b/test/__snapshots__/minify.test.js.snap @@ -0,0 +1,238 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`when applied with minify option matches snapshot for \`terser\` minifier and \`sourceMap: true\`: errors 1`] = `Array []`; + +exports[`when applied with minify option matches snapshot for \`terser\` minifier and \`sourceMap: true\`: main.js 1`] = ` +Object { + "map": Object { + "file": "x", + "mappings": "+CAAAA,OAAAC,eAAAC,EAAA,cAAAC,OAAA,IAcAD,EAAA,cAbAE,YAAAC,EAAAC,GACAC,KAAAF,IACAE,KAAAD,IAGAF,gBAAAI,EAAAC,GACA,MAAAC,EAAAF,EAAAH,EAAAI,EAAAJ,EACAM,EAAAH,EAAAF,EAAAG,EAAAH,EAEA,OAAAM,KAAAC,MAAAH,EAAAC", + "names": Array [ + "Object", + "defineProperty", + "__webpack_exports__", + "value", + "[object Object]", + "x", + "y", + "this", + "a", + "b", + "dx", + "dy", + "Math", + "hypot", + ], + "sources": Array [ + "test/fixtures/minify/es6.js", + ], + "sourcesContent": Array [ + "class Point { + constructor(x, y) { + this.x = x; + this.y = y; + } + + static distance(a, b) { + const dx = a.x - b.x; + const dy = a.y - b.y; + + return Math.hypot(dx, dy); + } +} + +export default Point; +", + ], + "version": 3, + }, + "source": "webpackJsonp([0],[function(t,e,s){\\"use strict\\";Object.defineProperty(e,\\"__esModule\\",{value:!0});e.default=class{constructor(t,e){this.x=t,this.y=e}static distance(t,e){const s=t.x-e.x,c=t.y-e.y;return Math.hypot(s,c)}}}],[0]);", +} +`; + +exports[`when applied with minify option matches snapshot for \`terser\` minifier and \`sourceMap: true\`: manifest.js 1`] = ` +Object { + "map": Object { + "file": "x", + "mappings": "aACA,IAAAA,EAAAC,OAAA,aACAA,OAAA,sBAAAC,EAAAC,EAAAC,GAIA,IADA,IAAAC,EAAAC,EAAAC,EAAAC,EAAA,EAAAC,EAAA,GACQD,EAAAN,EAAAQ,OAAoBF,IAC5BF,EAAAJ,EAAAM,GACAG,EAAAL,IACAG,EAAAG,KAAAD,EAAAL,GAAA,IAEAK,EAAAL,GAAA,EAEA,IAAAD,KAAAF,EACAU,OAAAC,UAAAC,eAAAC,KAAAb,EAAAE,KACAY,EAAAZ,GAAAF,EAAAE,IAIA,IADAL,KAAAE,EAAAC,EAAAC,GACAK,EAAAC,QACAD,EAAAS,OAAAT,GAEA,GAAAL,EACA,IAAAI,EAAA,EAAYA,EAAAJ,EAAAM,OAA2BF,IACvCD,EAAAY,IAAAC,EAAAhB,EAAAI,IAGA,OAAAD,GAIA,IAAAc,EAAA,GAGAV,EAAA,CACAW,EAAA,GAIA,SAAAH,EAAAd,GAGA,GAAAgB,EAAAhB,GACA,OAAAgB,EAAAhB,GAAAkB,QAGA,IAAAC,EAAAH,EAAAhB,GAAA,CACAG,EAAAH,EACAoB,GAAA,EACAF,QAAA,IAUA,OANAN,EAAAZ,GAAAW,KAAAQ,EAAAD,QAAAC,IAAAD,QAAAJ,GAGAK,EAAAC,GAAA,EAGAD,EAAAD,QAKAJ,EAAAO,EAAAT,EAGAE,EAAAQ,EAAAN,EAGAF,EAAAS,EAAA,SAAAL,EAAAM,EAAAC,GACAX,EAAAY,EAAAR,EAAAM,IACAhB,OAAAmB,eAAAT,EAAAM,EAAA,CACAI,cAAA,EACAC,YAAA,EACAC,IAAAL,KAMAX,EAAAiB,EAAA,SAAAZ,GACA,IAAAM,EAAAN,KAAAa,WACA,WAA2B,OAAAb,EAAA,SAC3B,WAAiC,OAAAA,GAEjC,OADAL,EAAAS,EAAAE,EAAA,IAAAA,GACAA,GAIAX,EAAAY,EAAA,SAAAO,EAAAC,GAAsD,OAAA1B,OAAAC,UAAAC,eAAAC,KAAAsB,EAAAC,IAGtDpB,EAAAqB,EAAA,GAGArB,EAAAsB,GAAA,SAAAC,GAA8D,MAApBC,QAAAC,MAAAF,GAAoBA", + "names": Array [ + "parentJsonpFunction", + "window", + "chunkIds", + "moreModules", + "executeModules", + "moduleId", + "chunkId", + "result", + "i", + "resolves", + "length", + "installedChunks", + "push", + "Object", + "prototype", + "hasOwnProperty", + "call", + "modules", + "shift", + "__webpack_require__", + "s", + "installedModules", + "1", + "exports", + "module", + "l", + "m", + "c", + "d", + "name", + "getter", + "o", + "defineProperty", + "configurable", + "enumerable", + "get", + "n", + "__esModule", + "object", + "property", + "p", + "oe", + "err", + "console", + "error", + ], + "sources": Array [ + "webpack/bootstrap 3a73c860b0d2c6572303", + ], + "sourcesContent": Array [ + " // install a JSONP callback for chunk loading + var parentJsonpFunction = window[\\"webpackJsonp\\"]; + window[\\"webpackJsonp\\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) { + // add \\"moreModules\\" to the modules object, + // then flag all \\"chunkIds\\" as loaded and fire callback + var moduleId, chunkId, i = 0, resolves = [], result; + for(;i < chunkIds.length; i++) { + chunkId = chunkIds[i]; + if(installedChunks[chunkId]) { + resolves.push(installedChunks[chunkId][0]); + } + installedChunks[chunkId] = 0; + } + for(moduleId in moreModules) { + if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { + modules[moduleId] = moreModules[moduleId]; + } + } + if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules); + while(resolves.length) { + resolves.shift()(); + } + if(executeModules) { + for(i=0; i < executeModules.length; i++) { + result = __webpack_require__(__webpack_require__.s = executeModules[i]); + } + } + return result; + }; + + // The module cache + var installedModules = {}; + + // objects to store loaded and loading chunks + var installedChunks = { + 1: 0 + }; + + // The require function + function __webpack_require__(moduleId) { + + // Check if module is in cache + if(installedModules[moduleId]) { + return installedModules[moduleId].exports; + } + // Create a new module (and put it into the cache) + var module = installedModules[moduleId] = { + i: moduleId, + l: false, + exports: {} + }; + + // Execute the module function + modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + + // Flag the module as loaded + module.l = true; + + // Return the exports of the module + return module.exports; + } + + + // expose the modules object (__webpack_modules__) + __webpack_require__.m = modules; + + // expose the module cache + __webpack_require__.c = installedModules; + + // define getter function for harmony exports + __webpack_require__.d = function(exports, name, getter) { + if(!__webpack_require__.o(exports, name)) { + Object.defineProperty(exports, name, { + configurable: false, + enumerable: true, + get: getter + }); + } + }; + + // getDefaultExport function for compatibility with non-harmony modules + __webpack_require__.n = function(module) { + var getter = module && module.__esModule ? + function getDefault() { return module['default']; } : + function getModuleExports() { return module; }; + __webpack_require__.d(getter, 'a', getter); + return getter; + }; + + // Object.prototype.hasOwnProperty.call + __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; + + // __webpack_public_path__ + __webpack_require__.p = \\"\\"; + + // on error function for async loading + __webpack_require__.oe = function(err) { console.error(err); throw err; }; +", + ], + "version": 3, + }, + "source": "!function(r){var n=window.webpackJsonp;window.webpackJsonp=function(e,u,c){for(var f,i,p,a=0,l=[];a { + it('matches snapshot for `uglify-js` minifier', () => { + const compiler = createCompiler({ + entry: `${__dirname}/fixtures/minify/es5.js`, + output: { + path: `${__dirname}/dist-uglify-js`, + filename: '[name].js', + chunkFilename: '[id].[name].js', + }, + }); + + new UglifyJsPlugin({ + minify(file) { + return uglifyJs.minify(file, { + mangle: { + reserved: ['baz'], + }, + }); + }, + }).apply(compiler); + + return compile(compiler) + .then((stats) => { + const errors = stats.compilation.errors.map(cleanErrorStack); + const warnings = stats.compilation.warnings.map(cleanErrorStack); + + expect(errors).toMatchSnapshot('errors'); + expect(warnings).toMatchSnapshot('warnings'); + + for (const file in stats.compilation.assets) { + if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) { + expect(stats.compilation.assets[file].source()).toMatchSnapshot(file); + } + } + }); + }); + + it('matches snapshot for `uglify-es` minifier', () => { + const compiler = createCompiler({ + entry: `${__dirname}/fixtures/minify/es6.js`, + output: { + path: `${__dirname}/dist-uglify-es`, + filename: '[name].js', + chunkFilename: '[id].[name].js', + }, + }); + + new UglifyJsPlugin({ + minify(file) { + return uglifyEs.minify(file, { + mangle: { + reserved: ['baz'], + }, + }); + }, + }).apply(compiler); + + return compile(compiler) + .then((stats) => { + const errors = stats.compilation.errors.map(cleanErrorStack); + const warnings = stats.compilation.warnings.map(cleanErrorStack); + + expect(errors).toMatchSnapshot('errors'); + expect(warnings).toMatchSnapshot('warnings'); + + for (const file in stats.compilation.assets) { + if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) { + expect(stats.compilation.assets[file].source()).toMatchSnapshot(file); + } + } + }); + }); + + it('matches snapshot for `terser` minifier', () => { + const compiler = createCompiler({ + entry: `${__dirname}/fixtures/minify/es6.js`, + output: { + path: `${__dirname}/dist-terser`, + filename: '[name].js', + chunkFilename: '[id].[name].js', + }, + }); + + new UglifyJsPlugin({ + minify(file) { + return terser.minify(file, { + mangle: { + reserved: ['baz'], + }, + }); + }, + }).apply(compiler); + + return compile(compiler) + .then((stats) => { + const errors = stats.compilation.errors.map(cleanErrorStack); + const warnings = stats.compilation.warnings.map(cleanErrorStack); + + expect(errors).toMatchSnapshot('errors'); + expect(warnings).toMatchSnapshot('warnings'); + + for (const file in stats.compilation.assets) { + if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) { + expect(stats.compilation.assets[file].source()).toMatchSnapshot(file); + } + } + }); + }); + + it('matches snapshot for `terser` minifier and `sourceMap: true`', () => { + const compiler = createCompiler({ + entry: `${__dirname}/fixtures/minify/es6.js`, + output: { + path: `${__dirname}/dist-terser`, + filename: '[name].js', + chunkFilename: '[id].[name].js', + }, + }); + + function removeAbsoluteSourceMapSources(source) { + if (source.map && source.map.sources) { + // eslint-disable-next-line no-param-reassign + source.map.sources = source.map.sources.map(sourceFromMap => path.relative(process.cwd(), sourceFromMap)); + } + + return source; + } + + new UglifyJsPlugin({ + sourceMap: true, + minify(file, sourceMap) { + const terserOption = { + mangle: { + reserved: ['baz'], + }, + }; + + if (sourceMap) { + terserOption.sourceMap = { + content: sourceMap, + }; + } + + return terser.minify(file, terserOption); + }, + }).apply(compiler); + + return compile(compiler) + .then((stats) => { + const errors = stats.compilation.errors.map(cleanErrorStack); + const warnings = stats.compilation.warnings.map(cleanErrorStack); + + expect(errors).toMatchSnapshot('errors'); + expect(warnings).toMatchSnapshot('warnings'); + + for (const file in stats.compilation.assets) { + if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) { + expect(removeAbsoluteSourceMapSources(stats.compilation.assets[file].sourceAndMap())).toMatchSnapshot(file); + } + } + }); + }); +});