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 для использования в качестве приложения командной строки:
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 предполагает, что используется HTTPX-SourceMap
, и опускает директиву//# 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
. 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
).
Пример:
1uglifyjs file.js -c toplevel,sequences=false
Параметры изменения интерфейса командной строки
Чтобы включить диспетчер, вам необходимо передать --mangle
( -m
). Поддерживаются следующие параметры (разделенные запятыми):
toplevel
(по умолчаниюfalse
) - исключает имена, объявленные в области верхнего уровня.eval
(по умолчаниюfalse
) - исключает имена, видимые в областях, где используютсяeval
илиwith
.
Когда искажение включено, но вы хотите предотвратить искажение определенных имен, вы можете объявить эти имена с помощью --mangle reserved
- передать список имен, разделенных запятыми. Например:
1uglifyjs ... -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
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());
Чтобы это было --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
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
до 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 , the
3.x` API не бросает ошибки Для достижения подобного эффекта можно было бы сделать следующее.:
1
2var 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
) -passtrue
чтобы предотвратить удаление или искажение имен функций. Полезно для кода, основанного на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
как "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"
}
});
Если вы sourceMap.content
скомпилированный 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
заголовок 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 / continueinline
(по умолчанию: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
manglekeep_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
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
) -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 .
Разное
Keeping copyright notices or other comments
CAN Pass Вами --comments
Сохранять Определенная на комментарии вывод по умолчанию в IT-стиле Will Keep JSDoc, содержащие Комментарии «@preserve», «@license» или «@cc_on» (Условная компиляция для ИЭ) Пасс вы можете.. --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
с 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
ключу 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");'
Использование собственного 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 для искажения и сжатия этого:
1acorn 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 |
Чтобы включить режим быстрого уменьшения из интерфейса командной строки, используйте:
1uglifyjs file.js -m
Чтобы включить быстрый режим минимизации с помощью API, используйте:
1UglifyJS.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()
).