代码自动化打包系统【原创】
一、?需求背景
XX項目需要開發一套前端組件打包系統,來處理用戶的請求:
1.???????用戶通過平臺申請應用;
2.???????選擇所需要的組件;
3.???????把組件的相關前端文件如js、css、html進行抽取、合并、壓縮、打包;
4.???????把壓縮包鏈接地址返回給用戶,用戶下載壓縮包。
針對上面的需求,我們選擇一個比較流行的前端代碼打包工具grunt。
二、?grunt簡介
什么是grunt?
官網給它的解釋是The JavaScript Task Runner。Grunt是基于Node.js的項目構建工具,可以對項目文件壓縮、編譯、單元測試等任務通過Gruntfile配置用grunt命令自動執行,節省大部分無聊的工作和時間。
為什么選grunt?
因為grunt有豐富的插件,能滿足打包所需要的合并、壓縮、打zip包等功能。
三、?系統運行環境
打包系統的運行需要下面的環境提供支持,在開發前需要對其一一安裝。
Node:Javascript運行環境(runtime)。實際上它是對Google V8引擎進行了封裝
npm:全稱Node Package Manager,是一個NodeJS包管理和分發工具
pm2:帶有負載均衡功能的Node應用的進程管理器
Dnode:實現php與node之間的通信,提供雙向遠程方法調用類庫
Grunt及其插件:grunt-contrib-clean,grunt-contrib-concat,grunt-contrib-copy,grunt-contrib-cssmin,grunt-contrib-less,grunt-contrib-uglify,grunt-contrib-watch,grunt-zip,load-grunt-tasks,gurnt依靠這些插件完成了代碼的合并、壓縮、打zip包等功能
四、?打包系統實現
先看一下流程圖
上圖的流程是經過無數次修改后的方案,期間遇到很多問題,主要集中在php和grunt之間的調用和參數傳遞上。需要解決的問題:
1.???????怎樣從源代碼文件中根據所選擇的組件來抽取對應的文件;
2.???????怎樣用php程序調用grunt命令
3.???????dnode可以作為php調用grunt命令的橋梁,php怎樣同步調用grunt命令
1.???????Gruntfile文件使用
用戶首先要選擇組件進行下載壓縮包,通過grunt命令給Gruntfile傳遞需要打包的組件列表,Gruntfile包含grunt的全部處理邏輯。
加載grunt插件
加載所需要的插件,寫在package.json文件里:
"devDependencies": {"grunt": "~0.4.0","grunt-contrib-clean": "^0.6.0", "grunt-contrib-concat": "^0.1.3", "grunt-contrib-copy": "^0.4.0", "grunt-contrib-cssmin": "^0.6.1", "grunt-contrib-uglify": "^0.9.1", "grunt-contrib-watch": "^0.3.1", "grunt-contrib-less": "^1.0.0", "load-grunt-tasks": "^3.2.0", "time-grunt": "^1.2.1", "grunt-zip": "^0.16.2" }源文件配置文件:
下面是loading組件的配置文件,html和一些通用js,css (less)?直接寫在GruntFile文件內
{"app": "loading","less": ["src/app/loading/loading.less"],"js": ["src/vendor/common/pxloader.js", "src/app/loading/loading.js"] }Gruntfile參數接收:
var appArr = grunt.option('app').split(',');?(app為組件參數字符串,是組件名稱組合,名稱之間用逗號分隔)例如:’register,login,slider’。
Gruntfile根據獲取的組件列表讀取組件配置文件。
for (var i in appArr) {var confName = 'grunt_conf/' + appArr[i] + '.json'; confArr[i] = grunt.file.readJSON(confName); };Gruntfile根據參數app獲取組件名稱,然后又根據組件名稱獲取組件配置文件,通過配置文件,可以獲取源文件的文件列表,然后對這些組件的源文件進行組合、合并、壓縮,最后生成壓縮包
2.???????php調用grunt
由于生產環境php.ini的disable_functions把exec、shell_exec、system這樣可以執行linux命令的函數禁用,但是Node可以調用,DNode可以實現php和Node之間的通信。這樣我們就可以實現php程序調用grunt命令。
Node打包Server
var PORT = 7083; var dnode = require('dnode'); var cp = require('child_process'); var server = dnode({ pack: function (params, callback) { var ls = cp.exec("grunt --app=" + params.coms, [], function(error, stdout, stderr){ if(error != null || stdout.indexOf('without errors') < 0){ callback('error'); }else{ callback('success'); } }); } }); server.listen(PORT);?
Php同步調用
為什么同步調用而不是異步?因為打包后要對壓縮包上傳,上傳前必須保證壓縮包存在,所以我們使用了回調函數,并且可以根據回調函數的返回值判斷打包是否正常,同時也保證下一步上傳的正常進行。
/*** 源文件打包* @param string $components* @param string $path* @param string $fileName* @throws \H5EException */ private static function sourcePack($components){ $loop = new \React\EventLoop\StreamSelectLoop(); $dnode = new \DNode\DNode($loop); $port = 7083; self::$params = array('coms' => $components); $dnode->connect($port, function($remote, $connection) { $remote->pack(PackService::$params, function ($ret) use ($connection){ if ("success" != $ret) { throw new \H5EException("pack service error", Constants::SYSTEM_CODE); } $connection->end(); }); }); $loop->run(); }?
3.???????維持Node打包server的持續運行
node啟動打包server進程,一段時間后會莫名其妙的掛掉,pm2作為node的守護進程很好的解決了這個問題。
4.???????壓縮包上傳
壓縮包是根據版本來規劃的,當版本改變后,用戶下載壓縮包就需要重新打包,但是同一版本的源文件沒必要重新打壓縮包,所以我們把壓縮包上傳資源服務器上,然后把資源鏈接保存在數據庫中,下一次只需從數據庫中查詢到該鏈接即可,而無須重復打包,這樣既提高了用戶下載的速度,又節省了服務器資源。
五、?后期改進
增加Node日志,目前缺少node日志,如果出現異常,很難定位的問題;
Node打包server接收參數時進行嚴格校驗;
六、 安全問題思考
A.?控制訪問頻率,和普通數據接口相比,打包接口耗時較長,消耗服務器資源較多,如果出現接口被惡意頻繁請求,可能會影響服務器性能,同時造成正常的打包失敗,有必要對訪問頻率做限制;
B.?在php層和node層都要進行嚴格校驗參數,可以有效的防止因參數問題而帶來的意外;
C.?Node?代碼打包server運行的端口不能對外,阻止用戶通過外網直接訪問該端口。
轉載于:https://www.cnblogs.com/Felixdh/p/4986830.html
總結
以上是生活随笔為你收集整理的代码自动化打包系统【原创】的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Exception raised dur
- 下一篇: 巅峰坦克vap6奖励什么
