Удивительный модуль сообщества

UglifyJS 3

UglifyJS - это инструментарий синтаксического анализатора, минификатора, компрессора и улучшения JavaScript.

Замечания:

  • uglify-js@3 имеет упрощенный API и CLI, который не имеет обратной совместимости с uglify-js@2 .
  • Документацию для выпусков UglifyJS 2.x можно найти здесь .
  • uglify-js поддерживает только JavaScript (ECMAScript 5).
  • To minify ECMAScript 2015 or above позднюю версию, используйте такие инструменты, как Babel .

устанавливать

Сначала убедитесь, что вы установили последнюю версию node.js (возможно, вам потребуется перезагрузить компьютер после этого шага).

Из NPM для использования в качестве приложения командной строки:

1
npm install uglify-js -g

Из NPM для программного использования:

1
npm install uglify-js

Использование командной строки

1
uglifyjs [input files] [options]

UglifyJS может принимать несколько входных файлов. Рекомендуется сначала передать входные файлы, а затем передать параметры. UglifyJS будет последовательно анализировать входные файлы и применять любые параметры сжатия. Файлы анализируются в той же глобальной области видимости, то есть для справки. из файла в какую-либо переменную / функцию, объявленную в другом файле, будет сопоставлена ​​должным образом.

Если входной файл не указан, UglifyJS будет читать из STDIN.

Если вы хотите передать параметры перед входными файлами, разделите их двойным тире, чтобы входные файлы не использовались в качестве аргументов параметров:

1
uglifyjs --compress --mangle -- input.js

Command line options

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
-h, --help Print usage information. `--help options` for details on available options. -V, --version Print version number. -p, --parse <options> Specify parser options: `acorn` Use Acorn for parsing. `bare_returns` Allow return outside of functions. Useful when minifying CommonJS modules and Userscripts that may be anonymous function wrapped (IIFE) by the .user.js engine `caller`. `expression` Parse a single expression, rather than a program (for parsing JSON). `spidermonkey` Assume input files are SpiderMonkey AST format (as JSON). -c, --compress [options] Enable compressor/specify compressor options: `pure_funcs` List of functions that can be safely removed when their return values are not used. -m, --mangle [options] Mangle names/specify mangler options: `reserved` List of names that should not be mangled. --mangle-props [options] Mangle properties/specify mangler options: `builtins` Mangle property names that overlaps with standard JavaScript globals. `debug` Add debug prefix and suffix. `domprops` Mangle property names that overlaps with DOM properties. `keep_quoted` Only mangle unquoted properties. `regex` Only mangle matched property names. `reserved` List of names that should not be mangled. -b, --beautify [options] Beautify output/specify output options: `beautify` Enabled with `--beautify` by default. `preamble` Preamble to prepend to the output. You can use this to insert a comment, for example for licensing information. This will not be parsed, but the source map will adjust for its presence. `quote_style` Quote style: 0 - auto 1 - single 2 - double 3 - original `wrap_iife` Wrap IIFEs in parenthesis. Note: you may want to disable `negate_iife` under compressor options. -o, --output <file> Output file path (default STDOUT). Specify `ast` or `spidermonkey` to write UglifyJS or SpiderMonkey AST as JSON to STDOUT respectively. --comments [filter] Preserve copyright comments in the output. By default this works like Google Closure, keeping JSDoc-style comments that contain "@license" or "@preserve". You can optionally pass one of the following arguments to this flag: - "all" to keep all comments - a valid JS RegExp like `/foo/` or `/^!/` to keep only matching comments. Note that currently not *all* comments can be kept when compression is on, because of dead code removal or cascading statements into sequences. --config-file <file> Read `minify()` options from JSON file. -d, --define <expr>[=value] Global definitions. --ie8 Support non-standard Internet Explorer 8. Equivalent to setting `ie8: true` in `minify()` for `compress`, `mangle` and `output` options. By default UglifyJS will not try to be IE-proof. --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name. --name-cache <file> File to hold mangled name mappings. --self Build UglifyJS as a library (implies --wrap UglifyJS) --source-map [options] Enable source map/specify source map options: `base` Path to compute relative paths from input files. `content` Input source map, useful if you're compressing JS that was generated from some other original code. Specify "inline" if the source map is included within the sources. `filename` Name and/or location of the output source. `includeSources` Pass this flag if you want to include the content of source files in the source map as sourcesContent property. `root` Path to the original source to be included in the source map. `url` If specified, path to the source map to append in `//# sourceMappingURL`. --timings Display operations run time on STDERR. --toplevel Compress and/or mangle variables in top level scope. --verbose Print diagnostic messages. --warn Print warning messages. --wrap <name> Embed everything in a big function, making the “exports” and “global” variables available. You need to pass an argument to this option to specify the name that your module will take when included in, say, a browser.

Укажите --output ( -o ) для объявления выходного файла, в противном случае выходные данные отправляются в STDOUT.

Параметры карты источника CLI

UglifyJS может сгенерировать файл исходной карты, который очень полезен для отладки сжатого JavaScript. Чтобы получить исходную карту, передайте --source-map --output output.js (исходная карта будет записана в output.js.map ) ,

Дополнительные опции:

  • --source-map "filename='<NAME>'" чтобы указать имя исходной карты.

  • --source-map "root='<URL>'" для передачи URL, на котором можно найти исходные файлы.

  • --source-map "url='<URL>'" чтобы указать URL-адрес, по которому можно найти исходную карту. В противном случае UglifyJS предполагает, что используется HTTP X-SourceMap , и пропустит директиву //# sourceMappingURL= .

Например:

1 2 3
uglifyjs js/file1.js js/file2.js \ -o foo.min.js -c -m \ --source-map "root='http://foo.com/src',url='foo.min.js.map'"

file1.js сжимает и file1.js file2.js file1.js и file2.js , file2.js выходные данные в foo.min.js и карту источника в foo.min.js.map . foo.min.js.map источника будет ссылаться на http://foo.com/src/js/file1.js и http://foo.com/src/js/file2.js (на самом деле это будет список http://foo.com/src в качестве корневого источника карты, а исходные файлы как js/file1.js и js/file2.js ).

Composed source map

Когда вы сжимаете код JS, который был выведен компилятором, таким как CoffeeScript, сопоставление с кодом JS не будет слишком полезным. Вместо этого вы хотели бы вернуться к исходному коду (например, CoffeeScript). UglifyJS имеет возможность взять исходную карту источника. Предполагая, что у вас есть отображение из CoffeeScript → скомпилированный JS, UglifyJS может сгенерировать карту из CoffeeScript → сжатый JS, сопоставляя каждый токен в скомпилированном JS с его исходным местоположением.

Чтобы использовать эту функцию, передайте --source-map "content='/path/to/input/source.map'" или --source-map "content=inline" если исходная карта включена в линию с источниками.

Параметры сжатия CLI

Чтобы включить компрессор, необходимо передать --compress ( -c ). При желании вы можете передать список параметров сжатия, разделенных запятыми.

Параметры имеют вид foo=bar или просто foo (последний подразумевает логический параметр, который вы хотите установить в true ; это, по сути, ярлык для foo=true ).

Пример:

1
uglifyjs file.js -c toplevel,sequences=false

Параметры командной строки CLI

Чтобы включить mangler, вам нужно передать --mangle ( -m ). Поддерживаются следующие (через запятую) опции:

  • toplevel (по умолчанию false ) - искажать имена, объявленные в области верхнего уровня.

  • eval (по умолчанию false ) - отображать имена, видимые в областях, где используются eval или with .

Если функция искажения включена, но вы хотите предотвратить искажение определенных имен, вы можете объявить эти имена с помощью --mangle reserved - передать список имен через запятую. Например:

1
uglifyjs ... -m reserved=['$','require','exports']

чтобы предотвратить изменение require , exports и $ names.

Имена свойств CLI ( --mangle-props )

Примечание: Это, вероятно, сломает ваш код. Изменение имен свойств - это отдельный шаг, отличный от искажения имен переменных. Передайте --mangle-props чтобы включить его. Он будет манипулировать всеми свойствами входного кода, за исключением встроенных свойств DOM. и свойства в основных классах JavaScript. Например:

1 2 3 4 5 6 7 8 9 10 11
// example.js var x = { baz_: 0, foo_: 1, calc: function() { return this.foo_ + this.baz_; } }; x.bar_ = 2; x["baz_"] = 3; console.log(x.calc());

Изменить все свойства (кроме builtins JavaScript):

1
$ uglifyjs example.js -c -m --mangle-props
1
var x={o:0,_:1,l:function(){return this._+this.o}};x.t=2,x.o=3,console.log(x.l());

Mangle все свойства за исключением reserved свойств:

1
$ uglifyjs example.js -c -m --mangle-props reserved=[foo_,bar_]
1
var x={o:0,foo_:1,_:function(){return this.foo_+this.o}};x.bar_=2,x.o=3,console.log(x._());

Измените все свойства, соответствующие regex :

1
$ uglifyjs example.js -c -m --mangle-props regex=/_$/
1
var x={o:0,_:1,calc:function(){return this._+this.o}};x.l=2,x.o=3,console.log(x.calc());

Объединение параметров свойств mangle:

1
$ uglifyjs example.js -c -m --mangle-props regex=/_$/,reserved=[bar_]
1
var x={o:0,_:1,calc:function(){return this._+this.o}};x.bar_=2,x.o=3,console.log(x.calc());

Чтобы это было --mangle-props builtins , мы по умолчанию избегаем искажения стандартных имен JS ( --mangle-props builtins для переопределения).

Файл исключения по умолчанию предоставляется в tools/domprops.json который должен охватывать большинство стандартных свойств JS и DOM, определенных в различных браузерах. Передайте --mangle-props domprops чтобы отключить эту функцию.

Регулярное выражение может использоваться, чтобы определить, какие имена свойств должны быть --mangle-props regex=/^_/ , --mangle-props regex=/^_/ будет --mangle-props regex=/^_/ только имена свойств, которые начинаются с подчеркивания.

Когда вы сжимаете несколько файлов, используя эту опцию, для того, чтобы они в итоге работали вместе, нам нужно как-то убедиться, что одно свойство будет искажено во всех них с одинаковыми именами. Для этого передайте --name-cache filename.json и UglifyJS сохранит эти отображения в файле, который затем можно будет использовать повторно. Сначала он должен быть пустым. Пример:

1 2 3
$ rm -f /tmp/cache.json # start fresh $ uglifyjs file1.js file2.js --mangle-props --name-cache /tmp/cache.json -o part1.js $ uglifyjs file3.js file4.js --mangle-props --name-cache /tmp/cache.json -o part2.js

Теперь part1.js и part2.js будут согласованы друг с другом в терминах искаженных имен свойств.

Использование кэша имен не требуется, если вы сжимаете все свои файлы за один вызов UglifyJS.

--mangle-props keep_quoted ( --mangle-props keep_quoted )

Использование заключенного в кавычки имени свойства ( o["foo"] ) резервирует имя свойства ( foo ), чтобы оно не искажалось по всему сценарию даже при использовании в o.foo ( o.foo ). Пример:

1 2 3 4 5 6 7
// stuff.js var o = { "foo": 1, bar: 3 }; o.foo += o.bar; console.log(o.foo);
1
$ uglifyjs stuff.js --mangle-props keep_quoted -c -m
1
var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);

Debugging property name mangling

Вы также можете передать --mangle-props debug именами свойств, не затеняя их полностью. Например, свойство o.foo на o._$foo$_ с этой опцией. Это позволяет манипулировать свойствами большой базы кода. все еще будучи в состоянии отладить код и определить, где искажения ломают вещи.

1
$ uglifyjs stuff.js --mangle-props debug -c -m
1
var o={_$foo$_:1,_$bar$_:3};o._$foo$_+=o._$bar$_,console.log(o._$foo$_);

Вы также можете передать пользовательский суффикс, используя --mangle-props debug=XYZ . Это затем o.foo на o._$foo$XYZ_ . Вы можете изменять его каждый раз, когда вы компилируете скрипт, чтобы определить, как свойство было искажено Одним из методов является передача случайного числа в каждом компиляторе для имитации искажения, изменяющегося при разных входах (например, при обновлении сценария ввода новыми свойствами), и для выявления ошибок, таких как запись искаженных ключей в хранилище.

Справочник по API

Предполагая установку через NPM, вы можете загрузить UglifyJS в ваше приложение следующим образом:

1
var UglifyJS = require("uglify-js");

Существует одна высокоуровневая функция minify(code, options) , которая будет выполнять все этапы минимизации настраиваемым способом. По умолчанию minify() включает параметры compress и mangle . Пример:

1 2 3 4
var code = "function add(first, second) { return first + second; }"; var result = UglifyJS.minify(code); console.log(result.error); // runtime error, or `undefined` if no error console.log(result.code); // minified output: function add(n,d){return n+d}

Вы можете minify более одного файла JavaScript одновременно, используя объект для первого аргумента, где ключи - это имена файлов, а значения - исходный код:

1 2 3 4 5 6 7
var code = { "file1.js": "function add(first, second) { return first + second; }", "file2.js": "console.log(add(1 + 2, 3 + 4));" }; var result = UglifyJS.minify(code); console.log(result.code); // function add(d,n){return d+n}console.log(add(3,7));

Опция toplevel :

1 2 3 4 5 6 7 8
var code = { "file1.js": "function add(first, second) { return first + second; }", "file2.js": "console.log(add(1 + 2, 3 + 4));" }; var options = { toplevel: true }; var result = UglifyJS.minify(code, options); console.log(result.code); // console.log(3+7);

Опция nameCache :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
var options = { mangle: { toplevel: true, }, nameCache: {} }; var result1 = UglifyJS.minify({ "file1.js": "function add(first, second) { return first + second; }" }, options); var result2 = UglifyJS.minify({ "file2.js": "console.log(add(1 + 2, 3 + 4));" }, options); console.log(result1.code); // function n(n,r){return n+r} console.log(result2.code); // console.log(n(3,7));

Вы можете сохранить кэш имен в файловой системе следующим образом:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
var cacheFileName = "/tmp/cache.json"; var options = { mangle: { properties: true, }, nameCache: JSON.parse(fs.readFileSync(cacheFileName, "utf8")) }; fs.writeFileSync("part1.js", UglifyJS.minify({ "file1.js": fs.readFileSync("file1.js", "utf8"), "file2.js": fs.readFileSync("file2.js", "utf8") }, options).code, "utf8"); fs.writeFileSync("part2.js", UglifyJS.minify({ "file3.js": fs.readFileSync("file3.js", "utf8"), "file4.js": fs.readFileSync("file4.js", "utf8") }, options).code, "utf8"); fs.writeFileSync(cacheFileName, JSON.stringify(options.nameCache), "utf8");

Пример комбинации параметров minify() :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
var code = { "file1.js": "function add(first, second) { return first + second; }", "file2.js": "console.log(add(1 + 2, 3 + 4));" }; var options = { toplevel: true, compress: { global_defs: { "@console.log": "alert" }, passes: 2 }, output: { beautify: false, preamble: "/* uglified */" } }; var result = UglifyJS.minify(code, options); console.log(result.code); // /* uglified */ // alert(10);"

Для выдачи предупреждений:

1 2 3 4 5 6
var code = "function f(){ var u; return 2 + 3; }"; var options = { warnings: true }; var result = UglifyJS.minify(code, options); console.log(result.error); // runtime error, `undefined` in this case console.log(result.warnings); // [ 'Dropping unused variable u [0:1,18]' ] console.log(result.code); // function f(){return 5}

Пример ошибки:

1 2 3
var result = UglifyJS.minify({"foo.js" : "if (0) else console.log(1);"}); console.log(JSON.stringify(result.error)); // {"message":"Unexpected token: keyword (else)","filename":"foo.js","line":1,"col":7,"pos":7}

Примечание: в отличие от `uglify-js@2.x , the 3.x` API не бросает ошибки Для достижения подобного эффекта можно было бы сделать следующее.:

1 2
var result = UglifyJS.minify(code, options); if (result.error) throw result.error;

Минимизировать параметры

  • warnings (по умолчанию false ) - передайте true для возврата предупреждений компрессора в result.warnings . Используйте значение "verbose" для более подробных предупреждений.

  • parse (по умолчанию {} ) - передать объект, если вы хотите указать некоторые дополнительные параметры разбора .

  • compress (default {} ) - передайте false чтобы полностью пропустить сжатие. Передайте объект, чтобы указать пользовательские параметры сжатия .

  • mangle (по умолчанию true ) - передайте false чтобы пропустить искажение имен, или передайте объект, чтобы указать параметры mangle (см. ниже).

    • mangle.properties (по умолчанию false ) - подкатегория параметра mangle. Передайте объект, чтобы указать пользовательские параметры свойства mangle .
  • output (по умолчанию null ) - передать объект, если вы хотите указать дополнительные параметры вывода . Значения по умолчанию оптимизированы для лучшего сжатия.

  • sourceMap (по умолчанию false ) - пропустить объект, если вы хотите указать параметры карты источника .

  • toplevel (по умолчанию false ) - установить в true если вы хотите включить манипулирование имен переменных и функций верхнего уровня и удалить неиспользуемые переменные и функции.

  • nameCache (по умолчанию null ) nameCache пустой объект {} или ранее использовавшийся объект nameCache если вы хотите кэшировать искаженные имена переменных и свойств при нескольких nameCache minify() . Примечание: это свойство чтения / записи. minify() будет прочитайте состояние кэша имен этого объекта и обновите его во время минимизации, чтобы он мог повторно использоваться или сохраняться внешним пользователем.

  • ie8 (по умолчанию false ) - установить в true для поддержки IE8.

  • keep_fnames (default: false ) -pass true для предотвращения отбрасывания или искажения имен функций. Полезно для кода, полагающегося на Function.prototype.name .

Минимизировать структуру опций

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
{ parse: { // parse options }, compress: { // compress options }, mangle: { // mangle options properties: { // mangle property options } }, output: { // output options }, sourceMap: { // source map options }, nameCache: null, // or specify a name cache object toplevel: false, ie8: false, warnings: false, }

Source map options

Чтобы создать исходную карту:

1 2 3 4 5 6 7 8
var result = UglifyJS.minify({"file1.js": "var a = function() {};"}, { sourceMap: { filename: "out.js", url: "out.js.map" } }); console.log(result.code); // minified output console.log(result.map); // source map

Обратите внимание, что исходная карта не сохраняется в файле, она просто возвращается в result.map . Значение, переданное для sourceMap.url используется только для установки //# sourceMappingURL=out.js.map в result.code . Значение filename используется только для установки атрибута file (см. спецификацию ) в файле исходной карты.

Вы можете установить опцию sourceMap.url как "inline" и исходная карта будет добавлена ​​в код.

Вы также можете указать свойство sourceRoot для включения в карту источника:

1 2 3 4 5 6
var result = UglifyJS.minify({"file1.js": "var a = function() {};"}, { sourceMap: { root: "http://example.com/src", url: "out.js.map" } });

Если вы sourceMap.content скомпилированный JavaScript и имеете для него исходную карту, вы можете использовать sourceMap.content :

1 2 3 4 5 6 7
var result = UglifyJS.minify({"compiled.js": "compiled code"}, { sourceMap: { content: "content from compiled.js.map", url: "minified.js.map" } }); // same as before, it returns `code` and `map`

Если вы используете вместо этого заголовок X-SourceMap , вы можете просто пропустить sourceMap.url .

Варианты разбора

  • bare_returns (по умолчанию false ) - поддержка операторов return верхнего уровня

  • html5_comments (по умолчанию true )

  • shebang (по умолчанию true ) - поддержка команды #!command в качестве первой строки

Варианты сжатия

  • arguments (по умолчанию: true ) - по возможности заменяйте arguments[index] на имя параметра функции.

  • booleans (по умолчанию: true ) - различные оптимизации для логического контекста, например !!a ? b : c → a ? b : c

  • collapse_vars (по умолчанию: true ) - сворачивать одноразовые непостоянные переменные, если есть побочные эффекты.

  • comparisons (по умолчанию: true ) - применить определенные оптимизации к двоичным узлам, например !(a <= b) → a > b , попытаться отрицать двоичные узлы, например a = !b && !c && !d && !e → a=!(b||c||d||e) и т. д.

  • conditionals (по умолчанию: true ) - применять оптимизации для if -s и условных выражений

  • dead_code (по умолчанию: true ) - удалить недоступный код

  • drop_console (по умолчанию: false ) - drop_console true чтобы отменить вызовы функций console.* . Если вы хотите удалить конкретный вызов функции, такой как console.info и / или сохранить побочные эффекты от аргументов функции после pure_funcs вызова функции, тогда используйте pure_funcs вместо.

  • drop_debugger (по умолчанию: true ) - удалить debugger; операторы

  • evaluate (по умолчанию: true ) - попытаться вычислить константные выражения

  • expression (по умолчанию: false ) - передать true чтобы сохранить значения завершения из операторов терминала без return , например, в букмарклетах.

  • global_defs (по умолчанию: {} ) - см. условную компиляцию

  • hoist_funs (по умолчанию: false ) - объявления функции hoist_funs

  • hoist_props (по умолчанию: true ) - переносить свойства из константных литералов объекта и массива в обычные переменные с учетом ряда ограничений, например: var o={p:1, q:2}; f(op, oq); is преобразуется в f(1, 2); Примечание: hoist_props лучше всего работает при включенном mangle , опция compress passes значение 2 или выше, и опция compress toplevel включена.

  • hoist_vars (по умолчанию: false ) - декларации hoist_vars var (по умолчанию это false , потому что кажется, что он в целом увеличивает размер вывода)

  • if_return (по умолчанию: true ) - оптимизации для if / return и if / continue

  • inline (по умолчанию: true ) - встроенные вызовы функции с простым / return оператором:

    • false - так же, как 0
    • 0 - отключено встраивание
    • 1 - встроенные простые функции
    • 2 - встроенные функции с аргументами
    • 3 - встроенные функции с аргументами и переменными
    • true - так же, как 3
  • join_vars (по умолчанию: true ) - объединяет последовательные операторы var

  • keep_fargs (по умолчанию: true ) - запрещает компрессору отбрасывать неиспользуемые аргументы функции. Это необходимо для кода, который использует Function.length .

  • keep_fnames (по умолчанию: false ) - keep_fnames true чтобы компрессор не отбрасывал имена функций. Полезно для кода, полагающегося на Function.prototype.name . См. также: опция keep_fnames mangle .

  • keep_infinity (по умолчанию: false ) - keep_infinity true чтобы предотвратить сжатие Infinity в 1/0 , что может вызвать проблемы с производительностью в Chrome.

  • loops (по умолчанию: true ) - оптимизация for циклов do , while и for когда мы можем статически определить условие.

  • negate_iife (по умолчанию: true ) - отменяет «выражения функций с немедленным negate_iife », в которых возвращаемое значение отбрасывается, чтобы избежать тех паренсов, которые мог бы вставить генератор кода.

  • passes (по умолчанию: 1 ) - максимальное количество раз, чтобы выполнить сжатие. В некоторых случаях более одного прохода приводит к дальнейшему сжатому коду. Имейте в виду, что больше проходов займет больше времени.

  • properties (default: true ) - переписать доступ к свойству, используя точечную запись, например, foo["bar"] → foo.bar

  • pure_funcs (по умолчанию: null ) - вы можете передать массив имен, и UglifyJS будет предполагать, что эти функции не вызывают побочных эффектов. ОПАСНОСТЬ: не будет проверять, переопределено ли имя в области. Пример в данном случае, например, var q = Math.floor(a/b) . Если переменная q не используется в другом месте, UglifyJS удалит его, но все равно будет хранить Math.floor(a/b) , не зная, что он делает. Вы можете передать pure_funcs: [ 'Math.floor' ] чтобы сообщить, что эта функция не будет вызывать побочных эффектов, в этом случае весь оператор будет отброшен. Текущая реализация добавляет некоторые издержки (сжатие будет медленнее). Убедитесь, что символы в pure_funcs также под mangle.reserved чтобы избежать искажения.

  • pure_getters (по умолчанию: "strict" ) - если вы передадите true для этого, UglifyJS будет предполагать, что доступ к свойству объекта (например, foo.bar или foo["bar"] ) не имеет никаких побочных эффектов. Укажите "strict" для foo.bar с foo.bar как с побочным эффектом, только когда foo наверняка не сгенерирует, то есть не имеет значение null или undefined .

  • reduce_funcs (по умолчанию: true ) - позволяет одноразовым функциям быть встроенными в виде выражений функций, когда это допустимо, что допускает дальнейшую оптимизацию. Включено по умолчанию. Опция зависит от того, включен ли reduce_vars . Некоторый код работает быстрее в движке Chrome V8, если эта опция отключена Не оказывает негативного влияния на другие основные браузеры.

  • reduce_vars (по умолчанию: true ) - Улучшена оптимизация для переменных, назначенных и используемых в качестве постоянных значений.

  • sequences (default: true ) - объединить простые последовательные операторы с помощью оператора запятой. Может быть установлено положительное целое число, чтобы указать максимальное число последовательных последовательностей запятых, которые будут сгенерированы. Если для этого параметра установлено значение true то предел sequences по умолчанию равно 200 Установите для параметра значение false или для отключения значение 0 Наименьшая длина sequences равна 2 Значение sequences равное 1 определяется как эквивалентное значению true и, как таковое, означает 200 В редких случаях ограничение по умолчанию для последовательностей приводит к очень медленному времени сжатия. в этом случае рекомендуется значение 20 или меньше.

  • side_effects (по умолчанию: true ) - side_effects false чтобы отключить потенциально отбрасываемые функции, помеченные как «чистые». Вызов функции помечается как «чистый», если комментарий комментария /*@__PURE__*/ или /*#__PURE__*/ непосредственно предшествует вызов. Например: /*@__PURE__*/foo();

  • switches (по умолчанию: true ) - дедупликация и удаление недоступных ветвей switch

  • toplevel (по умолчанию: false ) - удалить несвязанные функции ( "funcs" ) и / или переменные ( "vars" ) в области видимости верхнего уровня (по умолчанию false , true чтобы удалить как функции, так и переменные, на которые нет ссылок)

  • top_retain (по умолчанию: null ) - предотвращает unused удаление определенных функций и переменных верхнего уровня (может быть массивом, разделенным запятыми, RegExp или функцией. Предполагается, что toplevel )

  • typeofs (по умолчанию: true ) - преобразует typeof foo == "undefined" в foo === void 0 Примечание. Рекомендуется установить значение false в IE10 и более ранних версиях из-за известных проблем.

  • unsafe (по умолчанию: false ) - применять «небезопасные» преобразования (обсуждение ниже)

  • unsafe_comps (по умолчанию: false ) - сжимает выражения типа a <= b предполагая, что ни один из операндов не может быть (приведен к) NaN .

  • unsafe_Function (по умолчанию: false ) - сжимать и изменять Function(args, code) когда args и code являются строковыми литералами.

  • unsafe_math (по умолчанию: false ) - оптимизировать числовые выражения, такие как 2 * x * 3 в 6 * x , что может дать неточные результаты с плавающей запятой.

  • unsafe_proto (по умолчанию: false ) - оптимизировать выражения типа Array.prototype.slice.call(a) в [].slice.call(a)

  • unsafe_regexp (по умолчанию: false ) - разрешить подстановку переменных значениями RegExp же, как если бы они были константами.

  • unsafe_undefined (по умолчанию: false ) - подставить void 0 если в области видимости есть переменная с именем undefined (имя переменной будет искажено, как правило, сокращено до одного символа)

  • unused (по умолчанию: true ) - отбрасывать функции и переменные, на которые нет ссылок (простые прямые назначения переменных не считаются ссылками, если не установлено значение "keep_assign" )

  • warnings (по умолчанию: false ) - отображать предупреждения при удалении недоступного кода или неиспользуемых объявлений и т. д.

Варианты Mangle

  • eval (по умолчанию false ) - передать true чтобы искажать имена, видимые в областях, где используются eval или with .

  • keep_fnames (по умолчанию false ) - keep_fnames true чтобы не искажать имена функций. Полезно для кода, полагающегося на Function.prototype.name . См. также: keep_fnames сжатия keep_fnames .

  • reserved (default [] ) - передать массив идентификаторов, которые следует исключить из искажения. Пример: ["foo", "bar"] .

  • toplevel (по умолчанию false ) - передайте true именам mangle, объявленным в области верхнего уровня.

Примеры:

1 2 3 4 5
// test.js var globalVar; function funcName(firstLongName, anotherLongName) { var myVariable = firstLongName + anotherLongName; }
1 2 3 4 5 6 7 8 9 10
var code = fs.readFileSync("test.js", "utf8"); UglifyJS.minify(code).code; // 'function funcName(a,n){}var globalVar;' UglifyJS.minify(code, { mangle: { reserved: ['firstLongName'] } }).code; // 'function funcName(firstLongName,a){}var globalVar;' UglifyJS.minify(code, { mangle: { toplevel: true } }).code; // 'function n(n,a){}var a;'

Mangle properties options

  • builtins (по умолчанию: false ) - используйте true чтобы разрешить искажение встроенных свойств DOM. Не рекомендуется переопределять этот параметр.

  • debug (по умолчанию: false ) - изменяет имена с исходным именем. Передайте пустую строку "" чтобы включить, или непустую строку, чтобы установить суффикс отладки.

  • keep_quoted (по умолчанию: false ) -— Только keep_quoted .

  • regex (по умолчанию: null ) -— Передать литерал RegExp только для того, чтобы искажать имена свойств, соответствующие регулярному выражению.

  • reserved (по умолчанию: [] ) - не искажать имена свойств, перечисленные в reserved массиве.

Варианты вывода

Генератор кода пытается вывести кратчайший из возможных кодов по умолчанию. Если вы хотите --beautify вывод, передайте --beautify ( -b ). При желании вы можете передать дополнительные аргументы, управляющие выводом кода:

  • ascii_only (по умолчанию false ) - экранировать символы Unicode в строках и ascii_only (влияет на директивы, в которых символы не-ascii становятся недопустимыми)

  • beautify (по умолчанию true ) - действительно ли нужно украсить вывод. Передавая -b установит для него значение true, но вам может потребоваться передать -b даже если вы хотите сгенерировать минимизированный код, чтобы указать дополнительные аргументы, чтобы вы могли используйте -b beautify=false чтобы переопределить его.

  • braces (по умолчанию false ) - всегда вставляйте фигурные скобки в операторах if , for , do , while или with , даже если их тело является одним оператором.

  • comments (по умолчанию false ) - передайте true или "all" чтобы сохранить все комментарии, "some" чтобы сохранить некоторые комментарии, строку регулярного выражения (например, /^!/ ) или функцию.

  • indent_level (по умолчанию 4 )

  • indent_start (по умолчанию 0 ) - префикс всех строк на столько пробелов

  • inline_script (по умолчанию true ) - экранировать комментарии HTML и косую черту в появлении </script> в строках

  • keep_quoted_props (по умолчанию false ) - при включении предотвращает удаление кавычек из имен свойств в литералах объекта.

  • max_line_len (по умолчанию false ) - максимальная длина строки (для увеличенного кода)

  • preamble (по умолчанию null ) - при передаче это должна быть строка, и она будет буквально добавлена ​​к выводу. Карта источника будет корректироваться для этого текста. Может использоваться, например, для вставки комментария, содержащего информацию о лицензировании.

  • preserve_line (по умолчанию false ) - передайте true для сохранения строк, но это работает, только если для beautify установлено значение false .

  • quote_keys (по умолчанию false ) - передать true чтобы quote_keys все ключи в литеральные объекты

  • quote_style (по умолчанию 0 ) - предпочтительный стиль кавычек для строк (также влияет на имена свойств и директивы в кавычках):

    • 0 - предпочитает двойные кавычки, переключается на одинарные, если в самой строке больше двойных кавычек, 0 лучше всего подходит для размера gzip.
    • 1 - всегда используйте одинарные кавычки
    • 2 - всегда используйте двойные кавычки
    • 3 - всегда используйте оригинальные цитаты
  • semicolons (по умолчанию true ) - отдельные операторы с точкой с запятой. Если вы передадите false тогда, когда это возможно, мы будем использовать новую точку вместо точки с запятой, что приведет к более удобочитаемому выводу кода с расширенными кодами (размер до gzip может быть меньше; размер после gzip незначительно больше ).

  • shebang (по умолчанию true ) - сохранить shebang #! в преамбуле (скрипты bash)

  • webkit (по умолчанию false ) - включить обходные пути для ошибок WebKit. Пользователям PhantomJS следует установить для этой опции значение true .

  • width (по умолчанию 80 ) - вступает в силу только при включенном украшении, это определяет (ориентировочную) ширину линии, которую beautifier будет пытаться выполнить. Это относится к ширине текста строки (исключая отступы). очень хорошо в настоящее время, но это делает код, сгенерированный UglifyJS, более читабельным.

  • wrap_iife (по умолчанию false ) - передайте true для переноса немедленно вызванных выражений функций. Подробнее см. # 640 .

Разное

МОЖЕТ пройти мимо вас --comments . Сохранение определенных для комментариев Вывод По умолчанию в стиле IT будет сохранять JSDoc, содержащий комментарии «@preserve», «@license» или «@cc_on» (условная компиляция для IE), передаваемая вами CAN. --comments all to keep all the comments, or a valid JavaScript regexp to keep only comments that match this regexp. For example --comments /^!/ will keep comments like /*! Copyright Notice */ .

Note, however, that there might be situations where comments are lost. For example:

1 2 3 4 5 6 7
function f() { /** @preserve Foo Bar */ function g() { // this function is never called } return something(); }

Even though it has "@preserve", the comment will be lost because the inner function g (which is the AST node to which the comment is attached to) is discarded by the compressor as not referenced.

The safest comments where to place copyright information (or other info that needs to be kept in the output) are comments attached to toplevel nodes.

The unsafe compress option

It enables some transformations that might break code logic in certain contrived cases, but should be fine for most code. You might want to try it on your own code, it should reduce the minified size. Here's what happens when this flag is on:

  • new Array(1, 2, 3) or Array(1, 2, 3)[ 1, 2, 3 ]
  • new Object(){}
  • String(exp) or exp.toString()"" + exp
  • new Object/RegExp/Function/Error/Array (...) → we discard the new

Conditional compilation

You can use the --define ( -d ) switch in order to declare global variables that UglifyJS will assume to be constants (unless defined in scope). For example if you pass --define DEBUG=false then, coupled with dead code removal UglifyJS will discard the following from the output:

1 2 3
if (DEBUG) { console.log("debug stuff"); }

You can specify nested constants in the form of --define env.DEBUG=false .

UglifyJS will warn about the condition being always false and about dropping unreachable code; for now there is no option to turn off only this specific warning, you can pass warnings=false to turn off all warnings.

Another way of doing that is to declare your globals as constants in a separate file and include it into the build. For example you can have a build/defines.js file with the following:

1 2 3
var DEBUG = false; var PRODUCTION = true; // etc.

and build your code like this:

1
uglifyjs build/defines.js js/foo.js js/bar.js... -c

UglifyJS will notice the constants and, since they cannot be altered, it will evaluate references to them to the value itself and drop unreachable code as usual. The build will contain the const declarations if you use them. If you are targeting < ES6 environments which does not support const , using var with reduce_vars (enabled by default) should suffice.

Conditional compilation API

You can also use conditional compilation via the programmatic API. With the difference that the property name is global_defs and is a compressor property:

1 2 3 4 5 6 7 8
var result = UglifyJS.minify(fs.readFileSync("input.js", "utf8"), { compress: { dead_code: true, global_defs: { DEBUG: false } } });

To replace an identifier with an arbitrary non-constant expression it is necessary to prefix the global_defs key with "@" to instruct UglifyJS to parse the value as an expression:

1 2 3 4 5 6 7 8
UglifyJS.minify("alert('hello');", { compress: { global_defs: { "@alert": "console.log" } } }).code; // returns: 'console.log("hello");'

Otherwise it would be replaced as string literal:

1 2 3 4 5 6 7 8
UglifyJS.minify("alert('hello');", { compress: { global_defs: { "alert": "console.log" } } }).code; // returns: '"console.log"("hello");'

Using native Uglify AST with minify()

1 2 3 4 5 6 7 8 9 10 11 12 13
// example: parse only, produce native Uglify AST var result = UglifyJS.minify(code, { parse: {}, compress: false, mangle: false, output: { ast: true, code: false // optional - faster if false } }); // result.ast contains native Uglify AST
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// example: accept native Uglify AST input and then compress and mangle // to produce both code and native AST. var result = UglifyJS.minify(ast, { compress: {}, mangle: {}, output: { ast: true, code: true // optional - faster if false } }); // result.ast contains native Uglify AST // result.code contains the minified code in string form.

Working with Uglify AST

Transversal and transformation of the native AST can be performed through TreeWalker and TreeTransformer respectively.

ESTree / SpiderMonkey AST

UglifyJS has its own abstract syntax tree format; for practical reasons we can't easily change to using the SpiderMonkey AST internally. However, UglifyJS now has a converter which can import a SpiderMonkey AST.

For example Acorn is a super-fast parser that produces a SpiderMonkey AST. It has a small CLI utility that parses one file and dumps the AST in JSON on the standard output. To use UglifyJS to mangle and compress that:

1
acorn file.js | uglifyjs -p spidermonkey -m -c

The -p spidermonkey option tells UglifyJS that all input files are not JavaScript, but JS code described in SpiderMonkey AST in JSON. Therefore we don't use our own parser in this case, but just transform that AST into our internal AST.

Use Acorn for parsing

More for fun, I added the -p acorn option which will use Acorn to do all the parsing. If you pass this option, UglifyJS will require("acorn") .

Acorn is really fast (eg 250ms instead of 380ms on some 650K code), but converting the SpiderMonkey tree that Acorn produces takes another 150ms so in total it's a bit more than just using UglifyJS's own parser.

Uglify Fast Minify Mode

It's not well known, but whitespace removal and symbol mangling accounts for 95% of the size reduction in minified code for most JavaScript - not elaborate code transforms. One can simply disable compress to speed up Uglify builds by 3 to 4 times. In this fast mangle -only mode Uglify has comparable minify speeds and gzip sizes to butternut :

d3.js minify size gzip size minify time (seconds)
original 451,131 108,733 -
uglify-js@3.0.24 mangle=false, compress=false 316,600 85,245 0.70
uglify-js@3.0.24 mangle=true, compress=false 220,216 72,730 1.13
butternut@0.4.6 217,568 72,738 1.41
uglify-js@3.0.24 mangle=true, compress=true 212,511 71,560 3.36
babili@0.1.4 210,713 72,140 12.64

To enable fast minify mode from the CLI use:

1
uglifyjs file.js -m

To enable fast minify mode with the API use:

1
UglifyJS.minify(code, { compress: false, mangle: true });

Source maps and debugging

Various compress transforms that simplify, rearrange, inline and remove code are known to have an adverse effect on debugging with source maps. This is expected as code is optimized and mappings are often simply not possible as some code no longer exists. For highest fidelity in source map debugging disable the Uglify compress option and just use mangle .

Compiler assumptions

To allow for better optimizations, the compiler makes various assumptions:

  • .toString() and .valueOf() don't have side effects, and for built-in objects they have not been overridden.
  • undefined , NaN and Infinity have not been externally redefined.
  • arguments.callee , arguments.caller and Function.prototype.caller are not used.
  • The code doesn't expect the contents of Function.prototype.toString() or Error.prototype.stack to be anything in particular.
  • Getting and setting properties on a plain object does not cause other side effects (using .watch() or Proxy ).
  • Object properties can be added , removed and modified (not prevented with Object.defineProperty() , Object.defineProperties() , Object.freeze() , Object.preventExtensions() or Object.seal() ).