diff --git a/src/index.js b/src/index.js index 13bc4af1..e319029e 100644 --- a/src/index.js +++ b/src/index.js @@ -44,6 +44,31 @@ const toTerserLiteral = (value, name) => { // default: behaviour from Terser (@prefix=1 produces expression/literal, unprefixed=1 produces string literal): }; +// Normalize Terser options from microbundle's relaxed JSON format (mutates argument in-place) +function normalizeMinifyOptions(minifyOptions) { + const mangle = minifyOptions.mangle || (minifyOptions.mangle = {}); + let properties = mangle.properties; + + // allow top-level "properties" key to override mangle.properties (including {properties:false}): + if (minifyOptions.properties != null) { + properties = mangle.properties = + minifyOptions.properties && + Object.assign(properties, minifyOptions.properties); + } + + // allow previous format ({ mangle:{regex:'^_',reserved:[]} }): + if (minifyOptions.regex || minifyOptions.reserved) { + if (!properties) properties = mangle.properties = {}; + properties.regex = properties.regex || minifyOptions.regex; + properties.reserved = properties.reserved || minifyOptions.reserved; + } + + if (properties) { + if (properties.regex) properties.regex = new RegExp(properties.regex); + properties.reserved = [].concat(properties.reserved || []); + } +} + // Parses values of the form "$=jQuery,React=react" into key-value object pairs. const parseMappingArgument = (globalStrings, processValue) => { const globals = {}; @@ -387,7 +412,9 @@ function createConfig(options, entry, format, writeMeta) { // let rollupName = safeVariableName(basename(entry).replace(/\.js$/, '')); let nameCache = {}; - let mangleOptions = options.pkg.mangle || false; + const bareNameCache = nameCache; + // Support "minify" field and legacy "mangle" field via package.json: + let minifyOptions = options.pkg.minify || options.pkg.mangle || {}; const useTypescript = extname(entry) === '.ts' || extname(entry) === '.tsx'; @@ -400,10 +427,22 @@ function createConfig(options, entry, format, writeMeta) { nameCache = JSON.parse( fs.readFileSync(resolve(options.cwd, 'mangle.json'), 'utf8'), ); + // 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; + let shebang; let config = { @@ -539,28 +578,22 @@ function createConfig(options, entry, format, writeMeta) { terser({ sourcemap: true, output: { comments: false }, - compress: { - keep_infinity: true, - pure_getters: true, - global_defs: defines, - passes: 10, - }, + compress: Object.assign( + { + keep_infinity: true, + pure_getters: true, + global_defs: defines, + passes: 10, + }, + minifyOptions.compress || {}, + ), warnings: true, ecma: 5, toplevel: format === 'cjs' || format === 'es', - mangle: { - properties: mangleOptions - ? { - regex: mangleOptions.regex - ? new RegExp(mangleOptions.regex) - : null, - reserved: mangleOptions.reserved || [], - } - : false, - }, + mangle: Object.assign({}, minifyOptions.mangle || {}), nameCache, }), - mangleOptions && { + nameCache && { // before hook options: loadNameCache, // after hook