diff --git a/.changeset/metal-olives-play.md b/.changeset/metal-olives-play.md new file mode 100644 index 00000000..f19f1c90 --- /dev/null +++ b/.changeset/metal-olives-play.md @@ -0,0 +1,5 @@ +--- +'microbundle': minor +--- + +Fix problems related to use terser nameCache diff --git a/src/index.js b/src/index.js index a913c3b0..51573d0f 100644 --- a/src/index.js +++ b/src/index.js @@ -111,12 +111,7 @@ export default async function microbundle(inputOptions) { for (let i = 0; i < options.entries.length; i++) { for (let j = 0; j < formats.length; j++) { steps.push( - createConfig( - options, - options.entries[i], - formats[j], - i === 0 && j === 0, - ), + createConfig(options, options.entries[i], formats[j], j === 0), ); } } @@ -390,15 +385,15 @@ function createConfig(options, entry, format, writeMeta) { // let rollupName = safeVariableName(basename(entry).replace(/\.js$/, '')); - let nameCache = {}; - const bareNameCache = nameCache; // Support "minify" field and legacy "mangle" field via package.json: const rawMinifyValue = options.pkg.minify || options.pkg.mangle || {}; - let minifyOptions = typeof rawMinifyValue === 'string' ? {} : rawMinifyValue; const getNameCachePath = typeof rawMinifyValue === 'string' ? () => resolve(options.cwd, rawMinifyValue) : () => resolve(options.cwd, 'mangle.json'); + let minifyOptions = typeof rawMinifyValue === 'string' ? {} : rawMinifyValue; + let endsWithNewLine = false; + let terserOptions = {}; const useTypescript = extname(entry) === '.ts' || extname(entry) === '.tsx'; const emitDeclaration = @@ -415,29 +410,6 @@ function createConfig(options, entry, format, writeMeta) { const externalTest = external.length === 0 ? id => false : id => externalPredicate.test(id); - let endsWithNewLine = false; - - function loadNameCache() { - try { - const data = fs.readFileSync(getNameCachePath(), 'utf8'); - endsWithNewLine = data.endsWith(EOL); - nameCache = JSON.parse(data); - // mangle.json can contain a "minify" field, same format as the pkg.mangle: - if (nameCache.minify) { - minifyOptions = Object.assign( - {}, - minifyOptions || {}, - nameCache.minify, - ); - } - } catch (e) {} - } - loadNameCache(); - - normalizeMinifyOptions(minifyOptions); - - if (nameCache === bareNameCache) nameCache = null; - /** @type {false | import('rollup').RollupCache} */ let cache; if (modern) cache = false; @@ -601,43 +573,79 @@ function createConfig(options, entry, format, writeMeta) { }, }), options.compress !== false && [ - terser({ - compress: Object.assign( - { - keep_infinity: true, - pure_getters: true, - // Ideally we'd just get Terser to respect existing Arrow functions... - // unsafe_arrows: true, - passes: 10, - }, - typeof minifyOptions.compress === 'boolean' - ? minifyOptions.compress - : minifyOptions.compress || {}, - ), - format: { - // By default, Terser wraps function arguments in extra parens to trigger eager parsing. - // Whether this is a good idea is way too specific to guess, so we optimize for size by default: - wrap_func_args: false, - comments: /^\s*([@#]__[A-Z]+__\s*$|@cc_on)/, - preserve_annotations: true, - }, - module: modern, - ecma: modern ? 2017 : 5, - toplevel: modern || format === 'cjs' || format === 'es', - mangle: - typeof minifyOptions.mangle === 'boolean' - ? minifyOptions.mangle - : Object.assign({}, minifyOptions.mangle || {}), - nameCache, - }), - nameCache && { + terser(terserOptions), + { // before hook - options: loadNameCache, + options() { + let nameCache = {}; + const bareNameCache = nameCache; + + function loadNameCache() { + try { + const data = fs.readFileSync(getNameCachePath(), 'utf8'); + endsWithNewLine = data.endsWith(EOL); + nameCache = JSON.parse(data); + // mangle.json can contain a "minify" field, same format as the pkg.mangle: + if (nameCache.minify) { + minifyOptions = Object.assign( + {}, + minifyOptions || {}, + nameCache.minify, + ); + } + } catch (e) {} + } + loadNameCache(); + + normalizeMinifyOptions(minifyOptions); + + if (nameCache === bareNameCache) nameCache = null; + + Object.entries({ + compress: Object.assign( + { + keep_infinity: true, + pure_getters: true, + // Ideally we'd just get Terser to respect existing Arrow functions... + // unsafe_arrows: true, + passes: 10, + }, + typeof minifyOptions.compress === 'boolean' + ? minifyOptions.compress + : minifyOptions.compress || {}, + ), + format: { + // By default, Terser wraps function arguments in extra parens to trigger eager parsing. + // Whether this is a good idea is way too specific to guess, so we optimize for size by default: + wrap_func_args: false, + comments: /^\s*([@#]__[A-Z]+__\s*$|@cc_on)/, + preserve_annotations: true, + }, + module: modern, + ecma: modern ? 2017 : 5, + toplevel: modern || format === 'cjs' || format === 'es', + mangle: + typeof minifyOptions.mangle === 'boolean' + ? minifyOptions.mangle + : Object.assign({}, minifyOptions.mangle || {}), + nameCache, + }).forEach(([key, value]) => { + terserOptions[key] = value; + }); + }, // after hook writeBundle() { - if (writeMeta && nameCache) { + if (writeMeta && terserOptions.nameCache) { + try { + if ( + terserOptions.nameCache.minify.mangle.properties.regex + ) { + terserOptions.nameCache.minify.mangle.properties.regex = + terserOptions.nameCache.minify.mangle.properties.regex.source; + } + } catch (error) {} let filename = getNameCachePath(); - let json = JSON.stringify(nameCache, null, 2); + let json = JSON.stringify(terserOptions.nameCache, null, 2); if (endsWithNewLine) json += EOL; fs.writeFile(filename, json, () => {}); } diff --git a/test/__snapshots__/index.test.js.snap b/test/__snapshots__/index.test.js.snap index 0e44f6ea..ab3054e7 100644 --- a/test/__snapshots__/index.test.js.snap +++ b/test/__snapshots__/index.test.js.snap @@ -2147,6 +2147,87 @@ exports[`fixtures build modern-generators with microbundle 6`] = ` " `; +exports[`fixtures build multi-source-mangle-json-file with microbundle 1`] = ` +"Used script: microbundle + +Directory tree: + +multi-source-mangle-json-file + dist + a.esm.mjs + a.esm.mjs.map + a.js + a.js.map + a.umd.js + a.umd.js.map + b.esm.mjs + b.esm.mjs.map + b.js + b.js.map + b.umd.js + b.umd.js.map + mangle.json + package.json + src + a.js + a_prop.js + b.js + b_prop.js + + +Build \\"multi-source-mangle-json-file\\" to dist: +110 B: a.js.gz +76 B: a.js.br +112 B: a.esm.mjs.gz +84 B: a.esm.mjs.br +212 B: a.umd.js.gz +173 B: a.umd.js.br +107 B: b.js.gz +95 B: b.js.br +110 B: b.esm.mjs.gz +100 B: b.esm.mjs.br +209 B: b.umd.js.gz +170 B: b.umd.js.br" +`; + +exports[`fixtures build multi-source-mangle-json-file with microbundle 2`] = `12`; + +exports[`fixtures build multi-source-mangle-json-file with microbundle 3`] = ` +"var o={prop1:1,__p2:2,o:4};function p(){return console.log(o.prop1),console.log(o.__p2),console.log(o.o),o}export default p; +//# sourceMappingURL=a.esm.mjs.map +" +`; + +exports[`fixtures build multi-source-mangle-json-file with microbundle 4`] = ` +"var o={prop1:1,__p2:2,o:4};module.exports=function(){return console.log(o.prop1),console.log(o.__p2),console.log(o.o),o}; +//# sourceMappingURL=a.js.map +" +`; + +exports[`fixtures build multi-source-mangle-json-file with microbundle 5`] = ` +"!function(e,o){\\"object\\"==typeof exports&&\\"undefined\\"!=typeof module?module.exports=o():\\"function\\"==typeof define&&define.amd?define(o):(e||self).multiSourceMangleJsonFile=o()}(this,function(){var e={prop1:1,__p2:2,o:4};return function(){return console.log(e.prop1),console.log(e.__p2),console.log(e.o),e}}); +//# sourceMappingURL=a.umd.js.map +" +`; + +exports[`fixtures build multi-source-mangle-json-file with microbundle 6`] = ` +"var o={prop1:1,__p2:2,p:3};function p(){return console.log(o.prop1),console.log(o.__p2),o}export default p; +//# sourceMappingURL=b.esm.mjs.map +" +`; + +exports[`fixtures build multi-source-mangle-json-file with microbundle 7`] = ` +"var o={prop1:1,__p2:2,p:3};module.exports=function(){return console.log(o.prop1),console.log(o.__p2),o}; +//# sourceMappingURL=b.js.map +" +`; + +exports[`fixtures build multi-source-mangle-json-file with microbundle 8`] = ` +"!function(e,o){\\"object\\"==typeof exports&&\\"undefined\\"!=typeof module?module.exports=o():\\"function\\"==typeof define&&define.amd?define(o):(e||self).multiSourceMangleJsonFile=o()}(this,function(){var e={prop1:1,__p2:2,p:3};return function(){return console.log(e.prop1),console.log(e.__p2),e}}); +//# sourceMappingURL=b.umd.js.map +" +`; + exports[`fixtures build name-custom-amd with microbundle 1`] = ` "Used script: microbundle diff --git a/test/fixtures/mangle-json-file/mangle.json b/test/fixtures/mangle-json-file/mangle.json index f95de54f..d8003ddc 100644 --- a/test/fixtures/mangle-json-file/mangle.json +++ b/test/fixtures/mangle-json-file/mangle.json @@ -2,7 +2,8 @@ "minify": { "mangle": { "properties": { - "regex": "^_" + "regex": "^_", + "reserved": [] } } }, diff --git a/test/fixtures/minify-path-config/minify.json b/test/fixtures/minify-path-config/minify.json index f95de54f..d8003ddc 100644 --- a/test/fixtures/minify-path-config/minify.json +++ b/test/fixtures/minify-path-config/minify.json @@ -2,7 +2,8 @@ "minify": { "mangle": { "properties": { - "regex": "^_" + "regex": "^_", + "reserved": [] } } }, diff --git a/test/fixtures/minify-path-parent-dir-with-cwd/minify.json b/test/fixtures/minify-path-parent-dir-with-cwd/minify.json index f95de54f..d8003ddc 100644 --- a/test/fixtures/minify-path-parent-dir-with-cwd/minify.json +++ b/test/fixtures/minify-path-parent-dir-with-cwd/minify.json @@ -2,7 +2,8 @@ "minify": { "mangle": { "properties": { - "regex": "^_" + "regex": "^_", + "reserved": [] } } }, diff --git a/test/fixtures/multi-source-mangle-json-file/mangle.json b/test/fixtures/multi-source-mangle-json-file/mangle.json new file mode 100644 index 00000000..50bda52d --- /dev/null +++ b/test/fixtures/multi-source-mangle-json-file/mangle.json @@ -0,0 +1,17 @@ +{ + "minify": { + "mangle": { + "properties": { + "regex": "^_", + "reserved": [] + } + } + }, + "props": { + "props": { + "$_prop2": "__p2", + "$_prop4": "o", + "$_prop3": "p" + } + } +} diff --git a/test/fixtures/multi-source-mangle-json-file/package.json b/test/fixtures/multi-source-mangle-json-file/package.json new file mode 100644 index 00000000..02e98cbe --- /dev/null +++ b/test/fixtures/multi-source-mangle-json-file/package.json @@ -0,0 +1,7 @@ +{ + "name": "multi-source-mangle-json-file", + "source":[ + "./src/a.js", + "./src/b.js" + ] +} diff --git a/test/fixtures/multi-source-mangle-json-file/src/a.js b/test/fixtures/multi-source-mangle-json-file/src/a.js new file mode 100644 index 00000000..6fadbf62 --- /dev/null +++ b/test/fixtures/multi-source-mangle-json-file/src/a.js @@ -0,0 +1,8 @@ +import { obj } from './a_prop'; + +export default function () { + console.log(obj.prop1); + console.log(obj._prop2); + console.log(obj._prop4); + return obj; +} diff --git a/test/fixtures/multi-source-mangle-json-file/src/a_prop.js b/test/fixtures/multi-source-mangle-json-file/src/a_prop.js new file mode 100644 index 00000000..95464feb --- /dev/null +++ b/test/fixtures/multi-source-mangle-json-file/src/a_prop.js @@ -0,0 +1,5 @@ +export const obj = { + prop1: 1, + _prop2: 2, + _prop4: 4, +}; diff --git a/test/fixtures/multi-source-mangle-json-file/src/b.js b/test/fixtures/multi-source-mangle-json-file/src/b.js new file mode 100644 index 00000000..75ff3fe7 --- /dev/null +++ b/test/fixtures/multi-source-mangle-json-file/src/b.js @@ -0,0 +1,7 @@ +import { obj } from './b_prop'; + +export default function () { + console.log(obj.prop1); + console.log(obj._prop2); + return obj; +} diff --git a/test/fixtures/multi-source-mangle-json-file/src/b_prop.js b/test/fixtures/multi-source-mangle-json-file/src/b_prop.js new file mode 100644 index 00000000..b94223a1 --- /dev/null +++ b/test/fixtures/multi-source-mangle-json-file/src/b_prop.js @@ -0,0 +1,5 @@ +export const obj = { + prop1: 1, + _prop2: 2, + _prop3: 3, +}; diff --git a/test/fixtures/terser-annotations/mangle.json b/test/fixtures/terser-annotations/mangle.json index 1893c2de..331f3d31 100644 --- a/test/fixtures/terser-annotations/mangle.json +++ b/test/fixtures/terser-annotations/mangle.json @@ -3,5 +3,6 @@ "mangle": { "keep_fnames": true } - } + }, + "props": {} } \ No newline at end of file