UglifyJS中文文档
UglifyJS中文文檔
譯者:李平海
轉載請注明原文鏈接(https://github.com/LiPinghai/... )與作者信息。
譯序
由于webpack本身集成了UglifyJS插件(webpack.optimize.UglifyJsPlugin),其命令webpack -p即表示調用UglifyJS來壓縮代碼,還有不少webpack插件如html-webpack-plugin也會默認使用UglifyJS。因此我們其實經常要用到它,但UglifyJS2本身配置較復雜/選項繁多,又沒有中文文檔,使用起來如墜云霧。鑒于此特翻譯此文,謬誤甚多,敬請斧正。
本文檔譯自UglifyJS2文檔。
另有UglifyJS3中文文檔在此
喜歡的話請收藏、給個贊/star吧!謝謝!
詞典:
parse 解釋
compress 壓縮
mangle 混淆
beautify 美化
minify 最小化
CLI 命令行工具
sourcemap 編譯后代碼對源碼的映射,用于網頁調試
AST 抽象語法樹
name 名字,包括變量名、函數名、屬性名
toplevel 頂層作用域
unreachable 不可達代碼
option 選項
STDIN 標準輸入,指在命令行中直接輸入
STDOUT 標準輸出
STDERR 標準錯誤輸出
side effects函數副作用,即函數除了返回外還產生別的作用,比如改了全局變量
以下為正文:
UglifyJS 2
UglifyJs 是一個js 解釋器、最小化器、壓縮器、美化器工具集(parser, minifier, compressor or beautifier toolkit)。
這個網頁是命令行使用的文檔,要看API和內部文檔請到UglifyJS作者的網站。
另外還有個在線demo(FF、chrome,safari可能也行)
注意:
-
uglify-js的發行版本只支持ES5,如果你要壓縮ES6+代碼請使用兼容開發分支 - Node7有個已知的性能倒退問題——運行
uglify-js兩次導致很慢
安裝
首先確認一直你已經安裝了最新的node.js(裝完后或許需要重啟一下電腦)
用NPM安裝CLI:
npm install uglify-js -g
用NPM下載給程序使用:
npm install uglify-js
用Git下載:
git clone git://github.com/mishoo/UglifyJS2.git
cd UglifyJS2
npm link
使用
uglifyjs [input files] [options]
UglifyJS2可以輸入多文件。建議你先寫輸入文件,再傳選項。UglifyJS會根據壓縮選項,把文件放在隊列中依次解釋。所有文件都會在同一個全局域中,假如一個文件中的變量、方法被另一文件引用,UglifyJS會合理地匹配。
假如你不要輸入文件,而是要輸入字符串(STDIN),那就把文件名換成一個橫線(-)
如果你想要把選項寫在文件名的前面,那要在二者之前加上雙橫線,防止文件名被當成了選項:
uglifyjs --compress --mangle -- input.js
以下是可用的選項:
--source-map 指定輸出的文件產生一份sourcemap --source-map-root 此路徑中的源碼編譯后會產生sourcemap--source-map-url 放在//#sourceMappingURL的sourcemap路徑. 默認是 --source-map傳入的值.--source-map-include-sources 如果你要在sourcemap中加上源文件的內容作為sourcesContent屬性,就傳這個參數吧。--source-map-inline 把sourcemap以base64格式附在輸出文件結尾--in-source-map 輸入sourcemap。假如的你要編譯的JS是另外的源碼編譯出來的。假如該sourcemap包含在js內,請指定"inline"。--screw-ie8 是否要支持IE6/7/8。UglifyJS默認不兼容IE。--support-ie8 是否要支持IE6/7/8,等同于在`compress`, `mangle` 和`output`選項中都設置`screw_ie8: false`--expr 編譯一個表達式,而不是編譯一段代碼(編譯JSON時用)-p, --prefix 忽略sourcemap中源碼的前綴。例如`-p 3`會干掉文件名前面3層目錄以及保證路徑是相對路徑。你也可以指定`-p relative`,讓UglifyJS自己計算輸出文件、sourcemap與源碼之間的相對路徑。-o, --output 輸出文件,默認標準輸出(STDOUT)-b, --beautify 美化輸出/指定輸出 選項-m, --mangle Mangle的名字,或傳入一個mangler選項.-r, --reserved mangle的例外,不包含在mangling的名字-c, --compress 是否啟用壓縮功能(true/fasle),或者傳一個壓縮選項對象, 例如 `-c 'if_return=false,pure_funcs=["Math.pow","console.log"]'`,`-c`不帶參數的話就是用默認的壓縮設置。-d, --define 全局定義-e, --enclose 所有代碼嵌入到一個大方法中,傳入參數為配置項--comments 保留版權注釋。默認保留Google Closure那樣的,保留JSDoc-style、包含"@license" 或"@preserve"字樣的注釋。你也可以傳下面的參數:- "all" 保留所有注釋- 正則(如`/foo/`、`/^!/`)保留匹配到的。要注意,如果啟用了壓縮,因為會移除不可達代碼以及壓縮連續聲明,因此不是*所有*注釋都能保留下來。--preamble 在輸出文件開頭插入的前言。你可以插入一段注釋,例如版權信息。這些不會被編譯,但sourcemap會改成當前的樣子。--stats 在STDERR中顯示操作運行時間。--acorn 用 Acorn解析。--spidermonkey 假如輸入文件是 SpiderMonkey AST 格式(像JSON).--self 把UglifyJS2本身也構建成一個依賴包(等同于`--wrap=UglifyJS --export-all`)--wrap 所有代碼嵌入到一個大函數中,讓"exports"和"global"變量有效,你需要傳入一個參數指定模塊被瀏覽器引入時的名字。--export-all 只當`--wrap`時有效,告訴UglifyJS自動把代碼暴露到全局。--lint 顯示一些可視警告-v, --verbose Verbose-V, --version 打印版本號.--noerr 不要為-c,-b 或 -m選項中出現未知選項而拋出錯誤。--bare-returns 允許返回函數的外部。當最小化CommonJs模塊和Userscripts時,可能匿名函數會被.user.js引擎調用立即執行(IIFE)--keep-fnames 不要混淆、干掉的函數的名字。當代碼依賴Function.prototype.name時有用。--reserved-file 要保留的文件的名字--reserve-domprops 保留(絕大部分?)DOM的屬性,當--mangle-props--mangle-props 混淆屬性,默認是`0`.設置為`true`或`1`則會混淆所有屬性名。設為`unquoted`或 `2`則只混淆不在引號內的屬性。`2`時也會讓`keep_quoted_props` 美化選項生效,保留括號內的屬性;讓壓縮選項的`properties`失效,阻止覆寫帶點號(.)的屬性。你可以通過在命令中明確設置來覆寫它們。--mangle-regex 混淆正則,只混淆匹配到的屬性名。--name-cache 用來保存混淆map的文件--pure-funcs 假如返回值沒被調用則可以安全移除的函數。 例如`--pure-funcs Math.floor console.info`(需要設置 `--compress`)
指定--output (-o)來明確輸出文件,否則將在終端輸出(STDOUT)
sourcemap選項
Source map options
UglifyJS2可以生成一份sourcemap文件,這對調試你壓縮后的JS代碼非常有用。傳--source-map output.js.map(完整路徑)來獲取sorcemap文件。
另外,你可能要設置--source-map-root傳入源碼所在的根目錄。為了防止出現整個路徑,你可以用--prefix (-p)指定干掉幾層soucemap中路徑的前綴。
例如:
uglifyjs /home/doe/work/foo/src/js/file1.js \/home/doe/work/foo/src/js/file2.js \-o foo.min.js \--source-map foo.min.js.map \--source-map-root http://foo.com/src \-p 5 -c -m
上述配置會壓縮和混淆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)
關聯sourcemap
假如你的JS代碼是用其他編譯器(例如coffeescript)生成的,那么映射到JS代碼就沒什么用了,你肯定希望映射到CoffeeScript源碼。UglifyJS有一個選項可以輸入sourcemap,假如你有一個從CoffeeScript → 編譯后JS的map的話,UglifyJS可以生成一個從CoffeeScript->壓縮后JS的map映射到源碼位置。
你可以傳入 --in-source-map /path/to/input/source.map來嘗試此特性,如果sourcemap包含在js內,則寫--in-source-map inline 。通常輸入的sourcemap會指向源代碼生成的JS,所以你可以忽略不寫輸入文件。
混淆選項
Mangler options
你需要傳入--mangle (-m)來使啟用混淆功能。支持用逗號隔開選項:
-
toplevel— 混淆在最高作用域中聲明的變量名(默認disabled) -
eval- 混淆在eval或with作用域出現的變量名(默認disabled)
當啟用混淆功能時,如果你希望保留一些名字不被混淆,你可以用--reserved (-r) 聲明一些名字,用逗號隔開。例如:
uglifyjs ... -m -r '$,require,exports'
防止require, exports和 $被混淆改變。
混淆屬性名 (--mangle-props)
警告:這能會搞崩你的代碼?;煜龑傩悦煜兞棵灰粯?#xff0c;是相互獨立的。傳入--mangle-props會混淆對象所有可見的屬性名。例如:
var x = {foo: 1
};x.bar = 2;
x["baz"] = 3;
x[condition ? "moo" : "boo"] = 4;
console.log(x.something());
上面代碼中,foo, bar, baz, moo 、 boo會被替換成單字符名字,something()則不變。
為了合理地使用,我們應該避免混淆一些JS標準的名字。比如,如果你代碼中有x.length = 10,那length就將被混淆,不管這是在對象中還是訪問數組的長度,它都被干掉。為了避免這種情況,你可以用 --reserved-file來輸入一個文件,里面包含不參與混淆的名字,變量名或屬性名都行。就像下面這樣:
{"vars": [ "define", "require", ... ],"props": [ "length", "prototype", ... ]
}
--reserved-file 可以是文件名數組(用逗號隔開,你也可以傳多個--reserved-file),在上面例子中的名字將被排除在混淆中。tools/domprops.json 里有一個默認的排除名單,包括絕大部分標準JS和多種瀏覽器中的DOM屬性名。傳入--reserve-domprops 可以讀取此名單生效。
你也可以用正則表達式來定義一些應該被混淆的屬性名。例如--mangle-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=unquoted或 --mangle-props=2)
使用括號屬性名 (o["foo"])以保留屬性名(foo)。這會讓整個腳本中其余此屬性的引用(o.foo)也不被混淆。例如:
$ echo 'var o={"foo":1, bar:3}; o.foo += o.bar; console.log(o.foo);' | uglifyjs --mangle-props=2 -mc
var o={"foo":1,a:3};o.foo+=o.a,console.log(o.foo);
調試屬性名混淆
為了混淆屬性時不至于完全糊涂,你可以傳入--mangle-props-debug來調試。例如o.foo會被混淆成o._$foo$_。這讓源碼大量、屬性被混淆時也可以debug,可以看清混淆會把哪些屬性搞亂。
你可以用--mangle-props-debug=XYZ來傳入自定義后綴。讓o.foo 混淆成 o._$foo$XYZ_, 你可以在每次編譯是都改變一下,來辨清屬性名怎么被混淆的。一個小技巧,你可以每次編譯時傳隨機數來模仿混淆操作(例如你更新了腳本,有了新的屬性名),這有助于識別混淆時的出錯。
壓縮器選項
Compressor options
你要傳入 --compress (-c)來啟用壓縮功能。你可以用逗號隔開選項。選項的形式為foo=bar,或者就foo(后者等同于你要設為true,相當于foo=true的縮寫)。
-
sequences(默認true) -- 連續聲明變量,用逗號隔開來??梢栽O置為正整數來指定連續聲明的最大長度。如果設為true表示默認200個,設為false或0則禁用。sequences至少要是2,1的話等同于true(即200)。默認的sequences設置有極小幾率會導致壓縮很慢,所以推薦設置成20或以下。 -
properties-- 用.來重寫屬性引用,例如foo["bar"] → foo.bar -
dead_code-- 移除沒被引用的代碼 -
drop_debugger-- 移除debugger; -
unsafe(默認 false) -- 使用 "unsafe"轉換 (下面詳述) -
unsafe_comps(默認 false) -- 保留<和<=不被換成>和>=。假如某些運算對象是用get或valueOfobject得出的時候,轉換可能會不安全,可能會引起運算對象的改變。此選項只有當comparisons和unsafe_comps都設為true時才會啟用。 -
unsafe_math(默認 false) -- 優化數字表達式,例如2 * x * 3變成6 * x, 可能會導致不精確的浮點數結果。 -
unsafe_proto(默認 false) -- 把Array.prototype.slice.call(a)優化成[].slice.call(a) -
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 -
loops-- 當do、while、for循環的判斷條件可以確定是,對其進行優化。 -
unused-- 干掉沒有被引用的函數和變量。(除非設置"keep_assign",否則變量的簡單直接賦值也不算被引用。) -
toplevel-- 干掉頂層作用域中沒有被引用的函數 ("funcs")和/或變量("vars") (默認是false,true的話即函數變量都干掉) -
top_retain-- 當設了unused時,保留頂層作用域中的某些函數變量。(可以寫成數組,用逗號隔開,也可以用正則或函數. 參考toplevel) -
hoist_funs-- 提升函數聲明 -
hoist_vars(默認 false) -- 提升var聲明 (默認是false,因為那會加大文件的size) -
if_return-- 優化 if/return 和 if/continue -
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上有性能問題。
unsafe選項
在某些刻意營造的案例中,啟用某些轉換有可能會打斷代碼的邏輯,但絕大部分情況下是安全的。你可能會想嘗試一下,因為這畢竟會減少文件體積。以下是某些例子:
-
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的 -
typeof foo == "undefined"→foo === void 0 -
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聲明,構建后還會被保留。如果你的運行環境低于ES6、不支持const,請用var聲明加上reduce_vars設置(默認啟用)來實現。
編譯條件語句API
你也可以通過程序API來設置編譯配置。其中有差別的是一個壓縮器屬性global_defs:
uglifyJS.minify([ "input.js"], {compress: {dead_code: true,global_defs: {DEBUG: false}}
});
美化器選項
Beautifier options
代碼生成器默認會輸出盡量簡短的代碼。假如你想美化一下輸出代碼,請設置--beautify (-b)。你可以傳入更多可選的選項參數來控制代碼生成:
-
beautify(默認true) -- 是否美化輸出代碼。傳-b的話就是設成true。假如你想生成最小化的代碼同時又要用其他設置來美化代碼,你可以設-b beautify=false。 -
indent-level(默認 4) 縮進格數 -
indent-start(默認 0) -- 每行前面加幾個空格 -
quote-keys(默認false) -- 傳true的話會在對象所有的鍵加上括號 -
space-colon(默認true) -- 在冒號后面加空格 -
ascii-only(默認false) -- 避免Unicode字符在字符串/正則中出現(非ascii字符會變不合法)。 -
inline-script(默認false) -- 避免字符串中出現</script中的斜杠 -
width(默認 80) -- 僅在美化時生效,設定一個行寬讓美化器盡量實現。這會影響行中文字的數量(不包括縮進)。當前本功能實現得不是非常好,但依然讓美化后的代碼可讀性大大增強。 -
max-line-len(默認 32000) -- 最大行寬(壓縮后的代碼) -
bracketize(默認false) -- 永遠在if,for,do,while,with后面加上大括號,即使循環體只有一句。 -
semicolons(默認true) -- 用分號分開多個聲明。如果你傳false,則總會另起一行,增強輸出文件的可讀性。(gzip前體積更小,gzip后稍大一點點) -
preamble(默認null) -- 如果要傳的話,必須是字符串。它會被加在輸出文檔的前面。sourcemap會隨之調整。例如可以用來插入版權信息。 -
quote_style(默認0) -- 影響字符串的括號格式(也會影響屬性名和指令)。 -
0-- 傾向使用雙引號,字符串里還有引號的話就是單引號。 -
1-- 永遠單引號 -
2-- 永遠雙引號 -
3-- 永遠是本來的引號 -
keep_quoted_props(默認false) -- 如果啟用,會保留屬性名的引號。
保留版權告示和其他注釋
你可以傳入--comments讓輸出文件中保留某些注釋。默認時會保留JSDoc-style的注釋(包含"@preserve","@license" 或 "@cc_on"(為IE所編譯))。你可以傳入--comments all來保留全部注釋,或者傳一個合法的正則來保留那些匹配到的注釋。例如--comments '/foo|bar/'會保留那些包含"foo" 或 "bar"的注釋。
注意,無論如何,總會有些注釋在某些情況下會丟失。例如:
function f() {/** @preserve Foo Bar */function g() {// this function is never called}return something();
}
即使里面帶有"@preserve",注釋依然會被丟棄。因為內部的函數g(注釋所依附的抽象語法樹節點)沒有被引用、會被壓縮器干掉。
書寫版權信息(或其他需要在輸出文件中保留的信息)的最安全位置是全局節點。
對SpiderMonkey的支持
UglifyJS2有自己的抽象語法樹格式;為了某些現實的原因
我們無法在內部輕易地改成使用SpiderMonkey抽象語法樹(AST)。但UglifyJS現在有了一個可以輸入SpiderMonkeyAST的轉換器。
例如Acorn ,這是一個超級快的生成SpiderMonkey AST的解釋器。它帶有一個實用的迷你CLI,能解釋一個文件、把AST轉存為JSON并標準輸出??梢赃@樣用UglifyJS來壓縮混淆:
acorn file.js | uglifyjs --spidermonkey -m -c
--spidermonkey選項能讓UglifyJS知道輸入文件并非JavaScript,而是SpiderMonkey AST生成的JSON代碼。這事我們不用自己的解釋器,只把AST轉成我們內部AST。
使用 Acorn 來解釋代碼
更有趣的是,我們加了 --acorn選項來使用Acorn解釋所有代碼。如果你傳入這個選項,UglifyJS會require("acorn")
Acorn確實非常快(650k代碼原來要380ms,現在只需250ms),但轉換Acorn產生的SpiderMonkey樹會額外花費150ms。所以總共比UglifyJS自己的解釋器還要多花一點時間。
使用 UglifyJS 轉換 SpiderMonkey AST
現在你可以像使用其他中間工具一樣使用UglifyJS將JS抽象語法樹轉換為SpiderMonkey格式。
例如:
function uglify(ast, options, mangle) {// 把SpiderMonkey AST 轉成中間格式var uAST = UglifyJS.AST_Node.from_mozilla_ast(ast);// 壓縮uAST.figure_out_scope();uAST = UglifyJS.Compressor(options).compress(uAST);// 混淆 (可選)if (mangle) {uAST.figure_out_scope();uAST.compute_char_frequency();uAST.mangle_names();}// 轉回 SpiderMonkey ASTreturn uAST.to_mozilla_ast();
}
原博文有更多細節。
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.jsvar 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-regexCLI參數選項關聯) -
ignore_quoted– 只混淆非括號中的屬性名(與--mangle-props 2CLI 參數選項關聯) -
debug– 讓混淆后的名字與原名字有關。與--mangle-props-debugCLI 參數選項關聯)。默認是false。傳一個空字符串來啟用,或者傳一個非空字符串來添加后綴。
高級使用模式
如果minify函數太簡單不能滿足你的需求,下面這些API信息有更多的細節詳情:
解釋器
var toplevel_ast = UglifyJS.parse(code, options);
options 是可選的,要傳的話就必須傳個對象。下面這些是有效的屬性:
-
strict— 禁用自動添加分號,禁止數組、對象末尾還有逗號。 -
bare_returns— 允許函數返回外部。(與--bare-returnsCLI參數選項關聯,對minifyparse選項對象也有效。) -
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包含一個作用域分析器,你可以在壓縮、混淆前手動調用?;旧?#xff0c;它添加了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方法,用來生成輸出流?;旧?#xff0c;要生成代碼你只要這么做:
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
總結
以上是生活随笔為你收集整理的UglifyJS中文文档的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【bfs】廉价最短路径(2013特长生
- 下一篇: 【DP】K星人的语言(2020特长生 T