УглифайДжС 3
UglifyJS — это набор инструментов для парсера, минификатора, сжатия и улучшения JavaScript JavaScript.
Примечание:
uglify-js@3
имеет упрощенный API и CLI , который не имеет обратной совместимости сuglify-js@2
.- Документацию к
2.x
релизам UglifyJS можно найти здесь . uglify-js
поддерживает только JavaScript (ECMAScript 5).- Чтобы минимизировать ECMAScript 2015 или более позднюю версию, выполните транспиляцию с помощью таких инструментов, как Babel .
Установить
Сначала убедитесь, что у вас установлена последняя версия node.js (после этого шага вам может потребоваться перезагрузить компьютер).
Из NPM для использования в качестве приложения командной строки:
1npm install uglify-js -g
Из NPM для программного использования:
1npm install uglify-js
Использование командной строки
1uglifyjs [input files] [options]
UglifyJS может принимать несколько входных файлов. Рекомендуется сначала передать входные файлы, а затем параметры. UglifyJS последовательно анализирует входные файлы и применяет любые параметры сжатия. Файлы анализируются в одной глобальной области, то есть по ссылке из файла в некоторую переменную/функцию, объявленную в другом файле, будет правильно сопоставляться.
Если входной файл не указан, UglifyJS будет читать из STDIN.
Если вы хотите передать параметры перед входными файлами, разделите их двойным тире, чтобы предотвратить использование входных файлов в качестве аргументов параметров:
1uglifyjs --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 предполагает,X-SourceMap
что используется HTTP, и пропустит//# sourceMappingURL=
директиву.
Например:
1
2
3uglifyjs 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
. Сопоставление источника будет ссылаться на 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
).
Пример:
1uglifyjs file.js -c toplevel,sequences=false
Параметры управления CLI
Чтобы включить манглер, вам необходимо передать --mangle
( -m
). Поддерживаются следующие параметры (через запятую):
toplevel
(по умолчаниюfalse
) — искажать имена, объявленные в области верхнего уровня.eval
(по умолчаниюfalse
) — имена искажений видны в областях, где используютсяeval
или .with
Если искажение включено, но вы хотите предотвратить искажение определенных имен, вы можете объявить эти имена с помощью --mangle reserved
— передать список имен, разделенных запятыми. Например:
1uglifyjs ... -m reserved=['$','require','exports']
чтобы предотвратить изменение имен require
и exports
.$
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());
Исказить все свойства (кроме JavaScript builtins
):
1$ uglifyjs example.js -c -m --mangle-props
1var 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_]
1var 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=/_$/
1var 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_]
1var x={o:0,_:1,calc:function(){return this._+this.o}};x.bar_=2,x.o=3,console.log(x.calc());
Чтобы это было полезно, мы избегаем искажения стандартных имен JS по умолчанию ( --mangle-props builtins
для переопределения).
Предоставляется файл исключений по умолчанию, tools/domprops.json
который должен охватывать большинство стандартных свойств JS и DOM, определенных в различных браузерах. Нажмите,
--mangle-props domprops
чтобы отключить эту функцию.
Регулярное выражение можно использовать для определения того, какие имена свойств следует искажать. Например, --mangle-props regex=/^_/
будут искажаться только те имена свойств, которые начинаются с подчеркивания.
Когда вы сжимаете несколько файлов с помощью этой опции, чтобы они в конечном итоге работали вместе, нам нужно каким-то образом гарантировать, что одно свойство будет преобразовано в одно и то же имя во всех них. Для этого pass --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
)
Использование имени свойства в кавычках ( o["foo"]
) резервирует имя свойства ( 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
1var 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
1var 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 в свое приложение следующим образом:
1var UglifyJS = require("uglify-js");
Существует одна функция высокого уровня, minify(code, options)
которая будет выполнять все этапы минимизации настраиваемым образом. По умолчанию minify()
включены параметры compress
и mangle
. Пример:
1
2
3
4var 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
7var 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
8var 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
16var 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
16var 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
21var 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
6var 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
3var 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
, 3.x
API не выдает ошибок.Для достижения аналогичного эффекта можно сделать следующее:
1
2var result = UglifyJS.minify(code, options);
if (result.error) throw result.error;
Минимизировать параметры
warnings
(по умолчаниюfalse
) — переходtrue
для возврата предупреждений компрессора вresult.warnings
. Используйте значение"verbose"
для более подробных предупреждений.parse
(по умолчанию{}
) — передайте объект, если вы хотите указать некоторые дополнительные параметры анализа .compress
(по умолчанию{}
) — перейдитеfalse
, чтобы полностью пропустить сжатие. Передайте объект, чтобы указать пользовательские параметры сжатия .mangle
(по умолчаниюtrue
) — передатьfalse
, чтобы пропустить искажение имен, или передать объект, чтобы указать параметры искажения (см. ниже).mangle.properties
(по умолчаниюfalse
) — подкатегория параметра mangle. Передайте объект, чтобы указать пользовательские параметры свойства mangle .
output
(по умолчаниюnull
) — передайте объект, если вы хотите указать дополнительные параметры вывода . Значения по умолчанию оптимизированы для наилучшего сжатия.sourceMap
(по умолчаниюfalse
) — передайте объект, если вы хотите указать параметры исходной карты .toplevel
(по умолчаниюfalse
) — установите,true
если вы хотите включить изменение имен переменных и функций верхнего уровня и удалить неиспользуемые переменные и функции.nameCache
(по умолчаниюnull
) — передать пустой объект{}
или ранее использованныйnameCache
объект, если вы хотите кэшировать искаженные имена переменных и свойств при нескольких вызовахminify()
. Примечание: это свойство доступно для чтения и записи.minify()
Прочитает состояние кэша имен этого объекта и обновит его. во время минимизации, чтобы пользователь мог повторно использовать или сохранять его извне.ie8
(по умолчаниюfalse
) — настроенаtrue
поддержка IE8.keep_fnames
(по умолчанию:false
) — передать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
8var 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
be "inline"
, и исходная карта будет добавлена к коду.
Вы также можете указать свойство sourceRoot для включения в исходную карту:
1
2
3
4
5
6var result = UglifyJS.minify({"file1.js": "var a = function() {};"}, {
sourceMap: {
root: "http://example.com/src",
url: "out.js.map"
}
});
Если вы сжимаете скомпилированный JavaScript и у вас есть карта исходного кода, вы можете использовать sourceMap.content
:
1
2
3
4
5
6
7var 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
) — Passtrue
для отмены вызовов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(o.p, o.q);
преобразуется вf(1, 2);
. Примечание:hoist_props
лучше всего работает, еслиmangle
параметр включен,compress
параметрpasses
установлен на2
значение или выше, аcompress
параметрtoplevel
включен.hoist_vars
(по умолчанию:false
) —var
объявления подъема (этоfalse
по умолчанию, потому что кажется, что это увеличивает размер вывода в целом)if_return
(по умолчанию:true
) — оптимизация для if/return и if/continueinline
(по умолчанию:true
) — встроенные вызовы функции с помощьюreturn
оператора simple/:false
--такой же как0
0
-- отключена встраивание1
-- встроенные простые функции2
-- встроенные функции с аргументами3
-- встроенные функции с аргументами и переменнымиtrue
--такой же как3
join_vars
(по умолчанию:true
) — объединить последовательныеvar
операторыkeep_fargs
(по умолчанию:true
) — не позволяет компрессору отбрасывать неиспользуемые аргументы функции. Это необходимо для кода, который используетFunction.length
.keep_fnames
(по умолчанию:false
) -- Пропуститеtrue
, чтобы компрессор не отбрасывал имена функций. Полезно для кода, использующегоFunction.prototype.name
. См. также:keep_fnames
опция mangle .keep_infinity
(по умолчанию:false
) — используйтеtrue
для предотвращенияInfinity
сжатия в1/0
, что может вызвать проблемы с производительностью в Chrome.loops
(по умолчанию:true
) — оптимизация для и цикловdo
, когда мы можем статически определить условие.while
for
negate_iife
(по умолчанию:true
) — отрицание «выражений с немедленным вызовом функций», при которых возвращаемое значение отбрасывается, чтобы избежать круглых скобок, которые вставляет генератор кода.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
) — переходfalse
для отключения потенциально удаляемых функций, помеченных как «чистые». Вызов функции помечается как «чистый», если аннотация комментария/*@__PURE__*/
или/*#__PURE__*/
непосредственно предшествует вызову. Например:/*@__PURE__*/foo();
switches
(по умолчанию:true
) — дедупликация и удаление недоступныхswitch
ветвейtoplevel
(по умолчанию:false
) — удалить неиспользуемые функции ("funcs"
) и/или переменные ("vars"
) в области верхнего уровня (false
по умолчанию,true
чтобы удалить как неиспользуемые функции, так и переменные)top_retain
(по умолчанию:null
) — предотвращает удаление определенных функций и переменных верхнего уровняunused
(может быть массивом, через запятую, RegExp или function. Implisestoplevel
)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
in6 * 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
) — передатьtrue
, чтобы не искажать имена функций.Полезно для кода, использующего .СмFunction.prototype.name
. также: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
10var 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
) — Искажать только имена свойств без кавычек.regex
(по умолчанию:null
) — Передайте литерал RegExp, чтобы изменить только имена свойств, соответствующие регулярному выражению.reserved
(по умолчанию:[]
) — Не искажать имена свойств, перечисленные вreserved
массиве.
Варианты вывода
По умолчанию генератор кода пытается вывести как можно более короткий код. Если вы хотите улучшить вывод, передайте --beautify
( -b
). При желании вы можете передать дополнительные аргументы, управляющие выводом кода:
ascii_only
(по умолчаниюfalse
) — экранирование символов Юникода в строках и регулярных выражениях (влияет на директивы, в которых символы, отличные от 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_style
(по умолчанию0
) — предпочтительный стиль кавычек для строк (также влияет на имена свойств и директивы в кавычках):0
-- предпочитает двойные кавычки, переключается на одинарные кавычки, когда в самой строке больше двойных кавычек.0
Лучше всего подходит для размера gzip.1
-- всегда используйте одинарные кавычки2
-- всегда используйте двойные кавычки3
-- всегда используйте оригинальные кавычки
semicolons
(по умолчаниюtrue
) -- отдельные операторы с точкой с запятой. Если вы передадите,false
то, когда это возможно, мы будем использовать новую строку вместо точки с запятой, что приведет к более читаемому выводу искаженного кода (размер до gzip мог бы быть меньше; размер после gzip незначительно больше).shebang
(по умолчаниюtrue
) — сохранить шебанг#!
в преамбуле (скрипты bash)webkit
(по умолчаниюfalse
) — включить обходные пути для ошибок WebKit.Пользователям PhantomJS следует установить для этой опции значениеtrue
.width
(по умолчанию80
) — действует только тогда, когда украшение включено. Это определяет (ориентирующую) ширину линии, которой будет пытаться соответствовать средство украшения. Это относится к ширине текста строки (исключая отступы). Это работает не очень хорошо. в настоящее время, но это делает код, сгенерированный UglifyJS, более читабельным.wrap_iife
(по умолчаниюfalse
) — переходtrue
к переносу немедленно вызываемых функциональных выражений. Подробнее см. #640 .
Разнообразный
Keeping copyright notices or other comments
Вы можете передать --comments
, чтобы сохранить определенные комментарии в выходных данных. По умолчанию будут сохраняться комментарии в стиле JSDoc, содержащие "@preserve", "@license" или "@cc_on" (условная компиляция для IE). Вы можете передать,
--comments all
чтобы сохранить все комментарии или допустимое регулярное выражение JavaScript, чтобы сохранять только комментарии, соответствующие этому регулярному выражению. Например, --comments /^!/
будут сохраняться комментарии типа /*! Copyright Notice */
.
Однако учтите, что могут возникнуть ситуации, когда комментарии теряются, например:
1
2
3
4
5
6
7function 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
3if (DEBUG) {
console.log("debug stuff");
}
Вы можете указать вложенные константы в форме --define env.DEBUG=false
.
UglifyJS будет предупреждать о том, что условие всегда ложно и об удалении недостижимого кода; на данный момент нет возможности отключить только это конкретное предупреждение, вы можете отключить warnings=false
все предупреждения .
Другой способ сделать это — объявить глобальные переменные как константы в отдельном файле и включить их в сборку. Например, у вас может быть файл
build/defines.js
со следующим:
1
2
3var DEBUG = false;
var PRODUCTION = true;
// etc.
и создайте свой код следующим образом:
1uglifyjs build/defines.js js/foo.js js/bar.js... -c
UglifyJS заметит константы и, поскольку их нельзя изменить, он оценит ссылки на них как само значение и отбросит недоступный код, как обычно. Сборка будет содержать объявления, const
если вы их используете. Если вы ориентируетесь на среду < ES6, которая делает не поддерживается const
, использования var
with reduce_vars
(включено по умолчанию) должно быть достаточно.
Conditional compilation API
Вы также можете использовать условную компиляцию через программный API, с той разницей, что имя свойства global_defs
является свойством компрессора:
1
2
3
4
5
6
7
8var result = UglifyJS.minify(fs.readFileSync("input.js", "utf8"), {
compress: {
dead_code: true,
global_defs: {
DEBUG: false
}
}
});
Чтобы заменить идентификатор произвольным непостоянным выражением, необходимо добавить global_defs
к ключу префикс, "@"
чтобы указать UglifyJS проанализировать значение как выражение:
1
2
3
4
5
6
7
8UglifyJS.minify("alert('hello');", {
compress: {
global_defs: {
"@alert": "console.log"
}
}
}).code;
// returns: 'console.log("hello");'
В противном случае он будет заменен строковым литералом:
1
2
3
4
5
6
7
8UglifyJS.minify("alert('hello');", {
compress: {
global_defs: {
"alert": "console.log"
}
}
}).code;
// returns: '"console.log"("hello");'
Использование собственного Uglify AST с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
Трансверсализацию и трансформацию нативного АСТ можно осуществлять посредством
TreeWalker
и
TreeTransformer
соответственно.
ESTree / SpiderMonkey AST
UglifyJS имеет свой собственный формат абстрактного синтаксического дерева; по практическим соображениям мы не можем легко перейти на внутреннее использование AST SpiderMonkey. Однако в UglifyJS теперь есть конвертер, который может импортировать AST SpiderMonkey.
Например, Acorn — это сверхбыстрый парсер, который создает AST SpiderMonkey. У него есть небольшая утилита CLI, которая анализирует один файл и выводит AST в формате JSON на стандартный вывод. Чтобы использовать UglifyJS для искажения и сжатия этого:
1acorn file.js | uglifyjs -p spidermonkey -m -c
Опция -p spidermonkey
сообщает UglifyJS, что все входные файлы — это не JavaScript, а код JS, описанный в SpiderMonkey AST в JSON. Поэтому в этом случае мы не используем собственный парсер, а просто преобразуем этот AST во внутренний AST.
Use Acorn for parsing
Для развлечения я добавил -p acorn
опцию, которая будет использовать Acorn для выполнения всего синтаксического анализа. Если вы укажете эту опцию, UglifyJS будет использовать require("acorn")
.
Acorn действительно быстр (например, 250 мс вместо 380 мс для кода размером 650 КБ), но преобразование дерева SpiderMonkey, которое создает Acorn, занимает еще 150 мс, так что в целом это немного больше, чем просто использование собственного синтаксического анализатора UglifyJS.
Uglify Fast Minify Mode
Это малоизвестно, но удаление пробелов и искажение символов обеспечивают 95% уменьшения размера минимизированного кода для большинства JavaScript, а не сложные преобразования кода.Можно просто отключить, compress
чтобы ускорить сборку Uglify в 3-4 раза.В этом быстром mangle
- Единственный режим Uglify имеет сравнимую скорость минимизации и размеры gzip с
butternut
:
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 |
орех @ 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 |
Чтобы включить режим быстрого минимизации из CLI, используйте:
1uglifyjs file.js -m
Чтобы включить режим быстрого минимизации с помощью API, используйте:
1UglifyJS.minify(code, { compress: false, mangle: true });
Исходные карты и отладка
Известно, что различные compress
преобразования, которые упрощают, реорганизуют, встраивают и удаляют код, отрицательно влияют на отладку с использованием карт исходного кода. Это ожидаемо, поскольку код оптимизирован, а сопоставления часто просто невозможны, поскольку некоторый код больше не существует. Для максимальной точности исходного кода отладка карты отключите опцию Uglify compress
и просто используйте mangle
.
Compiler assumptions
Чтобы обеспечить лучшую оптимизацию, компилятор делает различные предположения:
.toString()
и.valueOf()
не имеют побочных эффектов, а для встроенных объектов они не переопределяются.undefined
иNaN
неInfinity
были переопределены извне.arguments.callee
,arguments.caller
иFunction.prototype.caller
не используются.- Код не ожидает, что содержимое
Function.prototype.toString()
будетError.prototype.stack
чем-то конкретным. - Получение и установка свойств простого объекта не вызывает других побочных эффектов (использование
.watch()
илиProxy
). - Свойства объекта можно добавлять, удалять и изменять (это не запрещено с помощью
,
Object.defineProperty()
,Object.defineProperties()
или ) .Object.freeze()
Object.preventExtensions()
Object.seal()