API参考
假如是通过NPM安装的,你可以这样在你的应用中加载UglifyJS:
var UglifyJS = require("uglify-js");
它会输出很多模块,但我在此只介绍一下涉及解释、混淆和压缩的基础代码。按(1)
解释, (2) 压缩, (3) 混淆, (4) 生成输出代码的顺序。
简易使用模式
minify
是一个顶级的、单独、包含所有步骤的方法。如果你不需要进一步自定义的话,你应该会喜欢使用它。
例子:
var result = UglifyJS.minify("/path/to/file.js");
console.log(result.code); // 最小化输出
// 假如你不想传一个文件名,而是要传入一段代码
var result = UglifyJS.minify("var b = function () {};", {fromString: true});
你也可以压缩多个文件:
var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ]);
console.log(result.code);
这样生成一份sourcemap:
var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ], {
outSourceMap: "out.js.map"
});
console.log(result.code); // 最小化输出
console.log(result.map);
你也可以用一个带fromString选项的对象来要生成sourcemap:
var result = UglifyJS.minify({"file1.js": "var a = function () {};"}, {
outSourceMap: "out.js.map",
outFileName: "out.js",
fromString: true
});
要注意,此时sourcemap并不会保存为一份文件,它只会返回在result.map
中。outSourceMap
的值只用来在result.code
中设置//# sourceMappingURL=out.js.map
,outFileName
的值只用来在sourcemap文件中设置 file
属性。
sourcemap(查阅规格)中的file
属性会优先使用 outFileName
,假如没有,会从outSourceMap
中推导(就是去掉'.map'
)。
你可以把sourceMapInline
设为true
,这样sourcemap会加在代码末尾。
你也可以指定sourcemap中的源文件根目录(sourceRoot)属性:
var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ], {
outSourceMap: "out.js.map",
sourceRoot: "http://example.com/src"
});
如果你要压缩从其他文件编译得来的带一份sourcemap的JS文件,你可以用inSourceMap
参数:
var result = UglifyJS.minify("compiled.js", {
inSourceMap: "compiled.js.map",
outSourceMap: "minified.js.map"
});
// 跟之前一样,返回 `code`和 `map`
如果你要输入的sourcemap并非一份单独文件,你可以在对象参数中设置inSourceMap
参数:
var result = UglifyJS.minify("compiled.js", {
inSourceMap: JSON.parse(my_source_map_string),
outSourceMap: "minified.js.map"
});
只有在需要outSourceMap
时, inSourceMap
才会被用到(否则就没用咯)。
要设置sourcemap的url的话,请用 sourceMapUrl
选项。
如果你要用X-SourceMap
请求头,你可以把sourceMapUrl
选项设为false。outSourceMap
的默认设置:
var result = UglifyJS.minify([ "file1.js" ], {
outSourceMap: "out.js.map",
sourceMapUrl: "localhost/out.js.map"
});
其他选项:
warnings
(默认false
) — 传true
来现实压缩器的警告fromString
(默认false
) — 传true
的话,你可以输入JS源码,而不是文件名。mangle
(默认true
) — 传false
来跳过混淆步骤,或者传一个对象来特定指明混淆选项(下面详述)。mangleProperties
(默认false
) — 传一个对象来自定义指明混淆对象属性的选项。output
(默认null
) — 如果你要进一步指定输出选项,请传一个对象。默认是压缩到最优化。compress
(默认{}
) — 传false
的话就跳过整个压缩步骤。自定义的话请传一个压缩选项对象。parse
(默认 {}) — 如果你要进一步自定义解释步骤请传一个解释选项对象(不是所有选项都有效….下面再说)。
混淆
except
- 传一个应该排除在混淆之外的标识的数组。toplevel
— 混淆那些定义在顶层作用域的名字(默认禁用)。eval
— 混淆那些在with或eval中出现的名字(默认禁用)。keep_fnames
— 默认false
。传true
的话就不混淆函数名。对那些依赖Function.prototype.name
的代码有用。延展阅读:keep_fnames
压缩选项.
例子:
//tst.js
var globalVar;
function funcName(firstLongName, anotherLongName)
{
var myVariable = firstLongName + anotherLongName;
}
UglifyJS.minify("tst.js").code;
// 'function funcName(a,n){}var globalVar;'
UglifyJS.minify("tst.js", { mangle: { except: ['firstLongName'] } }).code;
// 'function funcName(firstLongName,a){}var globalVar;'
UglifyJS.minify("tst.js", { mangle: { toplevel: true } }).code;
// 'function n(n,a){}var a;'
混淆属性名选项
regex
— 传一个正则,仅混淆匹配到的名字。(与--mangle-regex
CLI参数选项关联)ignore_quoted
– 只混淆非括号中的属性名(与--mangle-props 2
CLI 参数选项关联)debug
– 让混淆后的名字与原名字有关。与--mangle-props-debug
CLI 参数选项关联)。默认是false
。传一个空字符串来启用,或者传一个非空字符串来添加后缀。
高级使用模式
如果minify
函数太简单不能满足你的需求,下面这些API信息有更多的细节详情:
解释器
var toplevel_ast = UglifyJS.parse(code, options);
options
是可选的,要传的话就必须传个对象。下面这些是有效的属性:
strict
— 禁用自动添加分号,禁止数组、对象末尾还有逗号。bare_returns
— 允许函数返回外部。(与--bare-returns
CLI参数选项关联,对minify
parse
选项对象也有效。)filename
— 输入的文件名。toplevel
— 一个toplevel
节点。 (就是之前调用parse
返回的)
后面两个选项是当你要最小化多个文件成一个文件(以及正确的sourcemap)时有用。我们的CLI会像这样处理:
var toplevel = null;
files.forEach(function(file){
var code = fs.readFileSync(file, "utf8");
toplevel = UglifyJS.parse(code, {
filename: file,
toplevel: toplevel
});
});
完成后,我们就在toplevel
这个大AST里包含了我们的所有文件,每一份都带着正确的来源信息。
作用域信息
UglifyJS包含一个作用域分析器,你可以在压缩、混淆前手动调用。基本上,它添加了AST中的节点在哪里被命名、被引用了多少次、是否全局的、是否在eval
或with
中声明等等。我们将讨论除此之外的,那些在你对AST进行任何操作前必须知道的重要事项:
toplevel.figure_out_scope()
压缩
就如这样:
var compressor = UglifyJS.Compressor(options);
var compressed_ast = compressor.compress(toplevel);
options
可以不要。之前的“压缩器选项“中已经讲过可以填什么。默认选项对大多数脚本来说应该都是最佳的。
压缩器是破坏性的,所以不要依赖那些源树toplevel
。
混淆
压缩之后再调用一次figure_out_scope
是个好做法(因为压缩过程可能会干掉一些没用的、不可达的代码,改变标识的数量和位置),你也可以选择在Gzip(统计不可混淆的词中字符的使用频率)后调用。例如:
compressed_ast.figure_out_scope();
compressed_ast.compute_char_frequency();
compressed_ast.mangle_names();
生成输出代码
AST节点带一个print
方法,用来生成输出流。基本上,要生成代码你只要这么做:
var stream = UglifyJS.OutputStream(options);
compressed_ast.print(stream);
var code = stream.toString(); // 这就是你最小化后的代码
又或者这样缩写:
var code = compressed_ast.print_to_string(options);
通常情况下options
是可选的。输出流可以接收一堆选项参数,绝大多数在”美化选项“中有阐述。我们所关心的是source_map
和 comments
选项。
在输出代码中保留注释
你需要传入comments
选项来保留某些注释。你可以传正则表达式(以/
包裹或正则对象)、布尔值或函数。也可以传字符串all
或 some
,some
等同于CLI中--comments
不带任何参数。如果你传正则,只有匹配到的注释会被保留。注意,匹配的主体不包括 //
或 /*
。如果你传函数,每遇到树中的注释都会调用一下,传入两个参数,一是注释所依附的节点,二是注释标识本身。
注释标识有如下属性:
type
: 单行注释是”comment1”,多行注释 “comment2”。value
: 注释体本身。pos
和endpos
: 注释在源码中出现的起始位置/结束位置(从0开始索引)。line
和col
: 注释在源码中出现的行和列。file
— 源码的文件名nlb
— 在源码中,如果注释前有一空行或注释另起新一行的话是true
你的函数返回true
的话就保留注释,其他返回值都代表false。
生成sourcemap
你需要在调用print
时传source_map
参数。source_map
参数需要是SourceMap
对象(在source-map库顶部有个小框框里说了)。
例子:
var source_map = UglifyJS.SourceMap(source_map_options);
var stream = UglifyJS.OutputStream({
...
source_map: source_map
});
compressed_ast.print(stream);
var code = stream.toString();
var map = source_map.toString(); // 输出json格式sourcemap
source_map_options
(可选)包含以下属性:
file
: 被输出的、sourcemap所映射的JS的文件名root
:sourceRoot
属性 (详看 规格)orig
: “original source map”,方便你想让sourcemap映射到生成JS的源码上。此参数可以只是字符串或json,也可以是包含源码sourcemap的json对象。
兼容版
Harmony
如果你想使用能最小化ES6+的实验性质的兼容分支,请在你的package.json
文件中加上下面代码:
"uglify-js": "git+https://github.com/mishoo/UglifyJS2.git#harmony"
或者直接安装兼容实验版UglifyJS:
npm install --save-dev uglify-js@github:mishoo/UglifyJS2#harmony
更多细节请看 #448