From 3d21c043c11436dfe843aa1afc8db7db2bbcb699 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Fri, 22 Feb 2019 13:21:12 -0500 Subject: [PATCH] Make --define preserve boolean and integer literals by default instead of making everything a string. --- src/index.js | 39 ++++++++++++++++++++++++--- test/__snapshots__/index.test.js.snap | 22 +++++++++++++++ test/fixtures/define/index.js | 6 +++++ test/fixtures/define/package.json | 6 +++++ 4 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 test/fixtures/define/index.js create mode 100644 test/fixtures/define/package.json diff --git a/src/index.js b/src/index.js index 75cae80..3dd0d98 100644 --- a/src/index.js +++ b/src/index.js @@ -26,12 +26,40 @@ import camelCase from 'camelcase'; const removeScope = name => name.replace(/^@.*\//, ''); +// Convert booleans and int define= values to literals. +// This is more intuitive than `microbundle --define A=1` producing A="1". +// See: https://github.com/terser-js/terser#conditional-compilation-api +const toTerserLiteral = (value, name) => { + // --define A="1",B='true' produces string: + const matches = value.match(/^(['"])(.+)\1$/); + if (matches) { + return [matches[2], name]; + } + + // --define A=1,B=true produces int/boolean literal: + if (/^(true|false|\d+)$/i.test(value)) { + return [value, '@' + name]; + } + + // default: behaviour from Terser (@prefix=1 produces expression/literal, unprefixed=1 produces string literal): +}; + // Parses values of the form "$=jQuery,React=react" into key-value object pairs. -const parseMappingArgument = globalStrings => { +const parseMappingArgument = (globalStrings, processValue) => { const globals = {}; globalStrings.split(',').forEach(globalString => { - const [localName, globalName] = globalString.split('='); - globals[localName] = globalName; + let [key, value] = globalString.split('='); + if (processValue) { + const r = processValue(value, key); + if (r !== undefined) { + if (Array.isArray(r)) { + [value, key] = r; + } else { + value = r; + } + } + } + globals[key] = value; }); return globals; }; @@ -325,7 +353,10 @@ function createConfig(options, entry, format, writeMeta) { let defines = {}; if (options.define) { - defines = Object.assign(defines, parseMappingArgument(options.define)); + defines = Object.assign( + defines, + parseMappingArgument(options.define, toTerserLiteral), + ); } function replaceName(filename, name) { diff --git a/test/__snapshots__/index.test.js.snap b/test/__snapshots__/index.test.js.snap index f75d96c..9e983a7 100644 --- a/test/__snapshots__/index.test.js.snap +++ b/test/__snapshots__/index.test.js.snap @@ -753,6 +753,28 @@ exports[`fixtures default-named 6`] = ` exports[`fixtures default-named 7`] = `"{\\"version\\":3,\\"file\\":\\"default-named.umd.js\\",\\"sources\\":[\\"../src/index.js\\"],\\"sourcesContent\\":[\\"export const foo = 42;\\\\nexport default function bar() {}\\\\n\\"],\\"names\\":[],\\"mappings\\":\\"wLAAmB,aACJ\\"}"`; +exports[`fixtures define 1`] = ` +"Used script: microbundle --no-sourcemap -f cjs --define DEBUG=false + +Directory tree: + +define + dist + alias.js + index.js + package.json + + +Build \\"alias\\" to dist: +50 B: alias.js.gz +34 B: alias.js.br" +`; + +exports[`fixtures define 2`] = ` +"console.log(\\"debug mode\\",!1); +" +`; + exports[`fixtures esnext-ts 1`] = ` "Used script: microbundle --raw diff --git a/test/fixtures/define/index.js b/test/fixtures/define/index.js new file mode 100644 index 0000000..76be8f9 --- /dev/null +++ b/test/fixtures/define/index.js @@ -0,0 +1,6 @@ +const DEBUG = true; +if (DEBUG) { + console.log('debug mode', DEBUG); +} else { + console.log('production mode', DEBUG); +} diff --git a/test/fixtures/define/package.json b/test/fixtures/define/package.json new file mode 100644 index 0000000..0edf4dd --- /dev/null +++ b/test/fixtures/define/package.json @@ -0,0 +1,6 @@ +{ + "name": "alias", + "scripts": { + "build": "microbundle --no-sourcemap -f cjs --define DEBUG=false" + } +}