譯者:李平海javascript
轉載請註明原文連接(https://github.com/LiPinghai/... )與做者信息。html
因爲webpack自己集成了UglifyJS插件(webpack.optimize.UglifyJsPlugin),其命令webpack -p
即表示調用UglifyJS來壓縮代碼,還有很多webpack插件如html-webpack-plugin
也會默認使用UglifyJS。所以咱們其實常常要用到它,但UglifyJS2自己配置較複雜/選項繁多,又沒有中文文檔,使用起來如墜雲霧。鑑於此特翻譯此文,謬誤甚多,敬請斧正。java
本文檔譯自UglifyJS2文檔。node
另有UglifyJS3中文文檔在此webpack
喜歡的話請收藏、給個贊/star吧!謝謝!git
詞典:github
parse 解釋 compress 壓縮 mangle 混淆 beautify 美化 minify 最小化 CLI 命令行工具 sourcemap 編譯後代碼對源碼的映射,用於網頁調試 AST 抽象語法樹 name 名字,包括變量名、函數名、屬性名 toplevel 頂層做用域 unreachable 不可達代碼 option 選項 STDIN 標準輸入,指在命令行中直接輸入 STDOUT 標準輸出 STDERR 標準錯誤輸出 side effects函數反作用,即函數除了返回外還產生別的做用,好比改了全局變量
如下爲正文:web
UglifyJs 是一個js 解釋器、最小化器、壓縮器、美化器工具集(parser, minifier, compressor or beautifier toolkit)。正則表達式
這個網頁是命令行使用的文檔,要看API和內部文檔請到UglifyJS做者的網站。
另外還有個在線demo(FF、chrome,safari可能也行)chrome
uglify-js
的發行版本只支持ES5,若是你要壓縮ES6+代碼請使用兼容開發分支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)
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
)
假如你的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,因此你能夠忽略不寫輸入文件。
你須要傳入--mangle
(-m
)來使啓用混淆功能。支持用逗號隔開選項:
toplevel
— 混淆在最高做用域中聲明的變量名(默認disabled)eval
- 混淆在eval
或 with
做用域出現的變量名(默認disabled)當啓用混淆功能時,若是你但願保留一些名字不被混淆,你能夠用--reserved
(-r
) 聲明一些名字,用逗號隔開。例如:
uglifyjs ... -m -r '$,require,exports'
防止require
, exports
和 $
被混淆改變。
--mangle-props
)警告:這能會搞崩你的代碼。混淆屬性名跟混淆變量名不同,是相互獨立的。傳入--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_
, 你能夠在每次編譯是都改變一下,來辨清屬性名怎麼被混淆的。一個小技巧,你能夠每次編譯時傳隨機數來模仿混淆操做(例如你更新了腳本,有了新的屬性名),這有助於識別混淆時的出錯。
你要傳入 --compress
(-c
)來啓用壓縮功能。你能夠用逗號隔開選項。選項的形式爲foo=bar
,或者就foo
(後者等同於你要設爲true
,至關於foo=true
的縮寫)。
sequences
(默認true) -- 連續聲明變量,用逗號隔開來。能夠設置爲正整數來指定連續聲明的最大長度。若是設爲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
或 valueOf
object得出的時候,轉換可能會不安全,可能會引發運算對象的改變。此選項只有當 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/continuejoin_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
聲明,構建後還會被保留。若是你的運行環境低於ES六、不支持const
,請用var
聲明加上reduce_vars
設置(默認啓用)來實現。
你也能夠經過程序API來設置編譯配置。其中有差異的是一個壓縮器屬性global_defs
:
uglifyJS.minify([ "input.js"], { compress: { dead_code: true, global_defs: { DEBUG: false } } });
代碼生成器默認會輸出儘可能簡短的代碼。假如你想美化一下輸出代碼,請設置--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
(註釋所依附的抽象語法樹節點)沒有被引用、會被壓縮器幹掉。
書寫版權信息(或其餘須要在輸出文件中保留的信息)的最安全位置是全局節點。
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解釋全部代碼。若是你傳入這個選項,UglifyJS會require("acorn")
Acorn確實很是快(650k代碼原來要380ms,如今只需250ms),但轉換Acorn產生的SpiderMonkey樹會額外花費150ms。因此總共比UglifyJS本身的解釋器還要多花一點時間。
如今你能夠像使用其餘中間工具同樣使用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 AST return uAST.to_mozilla_ast(); }
原博文有更多細節。
假如是經過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。
你須要在調用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對象。若是你想使用能最小化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