引子: 別的複雜前端開發技術不會,用得多的還是手寫代碼,手動處理。 3年前手寫合併壓縮js和css文件的asp腳本代碼目前還能正常運行,也就沒有多大使用別的技術的動力。 直到近期被一個問題糾結著,今天花了一天時間摸索完成了一個後端構建功能。 目前接觸到的項目前端開發模式基本上是一樣的 1. 項目不會 ...
引子:
別的複雜前端開發技術不會,用得多的還是手寫代碼,手動處理。
3年前手寫合併壓縮js和css文件的asp腳本代碼目前還能正常運行,也就沒有多大使用別的技術的動力。
直到近期被一個問題糾結著,今天花了一天時間摸索完成了一個後端構建功能。
目前接觸到的項目前端開發模式基本上是一樣的
- 項目不會很大
- 通用css、js、第三方庫會獨立成單個文件
- 頁面依賴的多個文件會合併成一個css或js文件,併進行自定義語法編譯和壓縮混淆
- 多個頁面會用到的但不夠通用的會獨立成一個html文件,內嵌style、script標簽,伺服器端後端運行時包含進來
- 頁面使用的js、css完全內嵌style、script標簽(無法抗拒的優點:打開一個文件就能看到所有源代碼)
- 曉得這種模式很low,不過好用
瞭解到的前端構建方式
針對2、3項,跟目前看到的前端自動化構建工具,比如:webpack、gulp,其實處理思想上還是比較吻合,壓縮混淆實現是調用的一個壓縮js和css網站的介面tool.css-js.com/compressor.html
。
針對4、5項這種內嵌的style和script,以前是沒有任何處理,一個月前特意加上了壓縮混淆功能。實現方式是開發階段完成相關文件的壓縮混淆:壓縮混淆是只要頁面一運行,相關前端代碼後端會自動化處理;然後手動上傳結果到伺服器。如果源碼有改動,必須重新壓縮混淆和上傳文件(自己寫的後臺工具是這樣的規則)。
最近就是被如果源碼有改動,必須重新壓縮混淆和上傳文件
這個問題困擾著,一個是操作複雜,致命的是:如果漏上傳了混淆後的文件。。。
好,現在知道目前採用的壓縮混淆方式了:編寫前端代碼,後端代碼自動處理生成新的壓縮混淆後的代碼。
前奏
既然後端已經有壓縮混淆功能了,那麼還要這麼複雜的操作流程就多餘了。為什麼不扔到伺服器上自動處理?是考慮到第三方網站介面的穩定性,如果他們掛了,至少不影響線上功能(他們確實經常掛)。
問題出在第三方壓縮混淆介面上,那把功能本地化不就穩定了,沒毛病是這個邏輯。
昨天想了一下,如果要本地實現壓縮混淆css和js,涉及的代碼有點多,就放棄了。
今天上午又想了一下,如果不提前搞好,光生成出來的文件就一大堆,而且本質是次要的生成文件,提交svn的時候還要特殊對待,不提交又會導致新檢出項目可能丟失文件,提交的話又算是垃圾文件。還要上傳,如果是差異更新就有的對比了。必須動手了。
進行時
要壓縮css,有很多辦法:正則替換空白
,不過複雜css格式去掉空白後語義是不是一致就難說了;用現成的工具,甚至可以帶來更好的開發方式的less
、sass
,最終採用了less,看別人說的sass比less更好,不過要額外學和安裝Ruby起點比less高了許多;最終採用less方案。
壓縮js,uglifyjs
不二選擇。
安裝node模塊
cnpm install -g ing...
目前最新版本less 3.0.1壓縮css遇到問題:The compress option has been deprecated
-x
新版本選項不能用了,得知裝上less-plugin-clean-css
用--clean-css
命令可以進行壓縮。
好吧裝上less-plugin-clean-css 1.5.1,Unable to load plugin clean-css please make sure that it is installed
識別不到麽,到less-plugin-clean-css
看到一個issusehttps://github.com/less/less-plugin-clean-css/issues/24
說是要降級到2.x。
cnpm show less versions
查詢到less 2.x最高版本2.7.3,裝上壓縮成功。
uglifyjs 3.3.16最新版,裝上就能壓縮混淆,研究了一下參數,提供-m -c
兩個參數就足夠了,-m
混淆變數名,-c
壓縮優化代碼。
後端代碼接入和運行測試
後端接入方式和控制台敲命令行是一樣的,通過cmd調用less 或 uglifyjs進行處理文件代碼,接入進來很快的。
測試啦:win7環境
測試打開新頁面速度:
比以前慢5、6倍
測試壓縮一個23k js:
調用tool.css-js.com/compressor.html
介面大概要270毫秒
後臺代碼壓縮需要580毫秒
測試後臺代碼執行uglifyjs -V
:需要350多毫秒
測試後臺代碼執行echo 123
:需要0毫秒
測試分析:
實際壓縮混淆速度580-350=230毫秒,和第三方介面出入不大。
cmd調用速度0毫秒也可以忽略。
那就是啟動uglifyjs而外占用了350毫秒,猜了一下,每次啟動壓縮混淆都會重新啟動node,然後初始化uglifyjs,所以導致巨慢,大文件還好,小文件就不得了,調用第三方介面40毫秒搞定的時,後臺代碼至少要400毫秒起步。從而導致了頁面打開速度變慢很多倍。
基本上頁面上的script和style都是小的片段,這個速度不能接受。
優化
雖然已經能夠實現壓縮混淆了,但是壓縮必須經過啟動速度巨慢這個問題不能接受。
既然是node和模塊啟動的問題導致的,那麼將所有的壓縮混淆共用一次啟動過程不就解決了?是這樣的。
怎麼共用?用cmd肯定複雜了,直接上node,啟動和初始化所有模塊後等著命令的輸入,然後進行壓縮混淆,然後繼續接受命令,往複迴圈。
如此方式用http server最合適不過了,啟動和初始化所有模塊,等待http請求,一有請求就馬上處理並返回結果。
上code:
package.json裡面的模塊依賴:
{
"name": "node_server",
"version": "1.0.0",
"main": "server.js",
"dependencies": {
"uglify-js": "3.3.16",
"less": "2.7.3",
"less-plugin-clean-css": "1.5.1"
}
}
server.js node程式啟動代碼,特意只監聽127.0.0.1省的配置防火牆
var http = require('http');
var querystring = require('querystring');
var UglifyJS = require("uglify-js");
var less = require('less');
var cleanCss = require("less-plugin-clean-css");
http.createServer(function (req, rep) {
var ctx={c:0,m:"",v:""};
var post = '';
req.on('data', function(chunk){
post += chunk;
});
req.on('end', function(){
(async function(){
try{
var params = querystring.parse(post);
var path0=(/^\/([^\/]+)/.exec(req.url)||[])[1]||"";
if(path0=="test"){
ctx.v="test";
}else if(path0=="buildcss"){
ctx.v=await BuildCss(params);
}else if(path0=="buildjs"){
ctx.v=await BuildJs(params);
};
}catch(e){
ctx.c=1;
ctx.m="執行出錯:"+e.stack;
};
try{
var sendData=JSON.stringify(ctx);
}catch(e){
ctx={c:1,m:"返回數據失敗:"+e.stack};
sendData=JSON.stringify(ctx);
}
rep.writeHead(200, {'Content-Type': 'text/json; charset=utf-8'});
rep.end(sendData);
})();
});
}).listen(8004,"127.0.0.1");
function BuildCss(params){
return new Promise(function (resolve, reject) {
less.render(params.code||"", { plugins: [new cleanCss({advanced: true})] })
.then(function(output) {
resolve(output.css);
},function(e) {
reject(new Error(e.message));
});
});
};
function BuildJs(params){
return new Promise(function (resolve, reject) {
var res=UglifyJS.minify(params.code||"");
if(res.error){
reject(res.error);
}else{
resolve(res.code);
};
});
};
提供介面地址:
http://127.0.0.1:8004/test
程式運行狀態測試
http://127.0.0.1:8004/buildcss
post
code=css代碼
編譯css
http://127.0.0.1:8004/buildjs
post
code=js代碼
編譯js
介面返回結果
{c:0,m"錯誤消息",v:"沒有錯誤時返回的結果"}
,c為狀態碼,如果出錯c!=0,並提供錯誤消息,沒有錯誤時v有值。
如何運行
沒有怎麼用node和npm,經驗不足,不過還是能跑起來:
- 安裝node
- 安裝cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
npm太慢了 - 文件夾內新建package.json,把代碼copy進去
- 文件夾內新建server.js,把代碼copy進去
- 文件夾這個目錄上下文內執行cmd命令
cnpm install
,自動下載依賴模塊 npm start
啟動- 瀏覽器內輸入
http://127.0.0.1:8004/test
測試運行狀態
最終
再次測試壓縮一個23k js:
調用tool.css-js.com/compressor.html
介面大概要270毫秒
後臺代碼壓縮需要140毫秒
比第三介面還要快,估計是新版本的原因吧,(不要看網速影響,最多影響10ms就不錯了)