後端自動構建前端css和js

来源:https://www.cnblogs.com/xiangyuecn/archive/2018/03/29/8667389.html
-Advertisement-
Play Games

引子: 別的複雜前端開發技術不會,用得多的還是手寫代碼,手動處理。 3年前手寫合併壓縮js和css文件的asp腳本代碼目前還能正常運行,也就沒有多大使用別的技術的動力。 直到近期被一個問題糾結著,今天花了一天時間摸索完成了一個後端構建功能。 目前接觸到的項目前端開發模式基本上是一樣的 1. 項目不會 ...


service.js

引子:

別的複雜前端開發技術不會,用得多的還是手寫代碼,手動處理。

3年前手寫合併壓縮js和css文件的asp腳本代碼目前還能正常運行,也就沒有多大使用別的技術的動力。

直到近期被一個問題糾結著,今天花了一天時間摸索完成了一個後端構建功能。

目前接觸到的項目前端開發模式基本上是一樣的

  1. 項目不會很大
  2. 通用css、js、第三方庫會獨立成單個文件
  3. 頁面依賴的多個文件會合併成一個css或js文件,併進行自定義語法編譯和壓縮混淆
  4. 多個頁面會用到的但不夠通用的會獨立成一個html文件,內嵌style、script標簽,伺服器端後端運行時包含進來
  5. 頁面使用的js、css完全內嵌style、script標簽(無法抗拒的優點:打開一個文件就能看到所有源代碼)
  6. 曉得這種模式很low,不過好用

瞭解到的前端構建方式

針對2、3項,跟目前看到的前端自動化構建工具,比如:webpack、gulp,其實處理思想上還是比較吻合,壓縮混淆實現是調用的一個壓縮js和css網站的介面tool.css-js.com/compressor.html

針對4、5項這種內嵌的style和script,以前是沒有任何處理,一個月前特意加上了壓縮混淆功能。實現方式是開發階段完成相關文件的壓縮混淆:壓縮混淆是只要頁面一運行,相關前端代碼後端會自動化處理;然後手動上傳結果到伺服器。如果源碼有改動,必須重新壓縮混淆和上傳文件(自己寫的後臺工具是這樣的規則)。

最近就是被如果源碼有改動,必須重新壓縮混淆和上傳文件這個問題困擾著,一個是操作複雜,致命的是:如果漏上傳了混淆後的文件。。。

好,現在知道目前採用的壓縮混淆方式了:編寫前端代碼,後端代碼自動處理生成新的壓縮混淆後的代碼。

前奏

既然後端已經有壓縮混淆功能了,那麼還要這麼複雜的操作流程就多餘了。為什麼不扔到伺服器上自動處理?是考慮到第三方網站介面的穩定性,如果他們掛了,至少不影響線上功能(他們確實經常掛)。

問題出在第三方壓縮混淆介面上,那把功能本地化不就穩定了,沒毛病是這個邏輯。

昨天想了一下,如果要本地實現壓縮混淆css和js,涉及的代碼有點多,就放棄了。

今天上午又想了一下,如果不提前搞好,光生成出來的文件就一大堆,而且本質是次要的生成文件,提交svn的時候還要特殊對待,不提交又會導致新檢出項目可能丟失文件,提交的話又算是垃圾文件。還要上傳,如果是差異更新就有的對比了。必須動手了。

進行時

要壓縮css,有很多辦法:正則替換空白,不過複雜css格式去掉空白後語義是不是一致就難說了;用現成的工具,甚至可以帶來更好的開發方式的lesssass,最終採用了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,經驗不足,不過還是能跑起來:

  1. 安裝node
  2. 安裝cnpm npm install -g cnpm --registry=https://registry.npm.taobao.org npm太慢了
  3. 文件夾內新建package.json,把代碼copy進去
  4. 文件夾內新建server.js,把代碼copy進去
  5. 文件夾這個目錄上下文內執行cmd命令cnpm install,自動下載依賴模塊
  6. npm start 啟動
  7. 瀏覽器內輸入http://127.0.0.1:8004/test 測試運行狀態

已經install過的,啟動正常

服務已經在運行

最終

再次測試壓縮一個23k js:
調用tool.css-js.com/compressor.html介面大概要270毫秒
後臺代碼壓縮需要140毫秒

比第三介面還要快,估計是新版本的原因吧,(不要看網速影響,最多影響10ms就不錯了)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 入駐博客園兩個月今天第一次發隨筆,,話不多說,直接上圖展示效果 主界面用的RecyclerView的瀑布流(StaggeredGridLayoutManager),同時加上Floatbutton懸浮按鈕 此頁面是添加內容的頁面,圖中橫線框是重寫了EditText控制項達到的效果,挺簡陋的。。。 這裡集 ...
  • 為了對抗微信小程式,安卓手機廠商聯合起來推出了快應用,這是好事一件,但快應用的實現方式在我看來並不是一個最佳的方案。 ...
  • 1 //將UTCDate(世界標準時間)轉化為當地時區的標準Date(鐘錶顯示的時間) 2 //NSDate *date = [NSDate date]; 2018-03-27 06:54:41 +0000 3 //轉化後:2018-03-27 14:54:41 +0000 4 -(NSDate *... ...
  • 合成兩張圖片,上下疊加的效果: ...
  • 同步執行 + 主隊列 同步執行 + 主隊列在不同線程中調用結果也是不一樣,在主線程中調用會出現死鎖,而在其他線程中則不會。 在主線程中調用同步執行 + 主隊列 互相等待卡住不可行 1 - (void)syncMain { 2 3 NSLog(@"currentThread %@",[NSThread ...
  • 轉自:https://blog.csdn.net/murphykwu/article/details/52457667 selinux的概念如上一篇鏈接所示: http://www.cnblogs.com/linhaostudy/p/8659662.html 一、SELinux資源訪問基本概念 SE ...
  • 首先,確保手機打開了USB調試。如果還是出現檢測不到WebView頁面,主要有一下幾種情況。 反應慢,稍等一會 華為手機,請安裝華為手機助手,插上手機後會提示安裝的。不安裝的話,會出現不穩定的情況 要調試的APP沒有打開WebView的調試模式。會出現有的App能Inspect,有的不能。可參考Co ...
  • iOS平臺是按照一直有網路連接的思路來設計的,開發者利用這一特點創造了很多優秀的第三方應用。大多數的iOS應用都需要聯網,甚至有些應用嚴重依賴網路,沒有網路就無法正常工作。 "在訪問網路失敗的時候 ,應用沒有做出適當的提示“是蘋果的iOS審核團隊拒絕一個應用的常見理由。蘋果要求你必須先檢測網路連接狀 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...