译者:李平海javascript
转载请注明原文连接(https://github.com/LiPinghai/... )与做者信息。html
此前翻译的UglifyJS2中文文档发布没多久UglifyJS3就发布了,囧,如今把本文档也更新成UglifyJS3版本。html5
与UglifyJS2相比API变更较大,简化较多,文档也增长了很多示例。java
因为webpack自己集成了UglifyJS插件(webpack.optimize.UglifyJsPlugin),其命令webpack -p
即表示调用UglifyJS来压缩代码,还有很多webpack插件如html-webpack-plugin
也会默认使用UglifyJS。所以咱们其实常常要用到它,但UglifyJS自己配置较复杂/选项繁多,又没有中文文档,使用起来如坠云雾。鉴于此特翻译此文,谬误甚多,敬请斧正。node
词典:webpack
parse 解释 compress 压缩 mangle 混淆 beautify 美化 minify 最小化 CLI 命令行工具 sourcemap 编译后代码对源码的映射,用于网页调试 AST 抽象语法树 name 名字,包括变量名、函数名、属性名 toplevel 顶层做用域 unreachable 不可达代码 option 选项/配置 STDIN 标准输入,指在命令行中直接输入 STDOUT 标准输出 STDERR 标准错误输出 side effects函数反作用,即函数除了返回外还产生别的做用,好比改了全局变量 shebang 释伴(#!)
如下为正文:git
UglifyJS 是一个js 解释器、最小化器、压缩器、美化器工具集(parser, minifier, compressor or beautifier toolkit)。github
uglify-js@3
的API 和 CLI已简化,再也不向后兼容 uglify-js@2
.web
UglifyJS 2.x
文档在这里.正则表达式
uglify-js
只支持 ECMAScript 5 (ES5).
假如但愿压缩 ES2015+ (ES6+)代码,应该使用 uglify-es这个npm
包。
首先确认一直你已经安装了最新的node.js(装完后或许须要重启一下电脑)
用NPM安装CLI:
npm install uglify-js -g
用NPM下载给程序使用:
npm install uglify-js
uglifyjs [input files] [options]
UglifyJS能够输入多文件。建议你先写输入文件,再传选项。UglifyJS会根据压缩选项,把文件放在队列中依次解释。全部文件都会在同一个全局域中,假如一个文件中的变量、方法被另外一文件引用,UglifyJS会合理地匹配。
假如没有指定文件,UglifyJS会读取输入字符串(STDIN)。
若是你想要把选项写在文件名的前面,那要在两者以前加上双横线,防止文件名被当成了选项:
uglifyjs --compress --mangle -- input.js
-h, --help 列出使用指南。 `--help options` 获取可用选项的详情。 -V, --version 打印版本号。 -p, --parse <options> 指定解析器配置选项: `acorn` 使用 Acorn 来解析。 `bare_returns` 容许在函数外return。 在压缩CommonJS模块或`.user.js `引擎调用被同步执行函数包裹的用户脚本 时会用到。 `expression` 不是解析文件,二是解析一段表达式 (例如解析JSON). `spidermonkey` 输入文件是 SpiderMonkey AST 格式 (JSON). -c, --compress [options] 启用压缩(true/false)/指定压缩配置: `pure_funcs` 传一个函数名的列表,当这些函数返回值没被利用时,该函数会被安全移除。 -m, --mangle [options] 启用混淆(true/false)/指定混淆配置: `reserved` 不被混淆的名字列表。 --mangle-props [options] 混淆属性/指定压缩配置: `builtins` 混淆那些与标准JS全局变量重复的名字。 `debug` 添加debug前缀和后缀。 `domprops` 混淆那些鱼DOM属性名重复的名字。 `keep_quoted` 只混淆没括起来的属性名。 `regex` 只混淆匹配(该正则)的名字。 `reserved` 不须要混淆的名字的列表(即保留)。 -b, --beautify [options] 是否美化输出(true/false)/指定输出配置: `beautify` 默认是启用. `preamble` 预设的输出文件头部。你能够插入一段注释,好比版权信息。它不会被解析,但sourcemap会所以调整。 `quote_style` 括号类型: 0 - auto自动 1 - single单引号 2 - double双引号 3 - original跟随原码 `wrap_iife` 把当即执行函数括起来。注意:你或许应禁用压缩配置中的`negate_iife`选项。 -o, --output <file> 输出文件路径 (默认 STDOUT). 指定 `ast` 或 `spidermonkey`的话分别是输出UglifyJS或SpiderMonkey AST。 --comments [filter] 保留版权注释。默认像Google Closure那样,保留包含"@license"或"@preserve"这样JSDoc风格的注释。你能够传如下的参数: - "all" 保留所有注释 - 一个合适的正则,如 `/foo/` 或 `/^!/`,保留匹配到的注释。 注意,在启用压缩时,由于死代码被移除或压缩声明为一行,并不是*全部*的注释都会被保留。 --config-file <file> 今后JSON文件读取 `minify()` 配置。 -d, --define <expr>[=value] 定义全局变量。 --ie8 支持IE8。 等同于在`minify()`的`compress`、 `mangle` 和 `output`配置设置`ie8: true`。UglifyJS不会默认兼容IE8。 --keep-fnames 不要混淆、干掉的函数的名字。当代码依赖Function.prototype.name时有用。 --name-cache <file> 用来保存混淆map的文件。 --self 把UglifyJS自己也构建成一个依赖包 (等同于`--wrap UglifyJS`) --source-map [options] 启用 source map(true/false)/指定sourcemap配置: `base` 根路径,用于计算输入文件的相对路径。 `content` 输入sourcemap。假如的你要编译的JS是另外的源码编译出来的。 假如该sourcemap包含在js内,请指定"inline"。 `filename` 输出文件的名字或位置。 `includeSources` 若是你要在sourcemap中加上源文件的内容做sourcesContent属性,就传这个参数吧。 `root` 此路径中的源码编译后会产生sourcemap. `url` 若是指定此值,会添加sourcemap相对路径在`//#sourceMappingURL`中。 --timings 在STDERR显示操做运行时间。 --toplevel 压缩/混淆在最高做用域中声明的变量名。 --verbose 打印诊断信息。 --warn 打印警告信息。 --wrap <name> 把全部代码包裹在一个大函数中。让“exports”和“global”变量有效。 你须要传一个参数来指定此模块的名字,以便浏览器引用。
指定--output
(-o
)来明确输出文件,不然将在终端输出(STDOUT)
UglifyJS能够生成一份sourcemap文件,这很是有利于你调试压缩后的JS代码。传--source-map --output output.js
来获取sorcemap文件(sorcemap会生成为output.js.map
)。
额外选项:
--source-map filename=<NAME>
指定sourcemap名字。
--source-map root=<URL>
传一个源文件的路径。不然UglifyJS将假定已经用了HTTPX-SourceMap
,并将省略//#sourceMappingURL=
指示。
--source-map url=<URL>
指定生成sourcemap的路径。
例如:
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
和sourcemapfoo.min.js.map
,sourcemap会创建http://foo.com/src/js/file1.js
、http://foo.com/src/js/file2.js
的映射。(实际上,sourcemap根目录是http://foo.com/src
,因此至关于源文件路径是js/file1.js
、js/file2.js
)
假如你的JS代码是用其余编译器(例如coffeescript)生成的,那么映射到JS代码就没什么用了,你确定但愿映射到CoffeeScript源码。UglifyJS有一个选项能够输入sourcemap,假如你有一个从CoffeeScript → 编译后JS的map的话,UglifyJS能够生成一个从CoffeeScript->压缩后JS的map映射到源码位置。
你能够传入 --source-map content="/path/to/input/source.map"
或来尝试此特性,若是sourcemap包含在js内,则写 --source-map content=inline
。
你须要传入--mangle
(-m
)来使启用混淆功能。支持如下选项(用逗号隔开):
toplevel
— 混淆在最高做用域中声明的变量名(默认disabled)
eval
- 混淆在eval
或 with
做用域出现的变量名(默认disabled)
当启用混淆功能时,若是你但愿保留一些名字不被混淆,你能够用--mangle reserved
声明一些名字(用逗号隔开)。例如:
uglifyjs ... -m reserved=[$,require,exports]'
这样能防止require
, exports
和 $
被混淆改变。
--mangle-props
)--mangle-props
)警告:这能会搞崩你的代码。混淆属性名跟混淆变量名不同,是相互独立的。传入--mangle-props
会混淆对象全部可见的属性名,除了DOM属性名和JS内置的类名。例如:
// 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());
混淆全部属性(除了JS内置的):
$ uglifyjs example.js -c -m --mangle-props
var x={o:0,_:1,l:function(){return this._+this.o}};x.t=2,x.o=3,console.log(x.l());
混淆除了 reserved
(保留)外的全部属性:
$ uglifyjs example.js -c -m --mangle-props reserved=[foo_,bar_]
var x={o:0,foo_:1,_:function(){return this.foo_+this.o}};x.bar_=2,x.o=3,console.log(x._());
混淆匹配regex
(正则)的属性:
$ uglifyjs example.js -c -m --mangle-props regex=/_$/
var x={o:0,_:1,calc:function(){return this._+this.o}};x.l=2,x.o=3,console.log(x.calc());
混用多个混淆属性选项:
$ uglifyjs example.js -c -m --mangle-props regex=/_$/,reserved=[bar_]
var 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=/^_/
,只混淆下划线开头的属性。
当你压缩多个文件时,为了保证让它们最终能同时工做,咱们要让他们中一样的属性名混淆成相同的结果。传入`--name-cache
filename.json`,UglifyJS会维护一个共同的映射供他们复用。这个json一开始应该是空的,例如:
$ 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
会知晓对方混淆的属性名。
假如你把全部文件压缩成同一个文件,那就不须要启用名字缓存了。
--mangle-props keep_quoted
)--mangle-props keep_quoted
)使用括号属性名 (o["foo"]
)以保留属性名(foo
)。这会让整个脚本中其他此属性的引用(o.foo
)也不被混淆。例如:
// stuff.js var o = { "foo": 1, bar: 3 }; o.foo += o.bar; console.log(o.foo);
$ uglifyjs stuff.js --mangle-props keep_quoted -c -m
var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);
为了混淆属性时不至于彻底分不清,你能够传入--mangle-props debug
来调试。例如o.foo
会被混淆成o._$foo$_
。这让源码量大、属性被混淆时也能够debug,能够看清混淆会把哪些属性搞乱。
$ uglifyjs stuff.js --mangle-props debug -c -m
var o={_$foo$_:1,_$bar$_:3};o._$foo$_+=o._$bar$_,console.log(o._$foo$_);
你能够用--mangle-props-debug=XYZ
来传入自定义后缀。让o.foo
混淆成 o._$foo$XYZ_
, 你能够在每次编译是都改变一下,来辨清属性名怎么被混淆的。一个小技巧,你能够每次编译时传随机数来模仿混淆操做(例如你更新了脚本,有了新的属性名),这有助于识别混淆时的出错。
假如是经过NPM安装的,你能够在你的应用中这样加载UglifyJS:
var UglifyJS = require("uglify-js");
这输出一个高级函数minify(code, options)
,它能根据配置,实现多种最小化(即压缩、混淆等)。 minify()
默认启用压缩和混淆选项。例子:
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}
你能够经过一个对象(key为文件名,value为代码)来同时最小化
多个文件:
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
选项例子:
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
选项例子:
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));
你能够像下面这样把名字缓存保存在文件中:
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()
选项的例子:
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);"
生成警告提示:
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}
生成错误提示:
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}
Note: unlike uglify-js@2.x
, the 3.x
API does not throw errors. To
achieve a similar effect one could do the following:
var result = UglifyJS.minify(code, options); if (result.error) throw result.error;
warnings
(default false
) — 传 true
的话,会在result.warnings
中返回压缩过程的警告。传 "verbose"
得到更详细的警告。
parse
(default {}
) — 若是你要指定额外的解析配置parse options,传配置对象。
compress
(default {}
) — 传false
就彻底跳过压缩。传一个对象来自定义 压缩配置compress options。
mangle
(default true
) — 传 false
就跳过混淆名字。传对象来指定混淆配置mangle options (详情以下).
mangle.properties
(default false
) — 传一个对象来自定义混淆属性配置mangle property options.
output
(default null
) — 要自定义就传个对象来指定额外的 输出配置output options. 默认是压缩到最优化。
sourceMap
(default false
) - 传一个对象来自定义
sourcemap配置source map options.
toplevel
(default false
) - 若是你要混淆(和干掉没引用的)最高做用域中的变量和函数名,就传true
。
nameCache
(default null
) - 若是你要缓存 minify()
多处调用的经混淆的变量名、属性名,就传一个空对象{}
或先前用过的nameCache
对象。
注意:这是个可读/可写属性。minify()
会读取这个对象的nameCache状态,并在最小化过程当中更新,以便保留和供用户在外部使用。
ie8
(default false
) - 传 true
来支持 IE8.
{ warnings: false, 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, }
这样生成sourcemap:
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
要注意,此时sourcemap并不会保存为一份文件,它只会返回在result.map
中。sourceMap.url
传入的值只用来在result.code
中设置//# sourceMappingURL=out.js.map
,filename
的值只用来在sourcemap文件中设置 file
属性(详情看 规范)。
你能够把sourceMap.url
设为true
,这样sourcemap会加在代码末尾。
你也能够指定sourcemap中的源文件根目录(sourceRoot)属性:
var result = UglifyJS.minify({"file1.js": "var a = function() {};"}, { sourceMap: { root: "http://example.com/src", url: "out.js.map" } });
若是你要压缩从其余文件编译得来的带一份sourcemap的JS文件,你能够用sourceMap.content
参数:
var result = UglifyJS.minify({"compiled.js": "compiled code"}, { sourceMap: { content: "content from compiled.js.map", url: "minified.js.map" } }); // same as before, it returns `code` and `map`
若是你要用 X-SourceMap
请求头,你能够忽略 sourceMap.url
。
bare_returns
(default false
) -- 支持在顶级做用域中 return
声明。
html5_comments
(default true
)
shebang
(default true
) -- 支持在第一行用 #!command
sequences
(default: true) -- 连续声明变量,用逗号隔开来。能够设置为正整数来指定连续声明的最大长度。若是设为true
表示默认200
个,设为false
或0
则禁用。 sequences
至少要是2
,1
的话等同于true
(即200
)。默认的sequences设置有极小概率会致使压缩很慢,因此推荐设置成20
或如下。
properties
-- 用.
来重写属性引用,例如foo["bar"] → foo.bar
dead_code
-- 移除没被引用的代码
drop_debugger
-- 移除 debugger;
unsafe
(default: false) -- 使用 "unsafe"转换 (下面详述)
unsafe_comps
(default: false) -- 保留<
和 <=
不被换成 >
和 >=
。假如某些运算对象是用get
或 valueOf
object得出的时候,转换可能会不安全,可能会引发运算对象的改变。此选项只有当 comparisons
和unsafe_comps
都设为true时才会启用。
unsafe_Func
(default: false) -- 当 Function(args, code)
的args
和 code
都是字符串时,压缩并混淆。
unsafe_math
(default: false) -- 优化数字表达式,例如2 * x * 3
变成 6 * x
, 可能会致使不精确的浮点数结果。
unsafe_proto
(default: false) -- 把Array.prototype.slice.call(a)
优化成 [].slice.call(a)
unsafe_regexp
(default: false) -- 若是RegExp
的值是常量,替换成变量。
conditionals
-- 优化if
等判断以及条件选择
comparisons
-- 把结果必然的运算优化成二元运算,例如!(a <= b) → a > b
(只有设置了 unsafe_comps
时才生效);尽可能转成否运算。例如 a = !b && !c && !d && !e → a=!(b||c||d||e)
evaluate
-- 尝试计算常量表达式
booleans
-- 优化布尔运算,例如 !!a? b : c → a ? b : c
typeofs
-- 默认 true
. 转换 typeof foo == "undefined"
成 foo === void 0
. 注意:若是要适配IE10或如下,因为已知的问题,推荐设成false
。
loops
-- 当do
、while
、 for
循环的判断条件能够肯定是,对其进行优化。
unused
-- 干掉没有被引用的函数和变量。(除非设置"keep_assign"
,不然变量的简单直接赋值也不算被引用。)
toplevel
-- 干掉顶层做用域中没有被引用的函数 ("funcs"
)和/或变量("vars"
) (默认是false
, true
的话即函数变量都干掉)
top_retain
-- 当设了unused
时,保留顶层做用域中的某些函数变量。(能够写成数组,用逗号隔开,也能够用正则或函数. 参考toplevel
)
hoist_funs
-- 提高函数声明
hoist_vars
(default: false) -- 提高 var
声明 (默认是false
,由于那会加大文件的size)
if_return
-- 优化 if/return 和 if/continue
inline
-- 包裹简单函数。
join_vars
-- 合并连续 var
声明
cascade
-- 弱弱地优化一下连续声明, 将 x, x
转成 x
,x = something(), x
转成 x = something()
collapse_vars
-- 当 var
和 const
单独使用时尽可能合并
reduce_vars
-- 优化某些变量其实是按常量值来赋值、使用的状况。
warnings
-- 当删除没有用处的代码时,显示警告
negate_iife
-- 当当即执行函数(IIFE)的返回值没用时,取消之。避免代码生成器会插入括号。
pure_getters
-- 默认是 false
. 若是你传入true
,UglifyJS会假设对象属性的引用(例如foo.bar
或 foo["bar"]
)没有函数反作用。
pure_funcs
-- 默认 null
. 你能够传入一个名字的数组,UglifyJS会假设这些函数没有函数反作用。警告:假如名字在做用域中从新定义,不会再次检测。例如var q = Math.floor(a/b)
,假如变量q
没有被引用,UglifyJS会干掉它,但 Math.floor(a/b)
会被保留,没有人知道它是干吗的。你能够设置pure_funcs: [ 'Math.floor' ]
,这样该函数会被认为没有函数反作用,这样整个声明会被废弃。在目前的执行状况下,会增长开销(压缩会变慢)。
drop_console
-- 默认 false
. 传true
的话会干掉console.*
函数。若是你要干掉特定的函数好比console.info
,又想删掉后保留其参数中的反作用,那用pure_funcs
来处理吧。
expression
-- 默认 false
。传true
来保留终端语句中没有"return"的完成值。例如在bookmarklets。
keep_fargs
-- 默认true
。阻止压缩器干掉那些没有用到的函数参数。你须要它来保护某些依赖Function.length
的函数。
keep_fnames
-- 默认 false
。传 true
来防止压缩器干掉函数名。对那些依赖Function.prototype.name
的函数颇有用。延展阅读:keep_fnames
混淆选项.
passes
-- 默认 1
。运行压缩的次数。在某些状况下,用一个大于1的数字参数能够进一步压缩代码大小。注意:数字越大压缩耗时越长。
keep_infinity
-- 默认 false
。传true
以防止压缩时把1/0
转成Infinity
,那可能会在chrome上有性能问题。
side_effects
-- 默认 true
. 传false
禁用丢弃纯函数。若是一个函数被调用前有一段/*@__PURE__*/
or /*#__PURE__*/
注释,该函数会被标注为纯函数。例如 /*@__PURE__*/foo();
reserved
(default []
)。 传一个不须要混淆的名字的数组。 Example: ["foo", "bar"]
.
toplevel
(default false
)。混淆那些定义在顶层做用域的名字(默认禁用)。ß
keep_fnames
(default false
)。传true
的话就不混淆函数名。对那些依赖Function.prototype.name
的代码有用。延展阅读:keep_fnames
压缩配置.
eval
(default false
)。混淆那些在with或eval中出现的名字。
// test.js var globalVar; function funcName(firstLongName, anotherLongName) { var myVariable = firstLongName + anotherLongName; }
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;'
reserved
(default: []
) -- 不混淆在reserved
数组里的属性名.
regex
(default: null
) -— 传一个正则,只混淆匹配该正则的属性名。
keep_quoted
(default: false
) -— 只混淆不在括号内的属性名.
debug
(default: false
) -— 用原名字来组成混淆后的名字.
传空字符串""
来启用,或者非空字符串做为debu后缀。(例如"abc"
, foo.bar
=>foo.barabc
)
builtins
(default: false
) -- 传 true
的话,容许混淆内置的DOM属性名。不推荐使用。
代码生成器默认会尽可能输出最简短的代码。假如你要美化一下输出代码,能够传--beautify
(-b
)。你也能够传更多的参数来控制输出代码:
ascii_only
(default false
) -- 忽略字符串和正则(致使非ascii字符失效)中的Unicode字符。
beautify
(default true
) -- 是否美化输出代码。传-b
的话就是设成true。假如你想生成最小化的代码同时又要用其余设置来美化代码,你能够设-b beautify=false
。
bracketize
(default false
) -- 永远在if
, for
,do
, while
, with
后面加上大括号,即便循环体只有一句。
comments
(default false
) -- 传 true
或 "all"
保留所有注释,传 "some"
保留部分,传正则 (例如 /^!/
) 或者函数也行。
indent_level
(default 4) 缩进格数
indent_start
(default 0) -- 每行前面加几个空格
inline_script
(default false
) -- 避免字符串中出现</script
中的斜杠
keep_quoted_props
(default false
) -- 若是启用,会保留对象属性名的引号。
max_line_len
(default 32000) -- 最大行宽(压缩后的代码)
space-colon
(default true
) -- 在冒号后面加空格
preamble
(default null
) -- 若是要传的话,必须是字符串。它会被加在输出文档的前面。sourcemap会随之调整。例如能够用来插入版权信息。
preserve_line
(default false
) -- 传 true
就保留空行,但只在beautify
设为false
时有效。ß
quote_keys
(default false
) -- 传true
的话会在对象全部的键加上括号
quote_style
(default 0
) -- 影响字符串的括号格式(也会影响属性名和指令)。
0
-- 倾向使用双引号,字符串里还有引号的话就是单引号。
1
-- 永远单引号
2
-- 永远双引号
3
-- 永远是原本的引号
semicolons
(default true
) -- 用分号分开多个声明。若是你传false
,则总会另起一行,加强输出文件的可读性。(gzip前体积更小,gzip后稍大一点点)
shebang
(default true
) -- 保留开头的 shebang #!
(bash 脚本)
width
(default 80) -- 仅在美化时生效,设定一个行宽让美化器尽可能实现。这会影响行中文字的数量(不包括缩进)。当前本功能实现得不是很是好,但依然让美化后的代码可读性大大加强。
wrap_iife
(default false
) --传true
的话,把当即执行函数括起来。 更多详情看这里
#640
你能够传入--comments
让输出文件中保留某些注释。默认时会保留JSDoc-style的注释(包含"@preserve","@license" 或 "@cc_on"(为IE所编译))。你能够传入--comments all
来保留所有注释,或者传一个合法的正则来保留那些匹配到的注释。例如--comments /^!/
会保留/*! Copyright Notice */
这样的注释。
注意,不管如何,总会有些注释在某些状况下会丢失。例如:
function f() { /** @preserve Foo Bar */ function g() { // this function is never called } return something(); }
即便里面带有"@preserve",注释依然会被丢弃。由于内部的函数g
(注释所依附的抽象语法树节点)没有被引用、会被压缩器干掉。
书写版权信息(或其余须要在输出文件中保留的信息)的最安全位置是全局节点。
unsafe
`compress`配置unsafe
compress
option在某些刻意营造的案例中,启用某些转换有可能会打断代码的逻辑,但绝大部分状况下是安全的。你可能会想尝试一下,由于这毕竟会减小文件体积。如下是某些例子:
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
的
void 0
→ undefined
(假如做用域中有一个变量名叫"undefined";咱们这么作是由于变量名会被混淆成单字符)
Uglify会假设全局变量都是常量(无论是否在局部域中定义了),你能够用--define
(-d
)来实现定义全局变量。例如你传--define DEBUG=false
,UglifyJS会在输出中干掉下面代码:
if (DEBUG) { console.log("debug stuff"); }
你能够像--define env.DEBUG=false
这样写嵌套的常量。
在干掉那些永否的条件语句以及不可达代码时,UglifyJS会给出警告。如今没有选项能够禁用此特性,但你能够设置 warnings=false
来禁掉全部警告。
另外一个定义全局常量的方法是,在一个独立的文档中定义,再引入到构建中。例如你有一个这样的build/defines.js
:
const DEBUG = false; const PRODUCTION = true; // 等等
这样构建你的代码:
uglifyjs build/defines.js js/foo.js js/bar.js... -c
UglifyJS会注意到这些常量。由于它们没法改变,因此它们会被认为是没被引用而被照样干掉。若是你用const
声明,构建后还会被保留。若是你的运行环境低于ES六、不支持const
,请用var
声明加上reduce_vars
设置(默认启用)来实现。
你也能够经过程序API来设置编译配置。其中有差异的是一个压缩器属性global_defs
:
var result = UglifyJS.minify(fs.readFileSync("input.js", "utf8"), { compress: { dead_code: true, global_defs: { DEBUG: false } } });
在global_defs
配"@"
前缀的表达式,UglifyJS才会替换成语句表达式:
UglifyJS.minify("alert('hello');", { compress: { global_defs: { "@alert": "console.log" } } }).code; // returns: 'console.log("hello");'
不然会替换成字符串:
UglifyJS.minify("alert('hello');", { compress: { global_defs: { "alert": "console.log" } } }).code; // returns: '"console.log"("hello");'
minify()
得到原生UglifyJS astminify()
// 例子: 只解析代码,得到原生Uglify AST var result = UglifyJS.minify(code, { parse: {}, compress: false, mangle: false, output: { ast: true, code: false // optional - faster if false } }); // result.ast 便是原生 Uglify AST
// 例子: 输入原生 Uglify AST,接着把它压缩并混淆,生成代码和原生ast var result = UglifyJS.minify(ast, { compress: {}, mangle: {}, output: { ast: true, code: true // 可选,false更快 } }); // result.ast 是原生 Uglify AST // result.code 是字符串格式的最小化后的代码
能够经过TreeWalker
和TreeTransformer
分别横截(?transversal)和转换原生AST。
UglifyJS有本身的抽象语法树格式;为了某些现实的缘由
咱们没法在内部轻易地改为使用SpiderMonkey AST。但UglifyJS如今有了一个能够输入SpiderMonkeyAST的转换器。
例如Acorn ,这是一个超级快的生成SpiderMonkey AST的解释器。它带有一个实用的迷你CLI,能解释一个文件、把AST转存为JSON并标准输出。能够这样用UglifyJS来压缩混淆:
acorn file.js | uglifyjs --spidermonkey -m -c
-p --spidermonkey
选项能让UglifyJS知道输入文件并不是JavaScript,而是SpiderMonkey AST生成的JSON代码。这事咱们不用本身的解释器,只把AST转成咱们内部AST。
更有趣的是,咱们加了 -p --acorn
选项来使用Acorn解释全部代码。若是你传入这个选项,UglifyJS会require("acorn")
Acorn确实很是快(650k代码原来要380ms,如今只需250ms),但转换Acorn产生的SpiderMonkey树会额外花费150ms。因此总共比UglifyJS本身的解释器还要多花一点时间。
不多人知道,对大多数js代码而言,其实移除空格和混淆符号已经占了减小代码体积之中到的95%--没必要细致地转换。简单地禁用压缩compress
能加快UglifyJS的构建速度三四倍。咱们能够比较一下butternut
和只使用混淆mangle
的模式的Uglify的压缩速度与gzip大小:butternut
:
d3.js | minify size | gzip size | minify time (seconds) |
---|---|---|---|
original | 451,131 | 108,733 | - |
uglify-js@3.0.24 mangle=false, compress=false | 316,600 | 85,245 | 0.70 |
uglify-js@3.0.24 mangle=true, compress=false | 220,216 | 72,730 | 1.13 |
butternut@0.4.6 | 217,568 | 72,738 | 1.41 |
uglify-js@3.0.24 mangle=true, compress=true | 212,511 | 71,560 | 3.36 |
babili@0.1.4 | 210,713 | 72,140 | 12.64 |
在CLI中,这样启用快速最小化模式:
uglifyjs file.js -m
API这样用:
UglifyJS.minify(code, { compress: false, mangle: true });