const PLATFORM_MACROS = ['CC_EDITOR', 'CC_PREVIEW', 'CC_BUILD', 'CC_TEST']; const FLAGS = ['support_jit', 'jsb', 'runtime', 'debug', 'nativeRenderer', 'minigame', 'physics_builtin', 'physics_cannon']; // generate macros for uglify's global_defs // available platforms: 'editor' | 'preview' | 'build' | 'test' // available keys of flags: 'jsb' | 'runtime' | 'minigame' | 'debug' | 'nativeRenderer' exports.getMacros = function (platform, flags) { // platform macros var platformMacro = 'CC_' + platform.toUpperCase(); if (PLATFORM_MACROS.indexOf(platformMacro) === -1) { throw new Error('Unknown platform: ' + platform); } var res = {}; for (let i = 0; i < PLATFORM_MACROS.length; i++) { let macro = PLATFORM_MACROS[i]; res[macro] = (macro === platformMacro); } // flag macros if (flags) { for (let flag in flags) { if (flags.hasOwnProperty(flag) && flags[flag]) { if (FLAGS.indexOf(flag) === -1) { throw new Error('Unknown flag: ' + flag); } } } } for (let i = 0; i < FLAGS.length; i++) { let flag = FLAGS[i]; let macro = 'CC_' + flag.toUpperCase(); res[macro] = !!(flags && flags[flag]); } // debug macros res['CC_DEV'] = res['CC_EDITOR'] || res['CC_PREVIEW'] || res['CC_TEST']; res['CC_DEBUG'] = res['CC_DEBUG'] || res['CC_DEV']; // openHarmony does not support Funtion ,therefore this macro variable is temporarily set to false //res['CC_SUPPORT_JIT'] = false; if (typeof flags.force_setting_support_jit !== 'undefined') { res['CC_SUPPORT_JIT'] = flags.force_setting_support_jit; } else { res['CC_SUPPORT_JIT'] = !(res['CC_RUNTIME'] || res['CC_MINIGAME']); } res['CC_NATIVERENDERER'] = res['CC_JSB'] && true; return res; }; // see https://github.com/terser/terser#compress-options exports.getUglifyOptions = function (platform, flags) { var global_defs = exports.getMacros(platform, flags); var releaseMode = !global_defs['CC_DEBUG']; var optimizeForJSC = releaseMode && global_defs['CC_JSB']; if (optimizeForJSC) { return { parse: { bare_returns: true }, toplevel: false, compress: { global_defs: global_defs, negate_iife: false, sequences: false, keep_infinity: true, // reduce jsc file size typeofs: false, inline: true, reduce_funcs: false, // keep single-use function object being cached, but not supported since 4.2.1, see terser/terser#696 passes: 2, // first: remove deadcode, second: drop variables keep_fargs: false, unsafe_Function: true, unsafe_math: true, unsafe_methods: true, }, output: { beautify: true, // enable preserve_lines for line number indent_level: 0, // reduce jsc file size } }; } if (releaseMode) { return { parse: { bare_returns: true }, toplevel: false, compress: { global_defs: global_defs, negate_iife: false, inline: true, reduce_funcs: false, // keep single-use function object being cached, but not supported since 4.2.1, see terser/terser#696 passes: 2, // first: remove deadcode, second: reduce constant variables keep_fargs: false, unsafe_Function: true, unsafe_math: true, unsafe_methods: true, }, // mangle: false, output: { // http://lisperator.net/uglifyjs/codegen // beautify: true, // indent_level: 2, ascii_only: true, }, safari10: true, // cocos-creator/engine#5144 }; } else { return { parse: { bare_returns: true }, toplevel: false, compress: { global_defs: global_defs, negate_iife: false, sequences: false, // join consecutive statements with the “comma operator” properties: false, // optimize property access: a["foo"] → a.foo // dead_code: true, // discard unreachable code drop_debugger: false, // discard “debugger” statements // ecma: 5, // transform ES5 code into smaller ES6+ equivalent forms // evaluate: true, // evaluate constant expressions unsafe: false, // some unsafe optimizations (see below) // computed_props: true, // conditionals: false, // optimize if-s and conditional expressions comparisons: false, // optimize comparisons booleans: false, // optimize boolean expressions typeofs: false, // Transforms typeof foo == "undefined" into foo === void 0. Note: recommend to set this value to false for IE10 and earlier versions due to known issues. loops: false, // optimize loops unused: false, // drop unused variables/functions hoist_funs: false, // hoist function declarations hoist_props: false, hoist_vars: false, // hoist variable declarations if_return: false, // optimize if-s followed by return/continue inline: false, // embed simple functions join_vars: false, // join var declarations collapse_vars: false, // Collapse single-use non-constant variables - side effects permitting. reduce_funcs: false, reduce_vars: false, // Improve optimization on variables assigned with and used as constant values. //warnings: true, pure_getters: false, pure_funcs: null, drop_console: false, // expression: false, // Pass true to preserve completion values from terminal statements without return, e.g. in bookmarklets. keep_fargs: true, keep_fnames: true, keep_infinity: true, // Pass true to prevent Infinity from being compressed into 1/0, which may cause performance issues on Chrome. side_effects: false, // drop side-effect-free statements }, mangle: false, //preserveComments: 'all', output: { // http://lisperator.net/uglifyjs/codegen beautify: true, indent_level: 2, ascii_only: true, }, safari10: true, // cocos-creator/engine#5144 }; } }; exports.uglify = function (platform, isJSB, isDebugBuild) { const options = exports.getUglifyOptions(platform, isJSB, isDebugBuild); if (false) { const Composer = require('gulp-uglify/composer'); const Uglify = require('uglify-es'); return Composer(Uglify)(options); } else { const Terser = require("terser"); const ES = require('event-stream'); const applySourceMap = require('vinyl-sourcemaps-apply'); return ES.through(function (file) { if (file.path.endsWith('.js')) { let build; let eachOption; let content = file.contents.toString(); if (file.sourceMap && file.sourceMap.file) { build = {}; build[file.sourceMap.file] = content; eachOption = Object.assign({}, options, { sourceMap: { filename: file.sourceMap.file, }, }); } else { build = content; eachOption = options; } var result = Terser.minify(build, eachOption); if (result.error) { return this.emit('error', result.error); } content = result.code; file.contents = new Buffer(content); if (result.map) { applySourceMap(file, result.map); } } this.emit('data', file); }); } };