diff --git a/index.js b/index.js index 23f2f6b..80ed117 100644 --- a/index.js +++ b/index.js @@ -1,20 +1,22 @@ const { codeFrameColumns } = require("@babel/code-frame"); const Worker = require("jest-worker").default; const serialize = require("serialize-javascript"); -const { createFilter } = require('rollup-pluginutils'); +const { createFilter } = require("rollup-pluginutils"); function terser(userOptions = {}) { if (userOptions.sourceMap != null) { throw Error("sourceMap option is removed, use sourcemap instead"); } - const filter = createFilter( userOptions.include, userOptions.exclude, { resolve: false } ); + const filter = createFilter(userOptions.include, userOptions.exclude, { + resolve: false + }); return { name: "terser", renderChunk(code, chunk, outputOptions) { - if(!filter(chunk.fileName)){ + if (!filter(chunk.fileName)) { return null; } @@ -27,12 +29,20 @@ function terser(userOptions = {}) { this.numOfBundles++; - // TODO rewrite with object spread after node6 drop - const normalizedOptions = Object.assign({}, userOptions, { - sourceMap: userOptions.sourcemap !== false, - module: outputOptions.format === "es" || outputOptions.format === "esm" - }); + const defaultOptions = { + sourceMap: userOptions.sourcemap !== false + }; + if (outputOptions.format === "es" || outputOptions.format === "esm") { + defaultOptions.module = true; + } + if (outputOptions.format === "cjs") { + defaultOptions.toplevel = true; + } + + // TODO rewrite with object spread after dropping node v6 + const normalizedOptions = Object.assign({}, defaultOptions, userOptions); + // remove plugin specific options for (let key of ["include", "exclude", "sourcemap", "numWorkers"]) { if (normalizedOptions.hasOwnProperty(key)) { delete normalizedOptions[key]; @@ -68,7 +78,8 @@ function terser(userOptions = {}) { // only assign nameCache.vars if it was provided, and if terser produced values: if (vars) { - const newVars = result.nameCache.vars && result.nameCache.vars.props; + const newVars = + result.nameCache.vars && result.nameCache.vars.props; if (newVars) { vars.props = vars.props || {}; Object.assign(vars.props, newVars); @@ -81,14 +92,15 @@ function terser(userOptions = {}) { } // merge updated props into original nameCache object: - const newProps = result.nameCache.props && result.nameCache.props.props; + const newProps = + result.nameCache.props && result.nameCache.props.props; if (newProps) { props.props = props.props || {}; Object.assign(props.props, newProps); } } - return result.result + return result.result; }); } }; diff --git a/package.json b/package.json index 67e5d17..3693d83 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "@babel/plugin-transform-async-to-generator": "^7.5.0", "babel-jest": "^24.8.0", "jest": "^24.8.0", - "prettier": "^1.18.2", + "prettier": "^1.19.1", "rollup": "^1.27.10" } } diff --git a/test/test.js b/test/test.js index f68103b..c00c76f 100644 --- a/test/test.js +++ b/test/test.js @@ -49,7 +49,7 @@ test("minify multiple outputs", async () => { expect(output2.code).toEqual("window.a=5,window.a<3&&console.log(4);\n"); }); -test("minify module", async () => { +test("minify esm module", async () => { const bundle = await rollup({ input: "test/fixtures/plain-file.js", plugins: [terser()] @@ -60,6 +60,41 @@ test("minify module", async () => { expect(output.code).toEqual('console.log("bar");\n'); }); +test("minify esm module with disabled module option", async () => { + const bundle = await rollup({ + input: "test/fixtures/plain-file.js", + plugins: [terser({ module: false })] + }); + 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'); +}); + +test("minify cjs module", async () => { + const bundle = await rollup({ + input: "test/fixtures/plain-file.js", + plugins: [terser()] + }); + 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'); +}); + +test("minify cjs module with disabled toplevel option", async () => { + const bundle = await rollup({ + input: "test/fixtures/plain-file.js", + plugins: [terser({ toplevel: false })] + }); + const result = await bundle.generate({ format: "cjs" }); + expect(result.output).toHaveLength(1); + const [output] = result.output; + expect(output.code).toEqual( + '"use strict";const foo="bar";console.log(foo);\n' + ); +}); + test("minify with sourcemaps", async () => { const bundle = await rollup({ input: "test/fixtures/sourcemap.js", @@ -167,7 +202,7 @@ test("allow classic function definitions passing to worker", async () => { terser({ mangle: { properties: { regex: /^_/ } }, output: { - comments: function (node, comment) { + comments: function(node, comment) { if (comment.type === "comment2") { // multiline comment return /@preserve|@license|@cc_on|^!/i.test(comment.value); @@ -252,10 +287,10 @@ test("allow to pass not string values to worker", async () => { test("include chunk file by string name", async () => { const bundle = await rollup({ input: "test/fixtures/unminified.js", - plugins: [ terser({ include: 'some.js' }) ] + plugins: [terser({ include: "some.js" })] }); - const result = await bundle.generate({ format: "es", file: 'some.js' }); + const result = await bundle.generate({ format: "es", file: "some.js" }); const { code, map } = result.output[0]; expect(code).toBe(`window.a=5,window.a<3&&console.log(4);\n`); expect(map).toBeFalsy(); @@ -264,19 +299,24 @@ test("include chunk file by string name", async () => { test("exclude chunk file pattern name by minimatch pattern", async () => { const bundle = await rollup({ input: "test/fixtures/unminified.js", - plugins: [ terser({ exclude: '*-cjs.js' }) ] + plugins: [terser({ exclude: "*-cjs.js" })] + }); + const result = await bundle.generate({ + format: "cjs", + entryFileNames: "[name]-[format].js" }); - const result = await bundle.generate({ format: "cjs", entryFileNames: '[name]-[format].js' }); const { code, map } = result.output[0]; - expect(code).toBe(`'use strict';\n\nwindow.a = 5;\n\nif (window.a < 3) {\n console.log(4);\n}\n`); + expect(code).toBe( + `'use strict';\n\nwindow.a = 5;\n\nif (window.a < 3) {\n console.log(4);\n}\n` + ); expect(map).toBeFalsy(); }); test("include only one chunk file by regex", async () => { const bundle = await rollup({ - input: [ "test/fixtures/chunk-1.js", "test/fixtures/chunk-2.js" ], - plugins: [ terser({ include: /.+-1\.\w+/ }) ] + input: ["test/fixtures/chunk-1.js", "test/fixtures/chunk-2.js"], + plugins: [terser({ include: /.+-1\.\w+/ })] }); const result = await bundle.generate({ format: "es" }); const { 0: chunk1, 1: chunk2 } = result.output; @@ -291,44 +331,50 @@ test("terser accepts the nameCache option", async () => { const nameCache = { props: { props: { - $_priv: 'custom' + $_priv: "custom" } } }; const bundle = await rollup({ input: "test/fixtures/properties.js", - plugins: [terser({ - mangle: { - properties: { - regex: /^_/ - } - }, - nameCache - })] + plugins: [ + terser({ + mangle: { + properties: { + regex: /^_/ + } + }, + nameCache + }) + ] }); const result = await bundle.generate({ format: "es" }); - expect(result.output[0].code.trim()).toEqual(`console.log({foo:1,custom:2});`); + expect(result.output[0].code.trim()).toEqual( + `console.log({foo:1,custom:2});` + ); }); test("terser updates the nameCache object", async () => { const nameCache = { props: { props: { - $_priv: 'f' + $_priv: "f" } } }; const props = nameCache.props; const bundle = await rollup({ input: "test/fixtures/properties.js", - plugins: [terser({ - mangle: { - properties: { - regex: /./ - } - }, - nameCache - })] + plugins: [ + terser({ + mangle: { + properties: { + regex: /./ + } + }, + nameCache + }) + ] }); const result = await bundle.generate({ format: "es" }); expect(result.output[0].code.trim()).toEqual(`console.log({o:1,f:2});`); @@ -336,8 +382,8 @@ test("terser updates the nameCache object", async () => { expect(nameCache).toEqual({ props: { props: { - $_priv: 'f', - $foo: 'o' + $_priv: "f", + $foo: "o" } } }); @@ -347,22 +393,26 @@ test("omits populates an empty nameCache object", async () => { const nameCache = {}; const bundle = await rollup({ input: "test/fixtures/properties-and-locals.js", - plugins: [terser({ - mangle: { - properties: { - regex: /./ - } - }, - nameCache - })] + plugins: [ + terser({ + mangle: { + properties: { + regex: /./ + } + }, + nameCache + }) + ] }); 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));`); + expect(result.output[0].code.trim()).toEqual( + `console.log({o:1,i:2},function o(n){return n>0?o(n-1):n}(10));` + ); expect(nameCache).toEqual({ props: { props: { - $_priv: 'i', - $foo: 'o' + $_priv: "i", + $foo: "o" } } }); @@ -378,22 +428,26 @@ test("terser preserve vars in nameCache when provided", async () => { }; const bundle = await rollup({ input: "test/fixtures/properties-and-locals.js", - plugins: [terser({ - mangle: { - properties: { - regex: /./ - } - }, - nameCache - })] + plugins: [ + terser({ + mangle: { + properties: { + regex: /./ + } + }, + nameCache + }) + ] }); 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));`); + expect(result.output[0].code.trim()).toEqual( + `console.log({o:1,i:2},function o(n){return n>0?o(n-1):n}(10));` + ); expect(nameCache).toEqual({ props: { props: { - $_priv: 'i', - $foo: 'o' + $_priv: "i", + $foo: "o" } }, vars: { @@ -401,4 +455,3 @@ test("terser preserve vars in nameCache when provided", async () => { } }); }); - diff --git a/yarn.lock b/yarn.lock index 92aaaed..5300d61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2676,10 +2676,10 @@ prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" -prettier@^1.18.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" - integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== +prettier@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== pretty-format@^24.8.0: version "24.8.0"