node.js 使用 UglifyJS2 高效率壓縮 javascript 文件


UglifyJS2 這個工具使用很長時間了,但之前都是在 gulp 自動構建 時用到了 UglifyJS 算法進行壓縮. 最近玩了一下 UglifyJS2 ,做了一個 在線壓縮javascript工具 歡迎點擊玩耍.

為什么要壓縮 javascript

因為每個人開發者的書寫習慣,定義參數習慣,已經使用習慣都不一樣. 所以相同的功能出自不同開發者代碼各異.這里牽扯到一個代碼所占空間.

以前端為例來說明

大家通常都會認為,現在在網絡時代,動不動就是10M光纖,撥號上網讓人感覺是上個世紀的方式… 說法是沒有問題,但是,我們今天討論的並不是終端下載速度. 而是前端壓縮對服務器有何利好!


現在的前端越來越重,富客戶端方式讓人有更好的體驗,所以前端各種框架,插件空前盛行


我們普普通通引用一個第三方包或者開源插件,輕則幾十K,重則上M,十幾M 都很常見. 如果一個客戶端連接,服務器需要傳輸100K ,那么如果同時有幾百個,幾千個客戶端並發時,服務器輸出帶寬是多大? 再想想公司租賃帶寬一年費用多少? (這可不是我們普通家庭包年寬帶的價格)

如果你可以把前端 100k 的靜態資源壓縮到 50k ,那么在相同帶寬的情況下,是不是可以提高服務器並發量.這就是直接幫公司省錢了.

還有一個原因:

頁面加載,我們通常的優化方案是把 css 放到 head 里面加載,把 javascript 放到 body 結束處加載. 就是因為 javascript 的運行機制是單線程,如果你把大量的 javascript 腳本放在 head 處加載,無形中影響了 頁面渲染速度. 當然現在 html5 也在優化一些更優的方案. 但是不論這沒有,小文件的加載一定比大文件加載用戶體驗更好.

開始學習下 UglifyJS2

UglifyJS 和 UglifyJS2 是什么關系 UglifyJS是UglifyJS2的前身, 它是一個Javascript開發的通用的語法分析、代碼壓縮、代碼優化的工具. 基於Nodejs環境開發,支持CommonJS模塊系統的任意的Javascript平台.

UglifyJS 功能 生成JS代碼的抽象語法樹(AST),通過parse-js.js完成. 遍歷AST語法樹,做各種操作,比如自動縮進、縮短變量名、刪除塊括號{}、去空格、常量表達式、連續變量聲明、語塊合並、去掉無法訪問的代碼等,通過process.js完成.

UglifyJS2 是 UglifyJS 的改進版 作者對之前的 UglifyJS 做了很多的優化,包括下面手段:

  • parser,用於實現抽象語言法樹(AST)
  • the code generator, 通過AST生成JS代碼和source map
  • compressor, 用於JS代碼的壓縮
  • mangler, 用於減少局部變量的命名,用單字母替換
  • scope analyzer, 用來判斷 變量定義范圍和變量引用范圍的工具
  • tree walker, AST樹遍歷工具
  • tree transformer, AST樹轉換工具

UglifyJS2安裝

npm 全局安裝

npm install uglify-js -g

你也可以通過 github 來下載源碼使用

git clone git://github.com/mishoo/UglifyJS2.git

UglifyJS2 參數說明

➜ /Users/zhangzhi/code >uglifyjs --help uglifyjs input1.js [input2.js …] [options] Use a single dash to read input from the standard input.

NOTE: by default there is no mangling/compression. Without [options] it will simply parse input files and dump the AST with whitespace and comments discarded. To achieve compression and mangling you need to use -c and -m.

Options: –source-map Specify an output file where to generate source map. –source-map-root The path to the original source to be included in the source map. –source-map-url The path to the source map to be added in //# sourceMappingURL. Defaults to the value passed with --source-map. –source-map-include-sources Pass this flag if you want to include the content of source files in the source map as sourcesContent property. –in-source-map Input source map, useful if you’re compressing JS that was generated from some other original code. –screw-ie8 Pass this flag if you don’t care about full compliance with Internet Explorer 6-8 quirks (by default UglifyJS will try to be IE-proof). –expr Parse a single expression, rather than a program (for parsing JSON) -p, --prefix Skip prefix for original filenames that appear in source maps. For example -p 3 will drop 3 directories from file names and ensure they are relative paths. You can also specify -p relative, which will make UglifyJS figure out itself the relative paths between original sources, the source map and the output file. -o, --output Output file (default STDOUT). -b, --beautify Beautify output/specify output options. -m, --mangle Mangle names/pass mangler options. -r, --reserved Reserved names to exclude from mangling. -c, --compress Enable compressor/pass compressor options. Pass options like -c hoist_vars=false,if_return=false. Use -c with no argument to use the default compression options. -d, --define Global definitions -e, --enclose Embed everything in a big function, with a configurable parameter/argument list. –comments Preserve copyright comments in the output. By default this works like Google Closure, keeping JSDoc-style comments that contain “@license” or "@preserve". You can optionally pass one of the following arguments to this flag: - “all” to keep all comments - a valid JS regexp (needs to start with a slash) to keep only comments that match. Note that currently not all comments can be kept when compression is on, because of dead code removal or cascading statements into sequences. –preamble Preamble to prepend to the output. You can use this to insert a comment, for example for licensing information. This will not be parsed, but the source map will adjust for its presence. –stats Display operations run time on STDERR. –acorn Use Acorn for parsing. –spidermonkey Assume input files are SpiderMonkey AST format (as JSON). –self Build itself (UglifyJS2) as a library (implies –wrap=UglifyJS --export-all) –wrap Embed everything in a big function, making the “exports” and “global” variables available. You need to pass an argument to this option to specify the name that your module will take when included in, say, a browser. –export-all Only used when --wrap, this tells UglifyJS to add code to automatically export all globals. –lint Display some scope warnings -v, --verbose Verbose -V, --version Print version number and exit. –noerr Don’t throw an error for unknown options in -c, -b or -m. –bare-returns Allow return outside of functions. Useful when minifying CommonJS modules. –keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name. –reserved-file File containing reserved names –reserve-domprops Make (most?) DOM properties reserved for –mangle-props –mangle-props Mangle property names –mangle-regex Only mangle property names matching the regex –name-cache File to hold mangled names mappings

> 上面列出了好多的選項,如果使用的時候不明白,可以對比看下下面的說明 * source-map [string],生成source map文件。 * source-map-root [string], 指定生成source map的源文件位置。 * source-map-url [string], 指定source map的網站訪問地址。 * source-map-include-sources,設置源文件被包含到source map中。 * in-source-map,自定義source map,用於其他工具生成的source map * screw-ie8, 用於生成完全兼容IE6-8的代碼。 * expr, 解析一個表達式或JSON * -p, prefix [string], 跳過原始文件名的前綴部分,用於指定源文件、source map和輸出文件的相對路徑。 * -o, output [string], 輸出到文件。 * -b, beautify [string], 輸出帶格式化的文件。 * -m, mangle [string], 輸出變量名替換后的文件。 * -r, reserved [string], 保留變量名,排除mangle過程。 * -c, compress [string], 輸出壓縮后的文件。 * -d, define [string], 全局定義。 * -e, enclose [string], 把所有代碼合並到一個函數中,並提供一個可配置的參數列表。 * comments [string], 增加注釋參數,如@license@preserve * preamble [string], 增加注釋描述。 * stats, 顯示運行狀態。 * acorn, Acorn做解析。 * spidermonkey, 解析SpiderMonkey格式的文件,如JSON * self, UglifyJS2做為依賴庫一起打包。 * wrap, 把所有代碼合並到一個函數中。 * export-all, 和–wrap一起使用,自動輸出到全局環境。 * lint, 顯示環境的異常信息。 * -v, verbose, 打印運行日志詳細。 * -V, version, 打印版本號。 * noerr, 忽略錯誤命令行參數。 # UglifyJS2 使用方法 > UglifyJS2使用包括2種方式 1. shell 指令調用 2. api 調用 >> shell 指令 我們嘗試用來壓縮2個文件  /Users/zhangzhi/code/test > 我的 test 目錄下有好多 js 文件,准備挑選2 js 文件 ( start.js  test.js) 進行合並,合並后的文件名為 min.js ```shell ➜ /Users/zhangzhi/code/test >uglifyjs start.js test.js -o min.js --source-map min.js.map

然后看下當前目錄:

多出了2個文件 , min.js 和 min.js.map

壓縮后的樣子是這樣的

api 調用方法

var fs = require('fs'); var uglifyjs = require("uglify-js"); var result = uglifyjs.minify("../test.js",{ mangle:false });

上面的一個基本核心方法 minify ,下面我們單獨看下這個方法

minify 方法

這是一個非常智能的方法 ,共 2個參數

  • 第一個參數 *

支持 字符串,路徑,路徑數組

1.字符串參數

就是我們書寫的 javascript 代碼可以直接當做一個字符串參數參數函數,但是需要有第二個參數告訴函數,這是 javascript 源碼字符串

var result = uglifyjs.minify("var fun=function(){ alert('一介布衣博客');};",{ mangle:false, fromString:true, });

上面的第一個參數傳入了 javascript 源碼,第二個參數中 formString : true ,就是告訴 minify 函數,前面的參數是 需要壓縮的 javascript 源碼.

  1. 字符串路徑

這是函數默認支持的一種方式,可以單獨的一個參數,直接給定一個 需要壓縮的 javascript 文件路徑, 當然也可以2個參數.

var result = uglifyjs.minify("../test.js");

上面的函數執行,會吧我的上級目錄中的 test.js 進行壓縮.默認一個參數時,表示文件路徑

  1. 數組指定多個路徑

可以一個參數,但是這個參數是一個數組 [ ‘路徑1’,‘路徑2’,‘路徑3’] 類似這樣 結果就是把上面路徑的所有 javascript 壓縮后返回到了 result 對象中,稍后我們單獨說下 result 返回值.

var result = uglifyjs.minify([ "../test.js", "../mian.js"]);
  • 第二個參數*

參數說明

  • romString屬性 (default false) 指定第一個參數中的 字符串是 javascript 源碼

  • mangle屬性 默認為true;指定為false時,表示不進行混淆壓縮

  • width和max-line-len屬性 按照說明,這里應該是指壓縮后的文件的長度

  • outSourceMap屬性 用來指定函數返回值result.map字符串轉化為Object后file屬性的值

  • sourceRoot屬性 用來指定函數返回值result.map字符串轉化為Object后sourceRoot屬性的值

  • 返回值 result *

返回值 result 是一個對象. code 屬性對應的是壓縮后的腳本

{"code":"這里是壓縮后的 javascript 腳本","map":null}

<p style=“color:white;”>出自:<a style=“color:white;” href=“http://yijiebuyi.com/blog/88e7fe09ac514c8b56ff9936cefdf142.html” >node.js 使用 UglifyJS2 高效率壓縮 javascript 文件</a></p>

8 回復

馬克 自豪地采用 CNodeJS ionic

 

有混淆的工具么.

 
 

@ystyle 這個工具就是帶混淆的 mangle屬性 默認為true;指定為false時,表示不進行混淆壓縮.

 

服務端的代碼需要壓縮嗎?

 

@zzhi191 前幾天還有同事,沒有設置任何參數使用 uglify,結果 js 跑起來總是報錯。

后來發現是因為使用了 seajs,而 mangle 把 require 關鍵詞混淆了,導致 seajs 無法工作。

各位注意一下

 

@alsotang 使用 commonjs-wrap?

 
 

@alsotang 好的,多謝,又發現一個坑

 
 

@WilliamDu1981 不需要


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM