譯者:李平海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 });