diff --git a/package.json b/package.json index 3ccfee6..ef00f1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rollup-plugin-terser", - "version": "7.0.2", + "version": "7.1.0", "description": "Rollup plugin to minify generated es bundle", "type": "commonjs", "main": "rollup-plugin-terser.js", @@ -32,18 +32,18 @@ "author": "Bogdan Chadkin ", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.10.4", - "jest-worker": "^26.2.1", - "serialize-javascript": "^4.0.0", - "terser": "^5.0.0" + "@babel/code-frame": "^7.18.6", + "jest-worker": "^29.1.2", + "serialize-javascript": "^6.0.0", + "terser": "^5.15.1" }, "peerDependencies": { - "rollup": "^2.0.0" + "rollup": ">=2.0.0" }, "devDependencies": { - "@babel/core": "^7.11.1", - "jest": "^26.2.2", - "prettier": "^2.0.5", - "rollup": "^2.23.1" + "@babel/core": "^7.19.3", + "jest": "^29.1.2", + "prettier": "^2.7.1", + "rollup": ">=2.0.0" } } diff --git a/rollup-plugin-terser.js b/rollup-plugin-terser.js index 58b7684..d3f9190 100644 --- a/rollup-plugin-terser.js +++ b/rollup-plugin-terser.js @@ -1,5 +1,9 @@ -const { codeFrameColumns } = require("@babel/code-frame"); -const Worker = require("jest-worker").default; +const { + codeFrameColumns +} = require("@babel/code-frame"); +const { + Worker +} = require("jest-worker"); const serialize = require("serialize-javascript"); function terser(userOptions = {}) { @@ -28,8 +32,7 @@ function terser(userOptions = {}) { this.numOfBundles++; const defaultOptions = { - sourceMap: - outputOptions.sourcemap === true || + sourceMap: outputOptions.sourcemap === true || typeof outputOptions.sourcemap === "string", }; if (outputOptions.format === "es" || outputOptions.format === "esm") { @@ -39,7 +42,10 @@ function terser(userOptions = {}) { defaultOptions.toplevel = true; } - const normalizedOptions = { ...defaultOptions, ...userOptions }; + const normalizedOptions = { + ...defaultOptions, + ...userOptions + }; // remove plugin specific options for (let key of ["numWorkers"]) { @@ -54,7 +60,10 @@ function terser(userOptions = {}) { const result = await this.worker.transform(code, serializedOptions); if (result.nameCache) { - let { vars, props } = userOptions.nameCache; + let { + vars, + props + } = userOptions.nameCache; // only assign nameCache.vars if it was provided, and if terser produced values: if (vars) { @@ -82,9 +91,20 @@ function terser(userOptions = {}) { return result.result; } catch (error) { - const { message, line, col: column } = error; + const { + message, + line, + col: column + } = error; console.error( - codeFrameColumns(code, { start: { line, column } }, { message }) + codeFrameColumns(code, { + start: { + line, + column + } + }, { + message + }) ); throw error; } finally { @@ -99,4 +119,4 @@ function terser(userOptions = {}) { }; } -exports.terser = terser; +exports.terser = terser; \ No newline at end of file diff --git a/test/__snapshots__/test.js.snap b/test/__snapshots__/test.js.snap index 8cf7e1c..9efa6e3 100644 --- a/test/__snapshots__/test.js.snap +++ b/test/__snapshots__/test.js.snap @@ -1,37 +1,37 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - exports[`works with code splitting 1`] = ` -Object { - "chunk-1.js": Object { - "code": "console.log(\\"chunk-1\\"); +{ + "chunk-1.js": { + "code": "console.log(\"chunk-1\"); ", - "dynamicImports": Array [], - "exports": Array [], + "dynamicImports": [], + "exports": [], "fileName": "chunk-1.js", - "implicitlyLoadedBefore": Array [], - "imports": Array [], + "implicitlyLoadedBefore": [], + "importedBindings": {}, + "imports": [], "isDynamicEntry": false, "isEntry": true, "isImplicitEntry": false, "map": null, "name": "chunk-1", - "referencedFiles": Array [], + "referencedFiles": [], "type": "chunk", }, - "chunk-2.js": Object { - "code": "console.log(\\"chunk-2\\"); + "chunk-2.js": { + "code": "console.log(\"chunk-2\"); ", - "dynamicImports": Array [], - "exports": Array [], + "dynamicImports": [], + "exports": [], "fileName": "chunk-2.js", - "implicitlyLoadedBefore": Array [], - "imports": Array [], + "implicitlyLoadedBefore": [], + "importedBindings": {}, + "imports": [], "isDynamicEntry": false, "isEntry": true, "isImplicitEntry": false, "map": null, "name": "chunk-2", - "referencedFiles": Array [], + "referencedFiles": [], "type": "chunk", }, } diff --git a/test/test.js b/test/test.js index 9fb2a6c..2dfceed 100644 --- a/test/test.js +++ b/test/test.js @@ -1,12 +1,18 @@ -const { rollup } = require("rollup"); -const { terser } = require("../"); +const { + rollup +} = require("rollup"); +const { + terser +} = require("../"); test("minify", async () => { const bundle = await rollup({ input: "test/fixtures/unminified.js", plugins: [terser()], }); - const result = await bundle.generate({ format: "cjs" }); + const result = await bundle.generate({ + format: "cjs" + }); expect(result.output).toHaveLength(1); const [output] = result.output; expect(output.code).toEqual( @@ -18,7 +24,11 @@ test("minify", async () => { test("minify via terser options", async () => { const bundle = await rollup({ input: "test/fixtures/empty.js", - plugins: [terser({ output: { comments: "all" } })], + plugins: [terser({ + output: { + comments: "all" + } + })], }); const result = await bundle.generate({ banner: "/* package name */", @@ -37,8 +47,12 @@ test("minify multiple outputs", async () => { }); const [bundle1, bundle2] = await Promise.all([ - bundle.generate({ format: "cjs" }), - bundle.generate({ format: "es" }), + bundle.generate({ + format: "cjs" + }), + bundle.generate({ + format: "es" + }), ]); const [output1] = bundle1.output; const [output2] = bundle2.output; @@ -54,7 +68,9 @@ test("minify esm module", async () => { input: "test/fixtures/plain-file.js", plugins: [terser()], }); - const result = await bundle.generate({ format: "esm" }); + const result = await bundle.generate({ + format: "esm" + }); expect(result.output).toHaveLength(1); const [output] = result.output; expect(output.code).toEqual('console.log("bar");\n'); @@ -63,9 +79,13 @@ test("minify esm module", async () => { test("minify esm module with disabled module option", async () => { const bundle = await rollup({ input: "test/fixtures/plain-file.js", - plugins: [terser({ module: false })], + plugins: [terser({ + module: false + })], + }); + const result = await bundle.generate({ + format: "esm" }); - const result = await bundle.generate({ format: "esm" }); expect(result.output).toHaveLength(1); const [output] = result.output; expect(output.code).toEqual('const foo="bar";console.log(foo);\n'); @@ -76,7 +96,9 @@ test("minify cjs module", async () => { input: "test/fixtures/plain-file.js", plugins: [terser()], }); - const result = await bundle.generate({ format: "cjs" }); + const result = await bundle.generate({ + format: "cjs" + }); expect(result.output).toHaveLength(1); const [output] = result.output; expect(output.code).toEqual('"use strict";console.log("bar");\n'); @@ -85,9 +107,13 @@ test("minify cjs module", async () => { test("minify cjs module with disabled toplevel option", async () => { const bundle = await rollup({ input: "test/fixtures/plain-file.js", - plugins: [terser({ toplevel: false })], + plugins: [terser({ + toplevel: false + })], + }); + const result = await bundle.generate({ + format: "cjs" }); - const result = await bundle.generate({ format: "cjs" }); expect(result.output).toHaveLength(1); const [output] = result.output; expect(output.code).toEqual( @@ -100,22 +126,25 @@ test("minify with sourcemaps", async () => { input: "test/fixtures/sourcemap.js", plugins: [terser()], }); - const result = await bundle.generate({ format: "cjs", sourcemap: true }); - expect(result.output).toHaveLength(1); + const result = await bundle.generate({ + format: "cjs", + sourcemap: true + }); + expect(result.output).toHaveLength(2); const [output] = result.output; expect(output.map).toMatchInlineSnapshot(` SourceMap { "file": "sourcemap.js", "mappings": "aAEAA,QAAQC,ICFO", - "names": Array [ + "names": [ "console", "log", ], - "sources": Array [ + "sources": [ "test/fixtures/sourcemap.js", "test/fixtures/export-number.js", ], - "sourcesContent": Array [ + "sourcesContent": [ "import result from './export-number.js'; console.log(result); @@ -133,22 +162,25 @@ test('work with sourcemap: "inline"', async () => { input: "test/fixtures/sourcemap.js", plugins: [terser()], }); - const result = await bundle.generate({ format: "cjs", sourcemap: "inline" }); + const result = await bundle.generate({ + format: "cjs", + sourcemap: "inline" + }); expect(result.output).toHaveLength(1); const [output] = result.output; expect(output.map).toMatchInlineSnapshot(` SourceMap { "file": "sourcemap.js", "mappings": "aAEAA,QAAQC,ICFO", - "names": Array [ + "names": [ "console", "log", ], - "sources": Array [ + "sources": [ "test/fixtures/sourcemap.js", "test/fixtures/export-number.js", ], - "sourcesContent": Array [ + "sourcesContent": [ "import result from './export-number.js'; console.log(result); @@ -165,7 +197,9 @@ test("does not allow to pass sourcemap option", async () => { try { const bundle = await rollup({ input: "test/fixtures/sourcemap.js", - plugins: [terser({ sourcemap: false })], + plugins: [terser({ + sourcemap: false + })], }); expect(true).toBeFalsy(); } catch (error) { @@ -177,7 +211,9 @@ test("does not allow to pass sourceMap option", async () => { try { const bundle = await rollup({ input: "test/fixtures/sourcemap.js", - plugins: [terser({ sourceMap: false })], + plugins: [terser({ + sourceMap: false + })], }); expect(true).toBeFalsy(); } catch (error) { @@ -189,14 +225,17 @@ test("throw error on terser fail", async () => { try { const bundle = await rollup({ input: "test/fixtures/failed.js", - plugins: [ - { - renderChunk: () => ({ code: "var = 1" }), + plugins: [{ + renderChunk: () => ({ + code: "var = 1" + }), }, terser(), ], }); - await bundle.generate({ format: "esm" }); + await bundle.generate({ + format: "esm" + }); expect(true).toBeFalsy(); } catch (error) { expect(error.toString()).toMatch(/Name expected/); @@ -207,16 +246,21 @@ test("throw error on terser fail with multiple outputs", async () => { try { const bundle = await rollup({ input: "test/fixtures/failed.js", - plugins: [ - { - renderChunk: () => ({ code: "var = 1" }), + plugins: [{ + renderChunk: () => ({ + code: "var = 1" + }), }, terser(), ], }); await Promise.all([ - bundle.generate({ format: "cjs" }), - bundle.generate({ format: "esm" }), + bundle.generate({ + format: "cjs" + }), + bundle.generate({ + format: "esm" + }), ]); expect(true).toBeFalsy(); } catch (error) { @@ -229,13 +273,18 @@ test("works with code splitting", async () => { input: ["test/fixtures/chunk-1.js", "test/fixtures/chunk-2.js"], plugins: [terser()], }); - const { output } = await bundle.generate({ format: "esm" }); + const { + output + } = await bundle.generate({ + format: "esm" + }); const newOutput = {}; output.forEach((out) => { // TODO rewrite with object rest after node 6 dropping const value = Object.assign({}, out); delete value.modules; delete value.facadeModuleId; + delete value.moduleIds; newOutput[out.fileName] = value; }); expect(newOutput).toMatchSnapshot(); @@ -244,9 +293,17 @@ test("works with code splitting", async () => { test("allow to pass not string values to worker", async () => { const bundle = await rollup({ input: "test/fixtures/unminified.js", - plugins: [terser({ mangle: { properties: { regex: /^_/ } } })], + plugins: [terser({ + mangle: { + properties: { + regex: /^_/ + } + } + })], + }); + const result = await bundle.generate({ + format: "cjs" }); - const result = await bundle.generate({ format: "cjs" }); expect(result.output).toHaveLength(1); const [output] = result.output; expect(output.code).toEqual( @@ -259,7 +316,11 @@ test("allow classic function definitions passing to worker", async () => { input: "test/fixtures/commented.js", plugins: [ terser({ - mangle: { properties: { regex: /^_/ } }, + mangle: { + properties: { + regex: /^_/ + } + }, output: { comments: function (node, comment) { if (comment.type === "comment2") { @@ -272,7 +333,10 @@ test("allow classic function definitions passing to worker", async () => { }), ], }); - const result = await bundle.generate({ format: "cjs", compact: true }); + const result = await bundle.generate({ + format: "cjs", + compact: true + }); expect(result.output).toHaveLength(1); const [output] = result.output; expect(output.code).toEqual( @@ -285,7 +349,11 @@ test("allow method shorthand definitions passing to worker", async () => { input: "test/fixtures/commented.js", plugins: [ terser({ - mangle: { properties: { regex: /^_/ } }, + mangle: { + properties: { + regex: /^_/ + } + }, output: { comments(node, comment) { if (comment.type === "comment2") { @@ -298,7 +366,10 @@ test("allow method shorthand definitions passing to worker", async () => { }), ], }); - const result = await bundle.generate({ format: "cjs", compact: true }); + const result = await bundle.generate({ + format: "cjs", + compact: true + }); expect(result.output).toHaveLength(1); const [output] = result.output; expect(output.code).toEqual( @@ -311,7 +382,11 @@ test("allow arrow function definitions passing to worker", async () => { input: "test/fixtures/unminified.js", plugins: [ terser({ - mangle: { properties: { regex: /^_/ } }, + mangle: { + properties: { + regex: /^_/ + } + }, output: { comments: (node, comment) => { if (comment.type === "comment2") { @@ -324,7 +399,9 @@ test("allow arrow function definitions passing to worker", async () => { }), ], }); - const result = await bundle.generate({ format: "cjs" }); + const result = await bundle.generate({ + format: "cjs" + }); expect(result.output).toHaveLength(1); const [output] = result.output; expect(output.code).toEqual( @@ -335,9 +412,17 @@ test("allow arrow function definitions passing to worker", async () => { test("allow to pass not string values to worker", async () => { const bundle = await rollup({ input: "test/fixtures/unminified.js", - plugins: [terser({ mangle: { properties: { regex: /^_/ } } })], + plugins: [terser({ + mangle: { + properties: { + regex: /^_/ + } + } + })], + }); + const result = await bundle.generate({ + format: "cjs" }); - const result = await bundle.generate({ format: "cjs" }); expect(result.output[0].code).toEqual( '"use strict";window.a=5,window.a<3&&console.log(4);\n' ); @@ -364,7 +449,9 @@ test("terser accepts the nameCache option", async () => { }), ], }); - const result = await bundle.generate({ format: "es" }); + const result = await bundle.generate({ + format: "es" + }); expect(result.output[0].code.trim()).toEqual( `console.log({foo:1,custom:2});` ); @@ -392,7 +479,9 @@ test("terser updates the nameCache object", async () => { }), ], }); - const result = await bundle.generate({ format: "es" }); + const result = await bundle.generate({ + format: "es" + }); expect(result.output[0].code.trim()).toEqual(`console.log({o:1,f:2});`); expect(nameCache.props).toBe(props); expect(nameCache).toEqual({ @@ -420,7 +509,9 @@ test("omits populates an empty nameCache object", async () => { }), ], }); - const result = await bundle.generate({ format: "es" }); + const result = await bundle.generate({ + format: "es" + }); expect(result.output[0].code.trim()).toEqual( `console.log({o:1,i:2},function o(n){return n>0?o(n-1):n}(10));` ); @@ -455,7 +546,9 @@ test("terser preserve vars in nameCache when provided", async () => { }), ], }); - const result = await bundle.generate({ format: "es" }); + const result = await bundle.generate({ + format: "es" + }); expect(result.output[0].code.trim()).toEqual( `console.log({o:1,i:2},function o(n){return n>0?o(n-1):n}(10));` ); @@ -470,4 +563,4 @@ test("terser preserve vars in nameCache when provided", async () => { props: {}, }, }); -}); +}); \ No newline at end of file