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

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 и 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 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

Параметры изменения интерфейса командной строки

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

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

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

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

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

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

CLI --mangle-props имена свойств ( --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());

Исключить все свойства, кроме 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=/^_/ подчеркивания.

Когда вы сжимаете несколько файлов с помощью этой опции, для того, чтобы они работали вместе в конце, нам нужно каким-то образом гарантировать, что одно свойство будет искажено с одним и тем же именем во всех из них. Для этого передайте --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 до 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 возвращались предупреждения result.warnings . Используйте значение "verbose" для получения более подробных предупреждений.

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

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

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

    • 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 (по умолчанию: 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 заголовок 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 вместо.

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

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

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

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

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

  • 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 ) - поднимать объявления 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_fnames .

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

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

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

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

  • properties (по умолчанию: 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 точно не выбрасывает, т.е. не имеет null или undefined .

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

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

  • sequences (по умолчанию: 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" ( "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 ) - отображать предупреждения при удалении недостижимого кода или неиспользуемых объявлений и т. д.

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

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

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

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

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

Примеры:

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 только имена свойств без 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 ) - максимальная длина строки (для uglified кода)

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

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

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

  • 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 ) - действует только при включенном украшении, это определяет (ориентировочную) ширину линии, которой украситель будет пытаться подчиняться. Это относится к ширине текста строки (без отступа). Это не работает очень хорошо в настоящее время, но делает код, сгенерированный UglifyJS, более читабельным.

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

Разное

CAN Pass Вами --comments Сохранять Определенная на комментарии вывод по умолчанию в IT-стиле Will Keep JSDoc, содержащие Комментарии «@preserve», «@license» или «@cc_on» (Условная компиляция для ИЭ) Пасс вы можете.. --comments all чтобы сохранить все комментарии, или допустимое регулярное выражение JavaScript, чтобы оставить только комментарии, соответствующие этому регулярному выражению. Например, --comments /^!/ сохранит комментарии типа /*! Copyright Notice */ .

Учтите, однако, что возможны ситуации, когда комментарии теряются. Например:

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

Даже если в нем есть «@preserve», комментарий будет потерян, потому что внутренняя функция g (которая является узлом AST, к которому прикреплен комментарий) отбрасывается компрессором как не упоминаемая.

Самые безопасные комментарии, куда помещать информацию об авторских правах (или другую информацию, которая должна быть сохранена в выводе), - это комментарии, прикрепленные к узлам верхнего уровня.

Опция unsafe compress

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

  • new Array(1, 2, 3) или Array(1, 2, 3)[ 1, 2, 3 ]
  • new Object(){}
  • String(exp) или exp.toString()"" + exp
  • new Object/RegExp/Function/Error/Array (...) → отбрасываем new

Conditional compilation

Вы можете использовать переключатель --define ( -d ) для объявления глобальных переменных, которые UglifyJS будет считать константами (если они не определены в области видимости). Например, если вы передадите --define DEBUG=false тогда вместе с удалением мертвого кода UglifyJS исключит из вывода следующее:

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

Вы можете указать вложенные константы в форме --define env.DEBUG=false .

UglifyJS будет предупреждать о том, что условие всегда ложно, и об удалении недоступного кода; на данный момент нет возможности отключить только это конкретное предупреждение, вы можете передать warnings=false чтобы отключить все предупреждения.

Другой способ сделать это - объявить глобальные переменные как константы в отдельном файле и включить их в сборку. Например, у вас может быть файл build/defines.js со следующим:

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

и создайте свой код следующим образом:

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

UglifyJS заметит константы и, поскольку они не могут быть изменены, он будет оценивать ссылки на них на само значение и отбрасывать недостижимый код, как обычно. Сборка будет содержать объявления const если вы их используете. Если вы ориентируетесь на среды <ES6, которые не поддерживает const , достаточно использовать var с reduce_vars (по умолчанию включено).

Conditional compilation API

Вы также можете использовать условную компиляцию через программный API. С той разницей, что имя свойства - global_defs и является свойством компрессора:

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 } } });

Чтобы заменить идентификатор произвольным непостоянным выражением, необходимо global_defs ключу global_defs префикс "@" чтобы UglifyJS анализировал значение как выражение:

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

В противном случае он был бы заменен строковым литералом:

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

Использование собственного AST Uglify с minify 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

Трансверсия и преобразование собственного AST могут быть выполнены через TreeWalker и TreeTransformer соответственно.

ESTree / SpiderMonkey AST

UglifyJS имеет собственный формат абстрактного синтаксического дерева; по практическим соображениям мы не можем легко перейти на использование SpiderMonkey AST внутри. Однако в UglifyJS теперь есть конвертер, который может импортировать SpiderMonkey AST.

Например, Acorn - это сверхбыстрый синтаксический анализатор, который создает AST SpiderMonkey. У него есть небольшая утилита CLI, которая анализирует один файл и выводит AST в формате JSON на стандартный вывод. Чтобы использовать UglifyJS для искажения и сжатия этого:

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

Параметр -p spidermonkey сообщает UglifyJS, что все входные файлы - это не JavaScript, а код JS, описанный в AST SpiderMonkey в JSON. Поэтому в этом случае мы не используем наш собственный синтаксический анализатор, а просто преобразуем этот AST во внутренний AST.

Use Acorn for parsing

Для развлечения я добавил опцию -p acorn которая будет использовать Acorn для выполнения всего синтаксического анализа. Если вы передадите эту опцию, UglifyJS require("acorn") .

Acorn действительно быстр (например, 250 мс вместо 380 мс в коде 650K), но преобразование дерева SpiderMonkey, которое производит Acorn, занимает еще 150 мс, так что в целом это немного больше, чем просто использование собственного парсера UglifyJS.

Uglify Fast Minify Mode

Это малоизвестно, но удаление пробелов и искажение символов составляет 95% уменьшения размера минифицированного кода для большинства преобразований кода, не связанных с JavaScript. Можно просто отключить compress чтобы ускорить сборку Uglify в 3-4 раза. Режим mangle -only Uglify имеет сравнимые с butternut скорость butternut и размеры gzip:

d3.js уменьшить размер размер gzip минимизировать время (секунды)
оригинал 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

Чтобы включить режим быстрого уменьшения из интерфейса командной строки, используйте:

1
uglifyjs file.js -m

Чтобы включить быстрый режим минимизации с помощью API, используйте:

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

Исходные карты и отладка

Известно, что различные преобразования compress которые упрощают, переупорядочивают, встраивают и удаляют код, оказывают неблагоприятное влияние на отладку с исходными картами. Это ожидается, поскольку код оптимизирован, а сопоставления часто просто невозможны, так как некоторый код больше не существует. Для максимальной точности в Отладка исходной карты отключите параметр compress Uglify и просто используйте mangle .

Compiler assumptions

Чтобы обеспечить лучшую оптимизацию, компилятор делает различные предположения:

  • .toString() и .valueOf() не имеют побочных эффектов, и для встроенных объектов они не были переопределены.
  • undefined , NaN и Infinity не подвергались внешнему переопределению.
  • arguments.callee , arguments.caller и Function.prototype.caller не используются.
  • Код не ожидает, что содержимое Function.prototype.toString() или Error.prototype.stack будет чем-то конкретным.
  • Получение и установка свойств для простого объекта не вызывает других побочных эффектов (с использованием .watch() или Proxy ).
  • Object properties can be added , удалять и изменять (не предотвращается с помощью Object.defineProperty() , Object.defineProperties() , Object.freeze() , Object.preventExtensions() или Object.seal() ).