Skip to content

Commit 29bbc3a

Browse files
fix: respect environment options for terser and swc compress options (#509)
1 parent 64f2ff5 commit 29bbc3a

File tree

8 files changed

+857
-654
lines changed

8 files changed

+857
-654
lines changed

package-lock.json

Lines changed: 693 additions & 634 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/utils.js

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
/** @typedef {import("@jridgewell/trace-mapping").SourceMapInput} SourceMapInput */
22
/** @typedef {import("terser").FormatOptions} TerserFormatOptions */
33
/** @typedef {import("terser").MinifyOptions} TerserOptions */
4+
/** @typedef {import("terser").CompressOptions} TerserCompressOptions */
45
/** @typedef {import("terser").ECMA} TerserECMA */
6+
/** @typedef {import("@swc/core").JsMinifyOptions} SwcMinifyOptions */
7+
/** @typedef {import("@swc/core").TerserCompressOptions} SwcCompressOptions */
58
/** @typedef {import("./index.js").ExtractCommentsOptions} ExtractCommentsOptions */
69
/** @typedef {import("./index.js").ExtractCommentsFunction} ExtractCommentsFunction */
710
/** @typedef {import("./index.js").ExtractCommentsCondition} ExtractCommentsCondition */
@@ -219,15 +222,15 @@ async function terserMinify(
219222

220223
/**
221224
* @param {PredefinedOptions & TerserOptions} [terserOptions={}]
222-
* @returns {TerserOptions & { sourceMap: undefined } & ({ output: TerserFormatOptions & { beautify: boolean } } | { format: TerserFormatOptions & { beautify: boolean } })}
225+
* @returns {TerserOptions & { sourceMap: undefined } & { compress: TerserCompressOptions } & ({ output: TerserFormatOptions & { beautify: boolean } } | { format: TerserFormatOptions & { beautify: boolean } })}
223226
*/
224227
const buildTerserOptions = (terserOptions = {}) => {
225228
// Need deep copy objects to avoid https://github.com/terser/terser/issues/366
226229
return {
227230
...terserOptions,
228231
compress:
229232
typeof terserOptions.compress === "boolean"
230-
? terserOptions.compress
233+
? {}
231234
: { ...terserOptions.compress },
232235
// ecma: terserOptions.ecma,
233236
// ie8: terserOptions.ie8,
@@ -280,6 +283,19 @@ async function terserMinify(
280283
);
281284
}
282285

286+
// More optimizations
287+
if (typeof terserOptions.compress.ecma === "undefined") {
288+
terserOptions.compress.ecma = terserOptions.ecma;
289+
}
290+
291+
// https://github.com/webpack/webpack/issues/16135
292+
if (
293+
terserOptions.ecma === 5 &&
294+
typeof terserOptions.compress.arrows === "undefined"
295+
) {
296+
terserOptions.compress.arrows = false;
297+
}
298+
283299
const [[filename, code]] = Object.entries(input);
284300
const result = await minify({ [filename]: code }, terserOptions);
285301

@@ -536,15 +552,15 @@ uglifyJsMinify.getMinimizerVersion = () => {
536552
async function swcMinify(input, sourceMap, minimizerOptions) {
537553
/**
538554
* @param {PredefinedOptions & import("@swc/core").JsMinifyOptions} [swcOptions={}]
539-
* @returns {import("@swc/core").JsMinifyOptions & { sourceMap: undefined }}
555+
* @returns {SwcMinifyOptions & { sourceMap: undefined } & { compress: SwcCompressOptions }}
540556
*/
541557
const buildSwcOptions = (swcOptions = {}) => {
542558
// Need deep copy objects to avoid https://github.com/terser/terser/issues/366
543559
return {
544560
...swcOptions,
545561
compress:
546562
typeof swcOptions.compress === "boolean"
547-
? swcOptions.compress
563+
? {}
548564
: { ...swcOptions.compress },
549565
mangle:
550566
swcOptions.mangle == null
@@ -574,6 +590,19 @@ async function swcMinify(input, sourceMap, minimizerOptions) {
574590
swcOptions.sourceMap = true;
575591
}
576592

593+
// More optimizations
594+
if (typeof swcOptions.compress.ecma === "undefined") {
595+
swcOptions.compress.ecma = swcOptions.ecma;
596+
}
597+
598+
// https://github.com/webpack/webpack/issues/16135
599+
if (
600+
swcOptions.ecma === 5 &&
601+
typeof swcOptions.compress.arrows === "undefined"
602+
) {
603+
swcOptions.compress.arrows = false;
604+
}
605+
577606
const [[filename, code]] = Object.entries(input);
578607
const result = await swc.minify(code, swcOptions);
579608

test/__snapshots__/minify-option.test.js.snap

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ exports[`minify option should work using when the \`minify\` option is \`esbuild
119119
120120
exports[`minify option should work using when the \`minify\` option is \`swcMinify\` and ECMA modules output: assets 1`] = `
121121
Object {
122-
"main.js": "var a={};a.d=(b,c)=>{for(var d in c)a.o(c,d)&&!a.o(b,d)&&Object.defineProperty(b,d,{enumerable:!0,get:c[d]})},a.o=(a,b)=>Object.prototype.hasOwnProperty.call(a,b);var b={};function c(){console.log(11)}a.d(b,{Z:()=>d}),c();let d=c;var e=b.Z;export{e as default}",
122+
"main.js": "var e={};e.d=(r,o)=>{for(var a in o)e.o(o,a)&&!e.o(r,a)&&Object.defineProperty(r,a,{enumerable:!0,get:o[a]})},e.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r);var r={};function o(){console.log(11)}e.d(r,{Z:()=>a}),o();let a=o;var t=r.Z;export{t as default}",
123123
}
124124
`;
125125
@@ -139,7 +139,7 @@ exports[`minify option should work using when the \`minify\` option is \`swcMini
139139
140140
exports[`minify option should work using when the \`minify\` option is \`swcMinify\` and generate source maps: assets 1`] = `
141141
Object {
142-
"main.js": "(()=>{var a={791(a){a.exports=function(){console.log(7)}}},b={};function c(d){var e=b[d];if(void 0!==e)return e.exports;var f=b[d]={exports:{}};return a[d](f,f.exports,c),f.exports}var d=c(791)})()
142+
"main.js": "(()=>{var r={791(r){r.exports=function(){console.log(7)}}},o={};function t(e){var n=o[e];if(void 0!==n)return n.exports;var p=o[e]={exports:{}};return r[e](p,p.exports,t),p.exports}var e=t(791)})()
143143
//# sourceMappingURL=main.js.map",
144144
"main.js.map": "{\\"version\\":3,\\"file\\":\\"main.js\\",\\"mappings\\":\\"oBAKAA,CAAM,CAACC,OAAO,CAAG,UAAe,CAE9BC,OAAO,CAACC,GAAG,CAACC,CAAS,CAAC,CACvB,C,ECPGC,CAAwB,CAAG,EAAE,UAGxBC,CAAmB,CAACC,CAAQ,CAAE,CAEtC,IAAIC,CAAY,CAAGH,CAAwB,CAACE,CAAQ,CAAC,IACjDC,KAAiBC,CAAS,GAA1BD,CAAY,CACf,OAAOA,CAAY,CAACP,OAAO,KAGxBD,CAAM,CAAGK,CAAwB,CAACE,CAAQ,CAAC,CAAG,CAGjDN,OAAO,CAAE,EAAE,CACX,QAGDS,CAAmB,CAACH,CAAQ,CAAC,CAACP,CAAM,CAAEA,CAAM,CAACC,OAAO,CAAEK,CAAmB,CAAC,CAGnEN,CAAM,CAACC,OAAO,CACrB,ICnBGU,CAAmB,CAAGL,CAAmB,CAAC,GAAG,CAAC,C\\",\\"sources\\":[\\"webpack://terser-webpack-plugin/./test/fixtures/entry.js\\",\\"webpack://terser-webpack-plugin/webpack/bootstrap\\",\\"webpack://terser-webpack-plugin/webpack/startup\\"],\\"sourcesContent\\":[\\"// foo\\\\n/* @preserve*/\\\\n// bar\\\\nconst a = 2 + 2;\\\\n\\\\nmodule.exports = function Foo() {\\\\n const b = 2 + 2;\\\\n console.log(b + 1 + 2);\\\\n};\\\\n\\",\\"// The module cache\\\\nvar __webpack_module_cache__ = {};\\\\n\\\\n// The require function\\\\nfunction __webpack_require__(moduleId) {\\\\n\\\\t// Check if module is in cache\\\\n\\\\tvar cachedModule = __webpack_module_cache__[moduleId];\\\\n\\\\tif (cachedModule !== undefined) {\\\\n\\\\t\\\\treturn cachedModule.exports;\\\\n\\\\t}\\\\n\\\\t// Create a new module (and put it into the cache)\\\\n\\\\tvar module = __webpack_module_cache__[moduleId] = {\\\\n\\\\t\\\\t// no module.id needed\\\\n\\\\t\\\\t// no module.loaded needed\\\\n\\\\t\\\\texports: {}\\\\n\\\\t};\\\\n\\\\n\\\\t// Execute the module function\\\\n\\\\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\\\\n\\\\n\\\\t// Return the exports of the module\\\\n\\\\treturn module.exports;\\\\n}\\\\n\\\\n\\",\\"// startup\\\\n// Load entry module and return exports\\\\n// This entry module is referenced by other modules so it can't be inlined\\\\nvar __webpack_exports__ = __webpack_require__(791);\\\\n\\"],\\"names\\":[\\"module\\",\\"exports\\",\\"console\\",\\"log\\",\\"b\\",\\"__webpack_module_cache__\\",\\"__webpack_require__\\",\\"moduleId\\",\\"cachedModule\\",\\"undefined\\",\\"__webpack_modules__\\",\\"__webpack_exports__\\"],\\"sourceRoot\\":\\"\\"}",
145145
}
@@ -160,7 +160,7 @@ exports[`minify option should work using when the \`minify\` option is \`swcMini
160160
161161
exports[`minify option should work using when the \`minify\` option is \`swcMinify\`: assets 1`] = `
162162
Object {
163-
"main.js": "(()=>{var a={791(a){a.exports=function(){console.log(7)}}},b={};function c(d){var e=b[d];if(void 0!==e)return e.exports;var f=b[d]={exports:{}};return a[d](f,f.exports,c),f.exports}var d=c(791)})()",
163+
"main.js": "(()=>{var r={791(r){r.exports=function(){console.log(7)}}},o={};function t(e){var n=o[e];if(void 0!==n)return n.exports;var p=o[e]={exports:{}};return r[e](p,p.exports,t),p.exports}var e=t(791)})()",
164164
}
165165
`;
166166

test/__snapshots__/terserOptions-option.test.js.snap

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@ exports[`terserOptions option should match snapshot for the "compress" option wi
1212

1313
exports[`terserOptions option should match snapshot for the "compress" option with the "false" value: assets 1`] = `
1414
Object {
15-
"main.js": "/*! For license information please see main.js.LICENSE.txt */
16-
(()=>{var r={791:r=>{const n=null&&2+2;r.exports=function r(){const n=2+2;console.log(n+1+2)}}};var n={};function o(t){var e=n[t];if(e!==undefined){return e.exports}var s=n[t]={exports:{}};r[t](s,s.exports,o);return s.exports}var t=o(791)})();",
17-
"main.js.LICENSE.txt": "/* @preserve*/
18-
",
15+
"main.js": "(()=>{var r={791:r=>{r.exports=function(){console.log(7)}}},o={};(function t(e){var n=o[e];if(void 0!==n)return n.exports;var s=o[e]={exports:{}};return r[e](s,s.exports,t),s.exports})(791)})();",
1916
}
2017
`;
2118

@@ -38,7 +35,7 @@ Object {
3835
"main.js": "!function() {
3936
var __webpack_modules__ = {
4037
931: function(module) {
41-
var Person = {
38+
var abc, Person = {
4239
firstName: null,
4340
lastName: null
4441
}, Employee = Object.create(Person, {
@@ -60,7 +57,13 @@ Object {
6057
Person: Person,
6158
Employee: Employee,
6259
Manager: Manager
63-
};
60+
}, abc = {
61+
data() {
62+
return {
63+
a: 2
64+
};
65+
}
66+
}, console.log(abc);
6467
}
6568
}, __webpack_module_cache__ = {};
6669
(function __webpack_require__(moduleId) {
@@ -85,7 +88,7 @@ Object {
8588
"main.js": "!function() {
8689
var __webpack_modules__ = {
8790
931: function(module) {
88-
var Person = {
91+
var abc, Person = {
8992
firstName: null,
9093
lastName: null
9194
}, Employee = Object.create(Person, {
@@ -107,7 +110,13 @@ Object {
107110
Person: Person,
108111
Employee: Employee,
109112
Manager: Manager
110-
};
113+
}, abc = {
114+
data() {
115+
return {
116+
a: 2
117+
};
118+
}
119+
}, console.log(abc);
111120
}
112121
}, __webpack_module_cache__ = {};
113122
(function __webpack_require__(moduleId) {
@@ -132,7 +141,7 @@ Object {
132141
"main.js": "(() => {
133142
var __webpack_modules__ = {
134143
931: module => {
135-
var Person = {
144+
var abc, Person = {
136145
firstName: null,
137146
lastName: null
138147
}, Employee = Object.create(Person, {
@@ -154,7 +163,11 @@ Object {
154163
Person,
155164
Employee,
156165
Manager
157-
};
166+
}, abc = {
167+
data: () => ({
168+
a: 2
169+
})
170+
}, console.log(abc);
158171
}
159172
}, __webpack_module_cache__ = {};
160173
(function __webpack_require__(moduleId) {
@@ -174,12 +187,22 @@ exports[`terserOptions option should match snapshot for the "ecma" and set the o
174187

175188
exports[`terserOptions option should match snapshot for the "ecma" and set the option depending on the "output.environment" option ("es2020"): warnings 1`] = `Array []`;
176189

190+
exports[`terserOptions option should match snapshot for the "ecma" option with the "5" value ("swc"): assets 1`] = `
191+
Object {
192+
"main.js": "(()=>{var __webpack_modules__={931:module=>{var Person={firstName:null,lastName:null},Employee=Object.create(Person,{id:{value:null,enumerable:!0,configurable:!0,writable:!0}}),Manager=Object.create(Employee,{department:{value:null,enumerable:!0,configurable:!0,writable:!0}});module.exports={Person:Person,Employee:Employee,Manager:Manager},function(){var abc={data(){return{a:2}}};console.log(abc)}()}},__webpack_module_cache__={};function __webpack_require__(moduleId){var cachedModule=__webpack_module_cache__[moduleId];if(void 0!==cachedModule)return cachedModule.exports;var module=__webpack_module_cache__[moduleId]={exports:{}};return __webpack_modules__[moduleId](module,module.exports,__webpack_require__),module.exports}var __webpack_exports__=__webpack_require__(931)})()",
193+
}
194+
`;
195+
196+
exports[`terserOptions option should match snapshot for the "ecma" option with the "5" value ("swc"): errors 1`] = `Array []`;
197+
198+
exports[`terserOptions option should match snapshot for the "ecma" option with the "5" value ("swc"): warnings 1`] = `Array []`;
199+
177200
exports[`terserOptions option should match snapshot for the "ecma" option with the "5" value: assets 1`] = `
178201
Object {
179202
"main.js": "(() => {
180203
var __webpack_modules__ = {
181204
931: module => {
182-
var Person = {
205+
var abc, Person = {
183206
firstName: null,
184207
lastName: null
185208
}, Employee = Object.create(Person, {
@@ -201,7 +224,13 @@ Object {
201224
Person: Person,
202225
Employee: Employee,
203226
Manager: Manager
204-
};
227+
}, abc = {
228+
data() {
229+
return {
230+
a: 2
231+
};
232+
}
233+
}, console.log(abc);
205234
}
206235
}, __webpack_module_cache__ = {};
207236
(function __webpack_require__(moduleId) {
@@ -221,12 +250,27 @@ exports[`terserOptions option should match snapshot for the "ecma" option with t
221250

222251
exports[`terserOptions option should match snapshot for the "ecma" option with the "5" value: warnings 1`] = `Array []`;
223252

253+
exports[`terserOptions option should match snapshot for the "ecma" option with the "6" value ("swc"): assets 1`] = `
254+
Object {
255+
"main.js": "(()=>{var __webpack_modules__={513(module){console.log({data:()=>({a:2})}),module.exports=class{constructor(principal,years,rate){this.principal=principal,this.years=years,this.rate=rate}get monthlyPayment(){let monthlyRate=this.rate/100/12;return this.principal*monthlyRate/(1-Math.pow(1/(1+monthlyRate),12*this.years))}get amortization(){let monthlyPayment=this.monthlyPayment,monthlyRate=this.rate/100/12,balance=this.principal,amortization=[];for(let y=0;y<this.years;y++){let interestY=0,principalY=0;for(let m=0;m<12;m++){let interestM=balance*monthlyRate,principalM=monthlyPayment-interestM;interestY+=interestM,principalY+=principalM,balance-=principalM}amortization.push({principalY,interestY,balance})}return amortization}}}},__webpack_module_cache__={};function __webpack_require__(moduleId){var cachedModule=__webpack_module_cache__[moduleId];if(void 0!==cachedModule)return cachedModule.exports;var module=__webpack_module_cache__[moduleId]={exports:{}};return __webpack_modules__[moduleId](module,module.exports,__webpack_require__),module.exports}var __webpack_exports__=__webpack_require__(513)})()",
256+
}
257+
`;
258+
259+
exports[`terserOptions option should match snapshot for the "ecma" option with the "6" value ("swc"): errors 1`] = `Array []`;
260+
261+
exports[`terserOptions option should match snapshot for the "ecma" option with the "6" value ("swc"): warnings 1`] = `Array []`;
262+
224263
exports[`terserOptions option should match snapshot for the "ecma" option with the "6" value: assets 1`] = `
225264
Object {
226265
"main.js": "(() => {
227266
var __webpack_modules__ = {
228267
513: module => {
229-
module.exports = class {
268+
var abc;
269+
abc = {
270+
data: () => ({
271+
a: 2
272+
})
273+
}, console.log(abc), module.exports = class {
230274
constructor(principal, years, rate) {
231275
this.principal = principal, this.years = years, this.rate = rate;
232276
}

test/fixtures/ecma-5/entry.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,14 @@ module.exports = {
2828
Employee: Employee,
2929
Manager: Manager
3030
};
31+
32+
(function() {
33+
var zzz = {};
34+
var abc = {
35+
data() {
36+
return {
37+
a: 2
38+
};
39+
}};
40+
console.log(abc)
41+
})();

test/fixtures/ecma-6/entry.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,15 @@ class Mortgage {
3434
}
3535
}
3636

37+
(function() {
38+
var zzz = {};
39+
var abc = {
40+
data() {
41+
return {
42+
a: 2
43+
};
44+
}};
45+
console.log(abc)
46+
})();
47+
3748
module.exports = Mortgage;

test/terserOptions-option.test.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,29 @@ describe("terserOptions option", () => {
9999
expect(getWarnings(stats)).toMatchSnapshot("warnings");
100100
});
101101

102+
it('should match snapshot for the "ecma" option with the "5" value ("swc")', async () => {
103+
const compiler = getCompiler({
104+
entry: path.resolve(__dirname, "./fixtures/ecma-5/entry.js"),
105+
});
106+
107+
new TerserPlugin({
108+
minify: TerserPlugin.swcMinify,
109+
terserOptions: {
110+
ecma: 5,
111+
mangle: false,
112+
format: {
113+
beautify: true,
114+
},
115+
},
116+
}).apply(compiler);
117+
118+
const stats = await compile(compiler);
119+
120+
expect(readsAssets(compiler, stats)).toMatchSnapshot("assets");
121+
expect(getErrors(stats)).toMatchSnapshot("errors");
122+
expect(getWarnings(stats)).toMatchSnapshot("warnings");
123+
});
124+
102125
it('should match snapshot for the "ecma" option with the "6" value', async () => {
103126
const compiler = getCompiler({
104127
entry: path.resolve(__dirname, "./fixtures/ecma-6/entry.js"),
@@ -121,6 +144,29 @@ describe("terserOptions option", () => {
121144
expect(getWarnings(stats)).toMatchSnapshot("warnings");
122145
});
123146

147+
it('should match snapshot for the "ecma" option with the "6" value ("swc")', async () => {
148+
const compiler = getCompiler({
149+
entry: path.resolve(__dirname, "./fixtures/ecma-6/entry.js"),
150+
});
151+
152+
new TerserPlugin({
153+
minify: TerserPlugin.swcMinify,
154+
terserOptions: {
155+
ecma: 6,
156+
mangle: false,
157+
format: {
158+
beautify: true,
159+
},
160+
},
161+
}).apply(compiler);
162+
163+
const stats = await compile(compiler);
164+
165+
expect(readsAssets(compiler, stats)).toMatchSnapshot("assets");
166+
expect(getErrors(stats)).toMatchSnapshot("errors");
167+
expect(getWarnings(stats)).toMatchSnapshot("warnings");
168+
});
169+
124170
it('should match snapshot for the "ecma" option with the "7" value', async () => {
125171
const compiler = getCompiler({
126172
entry: path.resolve(__dirname, "./fixtures/ecma-7/entry.js"),

types/utils.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ export type Task<T> = () => Promise<T>;
22
export type SourceMapInput = import("@jridgewell/trace-mapping").SourceMapInput;
33
export type TerserFormatOptions = import("terser").FormatOptions;
44
export type TerserOptions = import("terser").MinifyOptions;
5+
export type TerserCompressOptions = import("terser").CompressOptions;
56
export type TerserECMA = import("terser").ECMA;
7+
export type SwcMinifyOptions = import("@swc/core").JsMinifyOptions;
8+
export type SwcCompressOptions = import("@swc/core").TerserCompressOptions;
69
export type ExtractCommentsOptions =
710
import("./index.js").ExtractCommentsOptions;
811
export type ExtractCommentsFunction =

0 commit comments

Comments
 (0)