日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

UglifyJS中文文档

發(fā)布時(shí)間:2023/12/3 综合教程 47 生活家
生活随笔 收集整理的這篇文章主要介紹了 UglifyJS中文文档 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

UglifyJS中文文檔

譯者:李平海

轉(zhuǎn)載請(qǐng)注明原文鏈接(https://github.com/LiPinghai/... )與作者信息。

譯序

由于webpack本身集成了UglifyJS插件(webpack.optimize.UglifyJsPlugin),其命令webpack -p即表示調(diào)用UglifyJS來壓縮代碼,還有不少webpack插件如html-webpack-plugin也會(huì)默認(rèn)使用UglifyJS。因此我們其實(shí)經(jīng)常要用到它,但UglifyJS2本身配置較復(fù)雜/選項(xiàng)繁多,又沒有中文文檔,使用起來如墜云霧。鑒于此特翻譯此文,謬誤甚多,敬請(qǐng)斧正。

本文檔譯自UglifyJS2文檔。

另有UglifyJS3中文文檔在此

喜歡的話請(qǐng)收藏、給個(gè)贊/star吧!謝謝!

詞典:

parse       解釋
compress    壓縮
mangle      混淆
beautify    美化
minify      最小化
CLI         命令行工具
sourcemap   編譯后代碼對(duì)源碼的映射,用于網(wǎng)頁調(diào)試
AST         抽象語法樹
name        名字,包括變量名、函數(shù)名、屬性名
toplevel    頂層作用域
unreachable 不可達(dá)代碼
option      選項(xiàng)
STDIN       標(biāo)準(zhǔn)輸入,指在命令行中直接輸入
STDOUT      標(biāo)準(zhǔn)輸出
STDERR      標(biāo)準(zhǔn)錯(cuò)誤輸出
side effects函數(shù)副作用,即函數(shù)除了返回外還產(chǎn)生別的作用,比如改了全局變量

以下為正文:

UglifyJS 2

UglifyJs 是一個(gè)js 解釋器、最小化器、壓縮器、美化器工具集(parser, minifier, compressor or beautifier toolkit)。

這個(gè)網(wǎng)頁是命令行使用的文檔,要看API和內(nèi)部文檔請(qǐng)到UglifyJS作者的網(wǎng)站。
另外還有個(gè)在線demo(FF、chrome,safari可能也行)

注意:

  • uglify-js的發(fā)行版本只支持ES5,如果你要壓縮ES6+代碼請(qǐng)使用兼容開發(fā)分支
  • Node7有個(gè)已知的性能倒退問題——運(yùn)行uglify-js兩次導(dǎo)致很慢

安裝

首先確認(rèn)一直你已經(jīng)安裝了最新的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可以輸入多文件。建議你先寫輸入文件,再傳選項(xiàng)。UglifyJS會(huì)根據(jù)壓縮選項(xiàng),把文件放在隊(duì)列中依次解釋。所有文件都會(huì)在同一個(gè)全局域中,假如一個(gè)文件中的變量、方法被另一文件引用,UglifyJS會(huì)合理地匹配。

假如你不要輸入文件,而是要輸入字符串(STDIN),那就把文件名換成一個(gè)橫線(-)

如果你想要把選項(xiàng)寫在文件名的前面,那要在二者之前加上雙橫線,防止文件名被當(dāng)成了選項(xiàng):

 uglifyjs --compress --mangle -- input.js

以下是可用的選項(xiàng):

  --source-map                  指定輸出的文件產(chǎn)生一份sourcemap --source-map-root             此路徑中的源碼編譯后會(huì)產(chǎn)生sourcemap--source-map-url              放在//#sourceMappingURL的sourcemap路徑.  默認(rèn)是 --source-map傳入的值.--source-map-include-sources  如果你要在sourcemap中加上源文件的內(nèi)容作為sourcesContent屬性,就傳這個(gè)參數(shù)吧。--source-map-inline           把sourcemap以base64格式附在輸出文件結(jié)尾--in-source-map               輸入sourcemap。假如的你要編譯的JS是另外的源碼編譯出來的。假如該sourcemap包含在js內(nèi),請(qǐng)指定"inline"。--screw-ie8                   是否要支持IE6/7/8。UglifyJS默認(rèn)不兼容IE。--support-ie8                 是否要支持IE6/7/8,等同于在`compress`, `mangle` 和`output`選項(xiàng)中都設(shè)置`screw_ie8: false`--expr                        編譯一個(gè)表達(dá)式,而不是編譯一段代碼(編譯JSON時(shí)用)-p, --prefix                  忽略sourcemap中源碼的前綴。例如`-p 3`會(huì)干掉文件名前面3層目錄以及保證路徑是相對(duì)路徑。你也可以指定`-p relative`,讓UglifyJS自己計(jì)算輸出文件、sourcemap與源碼之間的相對(duì)路徑。-o, --output                  輸出文件,默認(rèn)標(biāo)準(zhǔn)輸出(STDOUT)-b, --beautify                美化輸出/指定輸出 選項(xiàng)-m, --mangle                  Mangle的名字,或傳入一個(gè)mangler選項(xiàng).-r, --reserved                mangle的例外,不包含在mangling的名字-c, --compress                是否啟用壓縮功能(true/fasle),或者傳一個(gè)壓縮選項(xiàng)對(duì)象, 例如 `-c 'if_return=false,pure_funcs=["Math.pow","console.log"]'`,`-c`不帶參數(shù)的話就是用默認(rèn)的壓縮設(shè)置。-d, --define                  全局定義-e, --enclose                 所有代碼嵌入到一個(gè)大方法中,傳入?yún)?shù)為配置項(xiàng)--comments                    保留版權(quán)注釋。默認(rèn)保留Google Closure那樣的,保留JSDoc-style、包含"@license" 或"@preserve"字樣的注釋。你也可以傳下面的參數(shù):- "all" 保留所有注釋- 正則(如`/foo/`、`/^!/`)保留匹配到的。要注意,如果啟用了壓縮,因?yàn)闀?huì)移除不可達(dá)代碼以及壓縮連續(xù)聲明,因此不是*所有*注釋都能保留下來。--preamble                    在輸出文件開頭插入的前言。你可以插入一段注釋,例如版權(quán)信息。這些不會(huì)被編譯,但sourcemap會(huì)改成當(dāng)前的樣子。--stats                       在STDERR中顯示操作運(yùn)行時(shí)間。--acorn                       用 Acorn解析。--spidermonkey                假如輸入文件是 SpiderMonkey AST 格式(像JSON).--self                        把UglifyJS2本身也構(gòu)建成一個(gè)依賴包(等同于`--wrap=UglifyJS --export-all`)--wrap                        所有代碼嵌入到一個(gè)大函數(shù)中,讓"exports"和"global"變量有效,你需要傳入一個(gè)參數(shù)指定模塊被瀏覽器引入時(shí)的名字。--export-all                  只當(dāng)`--wrap`時(shí)有效,告訴UglifyJS自動(dòng)把代碼暴露到全局。--lint                        顯示一些可視警告-v, --verbose                 Verbose-V, --version                 打印版本號(hào).--noerr                       不要為-c,-b 或 -m選項(xiàng)中出現(xiàn)未知選項(xiàng)而拋出錯(cuò)誤。--bare-returns                允許返回函數(shù)的外部。當(dāng)最小化CommonJs模塊和Userscripts時(shí),可能匿名函數(shù)會(huì)被.user.js引擎調(diào)用立即執(zhí)行(IIFE)--keep-fnames                 不要混淆、干掉的函數(shù)的名字。當(dāng)代碼依賴Function.prototype.name時(shí)有用。--reserved-file               要保留的文件的名字--reserve-domprops            保留(絕大部分?)DOM的屬性,當(dāng)--mangle-props--mangle-props                混淆屬性,默認(rèn)是`0`.設(shè)置為`true`或`1`則會(huì)混淆所有屬性名。設(shè)為`unquoted`或 `2`則只混淆不在引號(hào)內(nèi)的屬性。`2`時(shí)也會(huì)讓`keep_quoted_props` 美化選項(xiàng)生效,保留括號(hào)內(nèi)的屬性;讓壓縮選項(xiàng)的`properties`失效,阻止覆寫帶點(diǎn)號(hào)(.)的屬性。你可以通過在命令中明確設(shè)置來覆寫它們。--mangle-regex                混淆正則,只混淆匹配到的屬性名。--name-cache                  用來保存混淆map的文件--pure-funcs                  假如返回值沒被調(diào)用則可以安全移除的函數(shù)。 例如`--pure-funcs Math.floor console.info`(需要設(shè)置 `--compress`)

指定--output (-o)來明確輸出文件,否則將在終端輸出(STDOUT)

sourcemap選項(xiàng)

Source map options

UglifyJS2可以生成一份sourcemap文件,這對(duì)調(diào)試你壓縮后的JS代碼非常有用。傳--source-map output.js.map(完整路徑)來獲取sorcemap文件。

另外,你可能要設(shè)置--source-map-root傳入源碼所在的根目錄。為了防止出現(xiàn)整個(gè)路徑,你可以用--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

上述配置會(huì)壓縮和混淆file1.jsfile2.js,輸出文件foo.min.js 和sourcemapfoo.min.js.map,sourcemap會(huì)建立http://foo.com/src/js/file1.js
http://foo.com/src/js/file2.js的映射。(實(shí)際上,sourcemap根目錄是http://foo.com/src,所以相當(dāng)于源文件路徑是js/file1.jsjs/file2.js

關(guān)聯(lián)sourcemap

假如你的JS代碼是用其他編譯器(例如coffeescript)生成的,那么映射到JS代碼就沒什么用了,你肯定希望映射到CoffeeScript源碼。UglifyJS有一個(gè)選項(xiàng)可以輸入sourcemap,假如你有一個(gè)從CoffeeScript → 編譯后JS的map的話,UglifyJS可以生成一個(gè)從CoffeeScript->壓縮后JS的map映射到源碼位置。

你可以傳入 --in-source-map /path/to/input/source.map來嘗試此特性,如果sourcemap包含在js內(nèi),則寫--in-source-map inline 。通常輸入的sourcemap會(huì)指向源代碼生成的JS,所以你可以忽略不寫輸入文件。

混淆選項(xiàng)

Mangler options

你需要傳入--mangle (-m)來使啟用混淆功能。支持用逗號(hào)隔開選項(xiàng):

  • toplevel — 混淆在最高作用域中聲明的變量名(默認(rèn)disabled)
  • eval - 混淆在evalwith作用域出現(xiàn)的變量名(默認(rèn)disabled)

當(dāng)啟用混淆功能時(shí),如果你希望保留一些名字不被混淆,你可以用--reserved (-r) 聲明一些名字,用逗號(hào)隔開。例如:

 uglifyjs ... -m -r '$,require,exports'

防止require, exports$被混淆改變。

混淆屬性名 (--mangle-props)

警告:這能會(huì)搞崩你的代碼。混淆屬性名跟混淆變量名不一樣,是相互獨(dú)立的。傳入--mangle-props會(huì)混淆對(duì)象所有可見的屬性名。例如:

var x = {foo: 1
};x.bar = 2;
x["baz"] = 3;
x[condition ? "moo" : "boo"] = 4;
console.log(x.something());

上面代碼中,foo, bar, baz, mooboo會(huì)被替換成單字符名字,something()則不變。

為了合理地使用,我們應(yīng)該避免混淆一些JS標(biāo)準(zhǔn)的名字。比如,如果你代碼中有x.length = 10,那length就將被混淆,不管這是在對(duì)象中還是訪問數(shù)組的長(zhǎng)度,它都被干掉。為了避免這種情況,你可以用 --reserved-file來輸入一個(gè)文件,里面包含不參與混淆的名字,變量名或?qū)傩悦夹小>拖裣旅孢@樣:

{"vars": [ "define", "require", ... ],"props": [ "length", "prototype", ... ]
}

--reserved-file 可以是文件名數(shù)組(用逗號(hào)隔開,你也可以傳多個(gè)--reserved-file),在上面例子中的名字將被排除在混淆中。
tools/domprops.json 里有一個(gè)默認(rèn)的排除名單,包括絕大部分標(biāo)準(zhǔn)JS和多種瀏覽器中的DOM屬性名。傳入--reserve-domprops 可以讀取此名單生效。

你也可以用正則表達(dá)式來定義一些應(yīng)該被混淆的屬性名。例如--mangle-regex="/^_/",會(huì)只混淆以下劃線開始的屬性名。

當(dāng)你壓縮多個(gè)文件時(shí),為了保證讓它們最終能同時(shí)工作,我們要讓他們中同樣的屬性名混淆成相同的結(jié)果。傳入`--name-cache
filename.json`,UglifyJS會(huì)維護(hù)一個(gè)共同的映射供他們復(fù)用。這個(gè)json一開始應(yīng)該是空的,例如:

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

現(xiàn)在,part1.jspart2.js會(huì)知曉對(duì)方混淆的屬性名。

假如你把所有文件壓縮成同一個(gè)文件,那就不需要啟用名字緩存了。

混淆括號(hào)中的名字(--mangle-props=unquoted--mangle-props=2)

使用括號(hào)屬性名 (o["foo"])以保留屬性名(foo)。這會(huì)讓整個(gè)腳本中其余此屬性的引用(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);

調(diào)試屬性名混淆

為了混淆屬性時(shí)不至于完全糊涂,你可以傳入--mangle-props-debug來調(diào)試。例如o.foo會(huì)被混淆成o._$foo$_。這讓源碼大量、屬性被混淆時(shí)也可以debug,可以看清混淆會(huì)把哪些屬性搞亂。

你可以用--mangle-props-debug=XYZ來傳入自定義后綴。讓o.foo 混淆成 o._$foo$XYZ_, 你可以在每次編譯是都改變一下,來辨清屬性名怎么被混淆的。一個(gè)小技巧,你可以每次編譯時(shí)傳隨機(jī)數(shù)來模仿混淆操作(例如你更新了腳本,有了新的屬性名),這有助于識(shí)別混淆時(shí)的出錯(cuò)。

壓縮器選項(xiàng)

Compressor options

你要傳入 --compress (-c)來啟用壓縮功能。你可以用逗號(hào)隔開選項(xiàng)。選項(xiàng)的形式為foo=bar,或者就foo(后者等同于你要設(shè)為true,相當(dāng)于foo=true的縮寫)。

  • sequences(默認(rèn)true) -- 連續(xù)聲明變量,用逗號(hào)隔開來。可以設(shè)置為正整數(shù)來指定連續(xù)聲明的最大長(zhǎng)度。如果設(shè)為true 表示默認(rèn)200個(gè),設(shè)為false0則禁用。 sequences至少要是2,1的話等同于true(即200)。默認(rèn)的sequences設(shè)置有極小幾率會(huì)導(dǎo)致壓縮很慢,所以推薦設(shè)置成20或以下。
  • properties -- 用.來重寫屬性引用,例如foo["bar"] → foo.bar
  • dead_code -- 移除沒被引用的代碼
  • drop_debugger -- 移除 debugger;
  • unsafe (默認(rèn) false) -- 使用 "unsafe"轉(zhuǎn)換 (下面詳述)
  • unsafe_comps (默認(rèn) false) -- 保留<<=不被換成 >>=。假如某些運(yùn)算對(duì)象是用getvalueOfobject得出的時(shí)候,轉(zhuǎn)換可能會(huì)不安全,可能會(huì)引起運(yùn)算對(duì)象的改變。此選項(xiàng)只有當(dāng) comparisonsunsafe_comps 都設(shè)為true時(shí)才會(huì)啟用。
  • unsafe_math (默認(rèn) false) -- 優(yōu)化數(shù)字表達(dá)式,例如2 * x * 3 變成 6 * x, 可能會(huì)導(dǎo)致不精確的浮點(diǎn)數(shù)結(jié)果。
  • unsafe_proto (默認(rèn) false) -- 把Array.prototype.slice.call(a) 優(yōu)化成 [].slice.call(a)
  • conditionals -- 優(yōu)化if等判斷以及條件選擇
  • comparisons -- 把結(jié)果必然的運(yùn)算優(yōu)化成二元運(yùn)算,例如!(a <= b) → a > b (只有設(shè)置了 unsafe_comps時(shí)才生效);盡量轉(zhuǎn)成否運(yùn)算。例如 a = !b && !c && !d && !e → a=!(b||c||d||e)
  • evaluate -- 嘗試計(jì)算常量表達(dá)式
  • booleans -- 優(yōu)化布爾運(yùn)算,例如 !!a? b : c → a ? b : c
  • loops -- 當(dāng)dowhilefor循環(huán)的判斷條件可以確定是,對(duì)其進(jìn)行優(yōu)化。
  • unused -- 干掉沒有被引用的函數(shù)和變量。(除非設(shè)置"keep_assign",否則變量的簡(jiǎn)單直接賦值也不算被引用。)
  • toplevel -- 干掉頂層作用域中沒有被引用的函數(shù) ("funcs")和/或變量("vars") (默認(rèn)是false , true 的話即函數(shù)變量都干掉)
  • top_retain -- 當(dāng)設(shè)了unused時(shí),保留頂層作用域中的某些函數(shù)變量。(可以寫成數(shù)組,用逗號(hào)隔開,也可以用正則或函數(shù). 參考toplevel)
  • hoist_funs -- 提升函數(shù)聲明
  • hoist_vars (默認(rèn) false) -- 提升 var 聲明 (默認(rèn)是false,因?yàn)槟菚?huì)加大文件的size)
  • if_return -- 優(yōu)化 if/return 和 if/continue
  • join_vars -- 合并連續(xù) var 聲明
  • cascade -- 弱弱地優(yōu)化一下連續(xù)聲明, 將 x, x 轉(zhuǎn)成 xx = something(), x 轉(zhuǎn)成 x = something()
  • collapse_vars -- 當(dāng) varconst 單獨(dú)使用時(shí)盡量合并
  • reduce_vars -- 優(yōu)化某些變量實(shí)際上是按常量值來賦值、使用的情況。
  • warnings -- 當(dāng)刪除沒有用處的代碼時(shí),顯示警告
  • negate_iife -- 當(dāng)立即執(zhí)行函數(shù)(IIFE)的返回值沒用時(shí),取消之。避免代碼生成器會(huì)插入括號(hào)。
  • pure_getters -- 默認(rèn)是 false. 如果你傳入true,UglifyJS會(huì)假設(shè)對(duì)象屬性的引用(例如foo.barfoo["bar"])沒有函數(shù)副作用。
  • pure_funcs -- 默認(rèn) null. 你可以傳入一個(gè)名字的數(shù)組,UglifyJS會(huì)假設(shè)這些函數(shù)沒有函數(shù)副作用。警告:假如名字在作用域中重新定義,不會(huì)再次檢測(cè)。例如var q = Math.floor(a/b),假如變量q沒有被引用,UglifyJS會(huì)干掉它,但 Math.floor(a/b)會(huì)被保留,沒有人知道它是干嘛的。你可以設(shè)置pure_funcs: [ 'Math.floor' ] ,這樣該函數(shù)會(huì)被認(rèn)為沒有函數(shù)副作用,這樣整個(gè)聲明會(huì)被廢棄。在目前的執(zhí)行情況下,會(huì)增加開銷(壓縮會(huì)變慢)。
  • drop_console -- 默認(rèn) false. 傳true的話會(huì)干掉console.*函數(shù)。如果你要干掉特定的函數(shù)比如console.info ,又想刪掉后保留其參數(shù)中的副作用,那用pure_funcs來處理吧。
  • expression -- 默認(rèn) false。傳true來保留終端語句中沒有"return"的完成值。例如在bookmarklets。
  • keep_fargs -- 默認(rèn)true。阻止壓縮器干掉那些沒有用到的函數(shù)參數(shù)。你需要它來保護(hù)某些依賴Function.length的函數(shù)。
  • keep_fnames -- 默認(rèn) false。傳 true來防止壓縮器干掉函數(shù)名。對(duì)那些依賴Function.prototype.name的函數(shù)很有用。延展閱讀:keep_fnames 混淆選項(xiàng).
  • passes -- 默認(rèn) 1。運(yùn)行壓縮的次數(shù)。在某些情況下,用一個(gè)大于1的數(shù)字參數(shù)可以進(jìn)一步壓縮代碼大小。注意:數(shù)字越大壓縮耗時(shí)越長(zhǎng)。
  • keep_infinity -- 默認(rèn) false。傳true以防止壓縮時(shí)把1/0轉(zhuǎn)成Infinity,那可能會(huì)在chrome上有性能問題。

unsafe選項(xiàng)

在某些刻意營造的案例中,啟用某些轉(zhuǎn)換有可能會(huì)打斷代碼的邏輯,但絕大部分情況下是安全的。你可能會(huì)想嘗試一下,因?yàn)檫@畢竟會(huì)減少文件體積。以下是某些例子:

  • 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 0undefined (假如作用域中有一個(gè)變量名叫"undefined";我們這么做是因?yàn)樽兞棵麜?huì)被混淆成單字符)

編譯條件語句

Uglify會(huì)假設(shè)全局變量都是常量(不管是否在局部域中定義了),你可以用--define (-d)來實(shí)現(xiàn)定義全局變量。例如你傳--define DEBUG=false,UglifyJS會(huì)在輸出中干掉下面代碼:

if (DEBUG) {
console.log("debug stuff");
}

你可以像--define env.DEBUG=false這樣寫嵌套的常量。

在干掉那些永否的條件語句以及不可達(dá)代碼時(shí),UglifyJS會(huì)給出警告。現(xiàn)在沒有選項(xiàng)可以禁用此特性,但你可以設(shè)置 warnings=false 來禁掉所有警告。

另一個(gè)定義全局常量的方法是,在一個(gè)獨(dú)立的文檔中定義,再引入到構(gòu)建中。例如你有一個(gè)這樣的build/defines.js

const DEBUG = false;
const PRODUCTION = true;
// 等等

構(gòu)建使用這樣寫:

  uglifyjs build/defines.js js/foo.js js/bar.js... -c

UglifyJS會(huì)注意到這些常量。因?yàn)樗鼈儫o法改變,所以它們會(huì)被認(rèn)為是沒被引用而被照樣干掉。如果你用const聲明,構(gòu)建后還會(huì)被保留。如果你的運(yùn)行環(huán)境低于ES6、不支持const,請(qǐng)用var聲明加上reduce_vars設(shè)置(默認(rèn)啟用)來實(shí)現(xiàn)。

編譯條件語句API

你也可以通過程序API來設(shè)置編譯配置。其中有差別的是一個(gè)壓縮器屬性global_defs

uglifyJS.minify([ "input.js"], {compress: {dead_code: true,global_defs: {DEBUG: false}}
});

美化器選項(xiàng)

Beautifier options

代碼生成器默認(rèn)會(huì)輸出盡量簡(jiǎn)短的代碼。假如你想美化一下輸出代碼,請(qǐng)?jiān)O(shè)置--beautify (-b)。你可以傳入更多可選的選項(xiàng)參數(shù)來控制代碼生成:

  • beautify (默認(rèn) true) -- 是否美化輸出代碼。傳-b的話就是設(shè)成true。假如你想生成最小化的代碼同時(shí)又要用其他設(shè)置來美化代碼,你可以設(shè)-b beautify=false
  • indent-level (默認(rèn) 4) 縮進(jìn)格數(shù)
  • indent-start (默認(rèn) 0) -- 每行前面加幾個(gè)空格
  • quote-keys (默認(rèn) false) -- 傳true的話會(huì)在對(duì)象所有的鍵加上括號(hào)
  • space-colon (默認(rèn) true) -- 在冒號(hào)后面加空格
  • ascii-only (默認(rèn) false) -- 避免Unicode字符在字符串/正則中出現(xiàn)(非ascii字符會(huì)變不合法)。
  • inline-script (默認(rèn) false) -- 避免字符串中出現(xiàn)</script中的斜杠
  • width (默認(rèn) 80) -- 僅在美化時(shí)生效,設(shè)定一個(gè)行寬讓美化器盡量實(shí)現(xiàn)。這會(huì)影響行中文字的數(shù)量(不包括縮進(jìn))。當(dāng)前本功能實(shí)現(xiàn)得不是非常好,但依然讓美化后的代碼可讀性大大增強(qiáng)。
  • max-line-len (默認(rèn) 32000) -- 最大行寬(壓縮后的代碼)
  • bracketize (默認(rèn) false) -- 永遠(yuǎn)在if, for,do, while, with后面加上大括號(hào),即使循環(huán)體只有一句。
  • semicolons (默認(rèn) true) -- 用分號(hào)分開多個(gè)聲明。如果你傳false,則總會(huì)另起一行,增強(qiáng)輸出文件的可讀性。(gzip前體積更小,gzip后稍大一點(diǎn)點(diǎn))
  • preamble (默認(rèn) null) -- 如果要傳的話,必須是字符串。它會(huì)被加在輸出文檔的前面。sourcemap會(huì)隨之調(diào)整。例如可以用來插入版權(quán)信息。
  • quote_style (默認(rèn) 0) -- 影響字符串的括號(hào)格式(也會(huì)影響屬性名和指令)。
  • 0 -- 傾向使用雙引號(hào),字符串里還有引號(hào)的話就是單引號(hào)。
  • 1 -- 永遠(yuǎn)單引號(hào)
  • 2 -- 永遠(yuǎn)雙引號(hào)
  • 3 -- 永遠(yuǎn)是本來的引號(hào)
  • keep_quoted_props (默認(rèn) false) -- 如果啟用,會(huì)保留屬性名的引號(hào)。

保留版權(quán)告示和其他注釋

你可以傳入--comments讓輸出文件中保留某些注釋。默認(rèn)時(shí)會(huì)保留JSDoc-style的注釋(包含"@preserve","@license" 或 "@cc_on"(為IE所編譯))。你可以傳入--comments all來保留全部注釋,或者傳一個(gè)合法的正則來保留那些匹配到的注釋。例如--comments '/foo|bar/'會(huì)保留那些包含"foo" 或 "bar"的注釋。

注意,無論如何,總會(huì)有些注釋在某些情況下會(huì)丟失。例如:

function f() {/** @preserve Foo Bar */function g() {// this function is never called}return something();
}

即使里面帶有"@preserve",注釋依然會(huì)被丟棄。因?yàn)閮?nèi)部的函數(shù)g(注釋所依附的抽象語法樹節(jié)點(diǎn))沒有被引用、會(huì)被壓縮器干掉。

書寫版權(quán)信息(或其他需要在輸出文件中保留的信息)的最安全位置是全局節(jié)點(diǎn)。

對(duì)SpiderMonkey的支持

UglifyJS2有自己的抽象語法樹格式;為了某些現(xiàn)實(shí)的原因
我們無法在內(nèi)部輕易地改成使用SpiderMonkey抽象語法樹(AST)。但UglifyJS現(xiàn)在有了一個(gè)可以輸入SpiderMonkeyAST的轉(zhuǎn)換器。
例如Acorn ,這是一個(gè)超級(jí)快的生成SpiderMonkey AST的解釋器。它帶有一個(gè)實(shí)用的迷你CLI,能解釋一個(gè)文件、把AST轉(zhuǎn)存為JSON并標(biāo)準(zhǔn)輸出。可以這樣用UglifyJS來壓縮混淆:

    acorn file.js | uglifyjs --spidermonkey -m -c

--spidermonkey選項(xiàng)能讓UglifyJS知道輸入文件并非JavaScript,而是SpiderMonkey AST生成的JSON代碼。這事我們不用自己的解釋器,只把AST轉(zhuǎn)成我們內(nèi)部AST。

使用 Acorn 來解釋代碼

更有趣的是,我們加了 --acorn選項(xiàng)來使用Acorn解釋所有代碼。如果你傳入這個(gè)選項(xiàng),UglifyJS會(huì)require("acorn")

Acorn確實(shí)非常快(650k代碼原來要380ms,現(xiàn)在只需250ms),但轉(zhuǎn)換Acorn產(chǎn)生的SpiderMonkey樹會(huì)額外花費(fèi)150ms。所以總共比UglifyJS自己的解釋器還要多花一點(diǎn)時(shí)間。

使用 UglifyJS 轉(zhuǎn)換 SpiderMonkey AST

現(xiàn)在你可以像使用其他中間工具一樣使用UglifyJS將JS抽象語法樹轉(zhuǎn)換為SpiderMonkey格式。

例如:

function uglify(ast, options, mangle) {// 把SpiderMonkey AST 轉(zhuǎn)成中間格式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();}// 轉(zhuǎn)回 SpiderMonkey ASTreturn uAST.to_mozilla_ast();
}

原博文有更多細(xì)節(jié)。

API參考

假如是通過NPM安裝的,你可以這樣在你的應(yīng)用中加載UglifyJS:

var UglifyJS = require("uglify-js");

它會(huì)輸出很多模塊,但我在此只介紹一下涉及解釋、混淆和壓縮的基礎(chǔ)代碼。按(1)
解釋, (2) 壓縮, (3) 混淆, (4) 生成輸出代碼的順序。

簡(jiǎn)易使用模式

minify是一個(gè)頂級(jí)的、單獨(dú)、包含所有步驟的方法。如果你不需要進(jìn)一步自定義的話,你應(yīng)該會(huì)喜歡使用它。

例子:

var result = UglifyJS.minify("/path/to/file.js");
console.log(result.code); // 最小化輸出
// 假如你不想傳一個(gè)文件名,而是要傳入一段代碼
var result = UglifyJS.minify("var b = function () {};", {fromString: true});

你也可以壓縮多個(gè)文件:

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);

你也可以用一個(gè)帶fromString選項(xiàng)的對(duì)象來要生成sourcemap:

var result = UglifyJS.minify({"file1.js": "var a = function () {};"}, {outSourceMap: "out.js.map",outFileName: "out.js",fromString: true
});

要注意,此時(shí)sourcemap并不會(huì)保存為一份文件,它只會(huì)返回在result.map中。outSourceMap 的值只用來在result.code中設(shè)置//# sourceMappingURL=out.js.mapoutFileName 的值只用來在sourcemap文件中設(shè)置 file屬性。

sourcemap(查閱規(guī)格)中的file屬性會(huì)優(yōu)先使用 outFileName ,假如沒有,會(huì)從outSourceMap中推導(dǎo)(就是去掉'.map')。

你可以把sourceMapInline設(shè)為true ,這樣sourcemap會(huì)加在代碼末尾。

你也可以指定sourcemap中的源文件根目錄(sourceRoot)屬性:

var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ], {outSourceMap: "out.js.map",sourceRoot: "http://example.com/src"
});

如果你要壓縮從其他文件編譯得來的帶一份sourcemap的JS文件,你可以用inSourceMap參數(shù):

var result = UglifyJS.minify("compiled.js", {inSourceMap: "compiled.js.map",outSourceMap: "minified.js.map"
});
// 跟之前一樣,返回 `code`和 `map`

如果你要輸入的sourcemap并非一份單獨(dú)文件,你可以在對(duì)象參數(shù)中設(shè)置inSourceMap參數(shù):

var result = UglifyJS.minify("compiled.js", {inSourceMap: JSON.parse(my_source_map_string),outSourceMap: "minified.js.map"
});

只有在需要outSourceMap時(shí), inSourceMap 才會(huì)被用到(否則就沒用咯)。

要設(shè)置sourcemap的url的話,請(qǐng)用 sourceMapUrl選項(xiàng)。

如果你要用 X-SourceMap 請(qǐng)求頭,你可以把sourceMapUrl選項(xiàng)設(shè)為false。
outSourceMap的默認(rèn)設(shè)置:

var result = UglifyJS.minify([ "file1.js" ], {outSourceMap: "out.js.map",sourceMapUrl: "localhost/out.js.map"
});

其他選項(xiàng):

  • warnings (默認(rèn) false) — 傳true來現(xiàn)實(shí)壓縮器的警告
  • fromString (默認(rèn) false) — 傳true的話,你可以輸入JS源碼,而不是文件名。
  • mangle (默認(rèn) true) — 傳false來跳過混淆步驟,或者傳一個(gè)對(duì)象來特定指明混淆選項(xiàng)(下面詳述)。
  • mangleProperties (默認(rèn) false) — 傳一個(gè)對(duì)象來自定義指明混淆對(duì)象屬性的選項(xiàng)。
  • output (默認(rèn) null) — 如果你要進(jìn)一步指定輸出選項(xiàng),請(qǐng)傳一個(gè)對(duì)象。默認(rèn)是壓縮到最優(yōu)化。
  • compress (默認(rèn) {}) — 傳false的話就跳過整個(gè)壓縮步驟。自定義的話請(qǐng)傳一個(gè)壓縮選項(xiàng)對(duì)象。
  • parse (默認(rèn) {}) — 如果你要進(jìn)一步自定義解釋步驟請(qǐng)傳一個(gè)解釋選項(xiàng)對(duì)象(不是所有選項(xiàng)都有效....下面再說)。

混淆

  • except - 傳一個(gè)應(yīng)該排除在混淆之外的標(biāo)識(shí)的數(shù)組。

    • toplevel — 混淆那些定義在頂層作用域的名字(默認(rèn)禁用)。
    • eval — 混淆那些在with或eval中出現(xiàn)的名字(默認(rèn)禁用)。
    • keep_fnames -- 默認(rèn)false。傳true的話就不混淆函數(shù)名。對(duì)那些依賴Function.prototype.name的代碼有用。延展閱讀:keep_fnames 壓縮選項(xiàng).

例子:

  //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;'

混淆屬性名選項(xiàng)

  • regex — 傳一個(gè)正則,僅混淆匹配到的名字。(與--mangle-regex CLI參數(shù)選項(xiàng)關(guān)聯(lián))
  • ignore_quoted – 只混淆非括號(hào)中的屬性名(與--mangle-props 2 CLI 參數(shù)選項(xiàng)關(guān)聯(lián))
  • debug – 讓混淆后的名字與原名字有關(guān)。與--mangle-props-debug CLI 參數(shù)選項(xiàng)關(guān)聯(lián))。默認(rèn)是false。傳一個(gè)空字符串來啟用,或者傳一個(gè)非空字符串來添加后綴。

高級(jí)使用模式

如果minify函數(shù)太簡(jiǎn)單不能滿足你的需求,下面這些API信息有更多的細(xì)節(jié)詳情:

解釋器

var toplevel_ast = UglifyJS.parse(code, options);

options 是可選的,要傳的話就必須傳個(gè)對(duì)象。下面這些是有效的屬性:

  • strict — 禁用自動(dòng)添加分號(hào),禁止數(shù)組、對(duì)象末尾還有逗號(hào)。
  • bare_returns — 允許函數(shù)返回外部。(與 --bare-returns CLI參數(shù)選項(xiàng)關(guān)聯(lián),對(duì)minify parse選項(xiàng)對(duì)象也有效。)
  • filename — 輸入的文件名。
  • toplevel — 一個(gè) toplevel 節(jié)點(diǎn)。 (就是之前調(diào)用parse返回的)

后面兩個(gè)選項(xiàng)是當(dāng)你要最小化多個(gè)文件成一個(gè)文件(以及正確的sourcemap)時(shí)有用。我們的CLI會(huì)像這樣處理:

var toplevel = null;
files.forEach(function(file){var code = fs.readFileSync(file, "utf8");toplevel = UglifyJS.parse(code, {filename: file,toplevel: toplevel});
});

完成后,我們就在toplevel這個(gè)大AST里包含了我們的所有文件,每一份都帶著正確的來源信息。

作用域信息

UglifyJS包含一個(gè)作用域分析器,你可以在壓縮、混淆前手動(dòng)調(diào)用。基本上,它添加了AST中的節(jié)點(diǎn)在哪里被命名、被引用了多少次、是否全局的、是否在evalwith中聲明等等。我們將討論除此之外的,那些在你對(duì)AST進(jìn)行任何操作前必須知道的重要事項(xiàng):

toplevel.figure_out_scope()

壓縮

就如這樣:

var compressor = UglifyJS.Compressor(options);
var compressed_ast = compressor.compress(toplevel);

options可以不要。之前的“壓縮器選項(xiàng)“中已經(jīng)講過可以填什么。默認(rèn)選項(xiàng)對(duì)大多數(shù)腳本來說應(yīng)該都是最佳的。

壓縮器是破壞性的,所以不要依賴那些源樹toplevel

混淆

壓縮之后再調(diào)用一次figure_out_scope是個(gè)好做法(因?yàn)閴嚎s過程可能會(huì)干掉一些沒用的、不可達(dá)的代碼,改變標(biāo)識(shí)的數(shù)量和位置),你也可以選擇在Gzip(統(tǒng)計(jì)不可混淆的詞中字符的使用頻率)后調(diào)用。例如:

compressed_ast.figure_out_scope();
compressed_ast.compute_char_frequency();
compressed_ast.mangle_names();

生成輸出代碼

AST節(jié)點(diǎn)帶一個(gè)print方法,用來生成輸出流。基本上,要生成代碼你只要這么做:

var stream = UglifyJS.OutputStream(options);
compressed_ast.print(stream);
var code = stream.toString(); // 這就是你最小化后的代碼

又或者這樣縮寫:

var code = compressed_ast.print_to_string(options);

通常情況下options是可選的。輸出流可以接收一堆選項(xiàng)參數(shù),絕大多數(shù)在”美化選項(xiàng)“中有闡述。我們所關(guān)心的是source_mapcomments選項(xiàng)。

在輸出代碼中保留注釋

你需要傳入comments選項(xiàng)來保留某些注釋。你可以傳正則表達(dá)式(以/包裹或正則對(duì)象)、布爾值或函數(shù)。也可以傳字符串allsomesome等同于CLI中--comments不帶任何參數(shù)。如果你傳正則,只有匹配到的注釋會(huì)被保留。注意,匹配的主體不包括 ///*。如果你傳函數(shù),每遇到樹中的注釋都會(huì)調(diào)用一下,傳入兩個(gè)參數(shù),一是注釋所依附的節(jié)點(diǎn),二是注釋標(biāo)識(shí)本身。

注釋標(biāo)識(shí)有如下屬性:

  • type: 單行注釋是"comment1",多行注釋 "comment2"。
  • value: 注釋體本身。
  • posendpos: 注釋在源碼中出現(xiàn)的起始位置/結(jié)束位置(從0開始索引)。
  • linecol: 注釋在源碼中出現(xiàn)的行和列。
  • file — 源碼的文件名
  • nlb — 在源碼中,如果注釋前有一空行或注釋另起新一行的話是true

你的函數(shù)返回true的話就保留注釋,其他返回值都代表false。

生成sourcemap

你需要在調(diào)用print時(shí)傳source_map參數(shù)。source_map參數(shù)需要是SourceMap對(duì)象(在source-map庫頂部有個(gè)小框框里說了)。

例子:

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 屬性 (詳看 規(guī)格)
  • orig: "original source map",方便你想讓sourcemap映射到生成JS的源碼上。此參數(shù)可以只是字符串或json,也可以是包含源碼sourcemap的json對(duì)象。

兼容版

Harmony

如果你想使用能最小化ES6+的實(shí)驗(yàn)性質(zhì)的兼容分支,請(qǐng)?jiān)谀愕?code>package.json 文件中加上下面代碼:

"uglify-js": "git+https://github.com/mishoo/UglifyJS2.git#harmony"

或者直接安裝兼容實(shí)驗(yàn)版UglifyJS:

npm install --save-dev uglify-js@github:mishoo/UglifyJS2#harmony

更多細(xì)節(jié)請(qǐng)看 #448

總結(jié)

以上是生活随笔為你收集整理的UglifyJS中文文档的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。