nodejs合并壓縮javascript和css的方法教程

來源:互聯網
上載者:User

對於壓縮公用程式前端攻城師最常見的就是雅虎的Yui Compressor / Google的Closure Compiler了。

對比其他壓縮公用程式相對在JS和CSS壓縮領域比較成熟,壓縮率也比較好.

一般會選擇結合ANT實現壓縮併合並,效果也不錯,但是比較偏向個人,團隊協作每個人都部署java/ant有些麻煩。

對於個人開發使用ANT的方案也是相對不錯的選擇。對於團隊,最好的解決辦法是在服務端壓縮,大家只需要登入並執行一個統一的指令碼。

下面分享下大致的測試結果,和改用nodejs壓縮合并js/css的原因。

js部分採用UglifyJS

1. 壓縮jquery 1.8,253 KB:使用UglifyJS(以下簡稱UJ): 90.5 KB;使用Closure Compiler(以下簡稱CC): 91.1 KB。

2. 如果在閉包(function($, window, undefined) {...})(jQuery, window); 內的 unused function/variables

CC會被刪除沒使用的;UJ 預設全部保留,加上 pro.ast_lift_variables(ast) 才會刪除未使用的函數/變數 (對象/數組 不會被刪除)。

如果直接暴漏在window下的,兩個基本差不多。

3. function c(){2}, CC 會警告,UJ不會

4. function c(){e()2},都會拋出異常,顯示行數,錯誤原因。CC提示列錯誤,UJ不會。

5. function c(){e();2},都保留了2,CC 警告,UglifyJS 無資訊

6. CC 一次顯示JS裡的全部錯誤(有些是前面的錯誤引起的, 所以部分是誤判),UJ每次只顯示一個錯誤。

7. 0 = {}; CC會報錯,而UJ不會。

8. if語句都可很好的最佳化。

9. CC喜歡把變數/函數(結構簡單的)內的語句,直接插入到使用它們的地方,UJ維持原樣。

如果函數內的內容較少, CC會把函數的內容直接插入到調用它的地方,比如:

function c(){xxxxxxx('12345678901234567');}

function c(){xxxxxx.yyyyy('12345678901234');}

function c(){xxxxxx.yyyyy.zzzz('12345678901');}

function c(){if (X){alert('1234')};alert('12');}

當其他函數裡調用c()時,會把c()方法刪除,然後把c()內的內容移動到這裡

(當裡面的字串長度+1後,就會直接使用原函數c(),所以CC這裡是根據字元長度)。

10. 如果是很長的字串, var str ='很長......很長'; 在其他函數內用到str,CC會把str的值直接插入,而UJ不會。

11. 10000 都會轉成 1e4。

12. alert(3*7) 都會轉成 alert(21)。

13. function c() {}; function b(){return; c();}; CC/UJ(開啟 --lift-vars) 都會刪除 c() 的代碼。

14. 這段代碼:(function() {return;})(); CC會刪除,UJ不會。

綜上,CC是編譯器,有進階最佳化選項,UJ目前只能算是壓縮器。CC喜歡把函數外的字串值/內容簡單的函數內容,直接插入到使用它的地方,所以有時這樣反而增加了壓縮後的檔案大小。

對於壓縮後的大小,UJ壓縮的一般比CC稍大,一般1KB左右。

壓縮速度,CC想的事情比較多,而且需要java,所以壓縮慢,UJ 速度飛快。

如果網站結構複雜,JS比較多的時候,UJ的速度優勢就非常明顯了。

所以團隊成員無JS新手,使用UJ是個不錯的選擇。

另外, uglifyjs2 也在開發中,比UJ1的壓縮效果好一些,https://github.com/mishoo/uglifyjs2,

對比uglifyjs1:

(function() {return;})(); 會變成:function(){}(), 刪除了return;

0 = {}; 還是不會報錯;

未使用的方法/變數移除時,會輸出WARN資訊;

function c(){e();2} 會把2刪除,並有WARN資訊;

提示資訊的行號部分有偏差(少了1行);

因為還是beta版,UJ2的一些問題都算正常的,UJ2由UJ1改進而來,測試中也沒發現重大bug,所以採用UJ2還算靠譜。

PS: 最近應用發現2個bug:

沒用的內部變數, 沒刪除完整, 剩下了 "var;"

壓縮檔末尾沒加上";"號, 當2個檔案合并後如果這樣, 問題就大了:

var a={};a.x=function(){console.log(this)} //file1
(function(){...})() //file2 // 變成a.x()()了..

所以上面的2個bug, 需要自己寫2個正則解決掉.

css部分採用clean-css

CSS壓縮找到的有:

https://github.com/GoalSmashers/clean-css

https://github.com/ded/sqwish

https://github.com/fczuardi/node-css-compressor

對比後,選擇了clean-css,壓縮速度和效果都還不錯,目前發現的問題:.a{}這樣的無內容的規則,不會被清理。

改用nodejs壓縮,1是源碼是JS的,發現bug可以快速解決;2是nodejs的非同步多線程IO特性,可以多線程壓縮,壓縮速度提升明顯;3是統一了環境,不需要再依賴java。並且合并檔案也非常簡單。

壓縮合并的大體思路:

build.js:

var argv = process.argv, arguments = argv.splice(2);

用來接收傳遞的參數,比如可以:sudo ./build.js css {project path}

var buildType = arguments[0], projectPath = arguments[1];

簡單的項目,就可以去project path的assets目錄遍曆待壓縮的檔案,進行壓縮。

進階點的,可以把檔案清單寫到配置,var maps = require('map').maps; 然後遍曆maps進行壓縮合并,只壓縮map的結構一維就夠了,如果想壓縮併合並,可以改成二維的結構。

再進階點,遍曆檔案夾得到待壓縮的檔案(想辦法去掉不需要壓縮的檔案),再根據規則產生待合并的檔案名稱,然後自動產生map。

再進階點,自動產生map的同時,針對檔案產生md5,下次壓縮根據md5判斷,如果檔案內容變動,才壓縮並重建map。

當然,也不是後面的方法最好,選擇適合自己的就是最好的。

大體上,這樣就可以製作“傻瓜版”壓縮公用程式了,只需要輸入參數,其他的不需要管。

我們的做法是讀取header / footer 的部分, 匹配標記產生待壓縮的檔案清單和合并後的目標檔案名,比如:

<!-- target="pkg1.min.js" {{{ -->
<script src="a1.js"></script>...<script src="b1.js"></script>
<!-- }}} -->
<!-- target="pkg2.min.js" {{{ --> ... <!-- }}} -->

然後產生帶MD5的map,對比檔案是否改動,選擇性壓縮,再合并到target指向的目標檔案。

開發時使用未壓縮的,上線前壓縮合并,再自動把header/footer未壓縮的注釋掉,加上合并後的JS/CSS。

使用UglifyJS2、clean-css的壓縮代碼,已經放到github,https://github.com/kairyou/f2e-tools/tree/master/libs。

require build-css-cc.js或build-js-uj2.js,就可以使用裡面的build方法壓縮了。

另外,壓縮時需要發送錯誤時終止並提示,所以壓縮時的讀取是sync方式,但是組建檔案map、產生MD5、合并檔案部分可以採用非同步方式。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.