背景介紹
前面在基于bat腳本的前端發布流程設計與實現中,我已經介紹了設計與實現,這一篇主要是針對其的一個優化折騰(分兩步走,第一步先搞出來,第二步再想著怎么去優化它),我主要做了以下幾件事。
- "各個擊破" ------ 更細粒度地拆分構建、打包、上傳模塊,邏輯更清晰,維護更簡便,程序更魯棒
- "條條大路通杭州" ------ 更改了壓縮zip的實現邏輯(npm pkg - archiver)
- "打掃干凈屋子再請客" ----- 追加了清理之前的文件的邏輯
- "雞蛋放一個籃子里" ------ 把生成的文件移到根目錄,更加直觀了
- "火影分身術" ------ 支持多進程打包,可以并行搞多個子項目
- "一網打盡" ------ 抽離了上傳的邏輯放最后一把梭哈
下面我以一個項目為例,著重向大家介紹我是怎么一步步折騰的。
archiver包實現文件打包
這里你問我為什么之前已經實現了bat腳本結合vbs腳本的文件壓縮,還要再搞一套?我也很難回答你為什么,就是玩哇,學編程搞技術愛折騰唄,我是個jser,同時也是個tser,想到用npm構建也合情合理。
我這里主要是用到了一個庫叫archiver,它的官網是
https://www.archiverjs.com/,代碼的一些細節我已經寫了注釋了,這里就不過多介紹,我大致的思路是,在文件構建完以后,定義下要打包的目錄,然后按照${項目名}-dist-${時間}.zip的格式打包,這里需要注意的是,當月份小于10的時候它下面代碼輸出的是M而不是MM,這個本身是做一個標識,要抹平這部分差異無非也就是多寫幾句話,我在這件事情上沒有強迫癥,所有我就沒抹平。
const fs = require('fs')
const path = require('path')
const archiver = require('archiver')
// 項目的文件目錄
const baseDir = path.join(__dirname, '../')
// 格式化當前時間,這里需要注意如果月份小于10的話是M而不是MM輸出,僅做個發版標記,那就沒必要強迫癥對齊YYYY-MM-DD hh:mm:ss
const [foo, bar] = new Date().toLocaleString().split(' ')
const time = `${foo.replaceAll('/', '')}${bar.replaceAll(':', '')}`
// 這里用數組,是因為如果你還想打包其他的文件目錄或者文件,就放到這個數組里
const target = ['dist']
// 打包輸出*-dist-*.zip
const output = fs.createWriteStream(`${baseDir}/App-dist-${time}.zip`)
const archive = archiver('zip', {
zlib: { level: 9 }
})
// 打包錯誤處理
archive.on('error', (err) => {
throw err
})
// 完結撒花,輸出文件路徑,文件大小
output.on('close', () => {
console.log(`生成打包文件成功,大小為${(archive.pointer() / 1024 / 1024).toFixed(1)}MB,系統路徑在 ${baseDir}app-dist-${time}.zip`)
})
archive.pipe(output)
// eslint-disable-next-line no-restricted-syntax
for (const item of target) {
archive.directory(item, item)
}
archive.finalize()
值得一提的是,之前我們都是打包到對應的子目錄,這樣子我還要翻幾下去看,給它優化掉去吧,直接打包完放根目錄
關于構建腳本粒度細化這件事
軟件工程上面說,你要做好一個東西,不能寫的一坨漿糊一樣,應該考慮每個模塊它干了什么,模塊的職責應該是單一的,同時維護起來也應該是簡單的,從這些方面考慮,我們重構之前寫的腳本,分三步哈,先清理 ——> 再構建完打包 ——> 再上傳, 流程是這樣子的。
先清理
上次忘記說清理這件事了,為什么我上次會忘呢?這里我還要謝謝git,它打包完后傳到linux服務器,不是可以通過discard change這個魔法讓打包后的文件消失嘛,所以我之前就是通過這么干的。
那我們來實現下刪除打包后的*.zip文件,其實也很簡單
cd %~dp0
del /a/f/q "*.zip"
如果說你想層級遞歸 /s加一下就可以了。
再構建完打包
在子項目中
構建沒什么好說的,大部分項目npm run build一把梭。
打包這里我們分兩步走,在子文件的package.json里面貼入如下內容:
...
"scripts": {
"zip": "node zip.js",
"build:zip": "npm run build && npm run zip"
}
...
然后新建一個build.bat, 內容如下:
call npm run build:zip
exit
這里call表示,等樓上的npm命令執行完再往下走,就會走到exit那里,這里這么寫為了更好地利用cpu來處理,有可能你有很多個項目,但一個時間段就開一個進程去構建,顯然是有點委屈了我那8核的CPU,這么搞以后,在父項目下執行構建就可以同時構建多個項目了,構建完自動退出,這不就是小時候看的動畫片中的影分身嘛。
在父項目中的build.bat腳本如下
cd /D %~dp0NotePBL-app
start call build.bat
cd /D %~dp0NotePBL-biz
start call build.bat
cd /D %~dp0NotePBL-fin
start call build.bat
再上傳
上傳這里,為了避免每次輸入密碼,我建議你參考我之前寫的第一篇,配到ssh里面,然后就很簡單了,需要用到哪個包就傳哪個,
cd %~dp0
scp app-*.zip root@這里填對應服務器的地址:這里填寫對應服務器的路徑
scp biz-*.zip root@這里填對應服務器的地址:這里填寫對應服務器的路徑
scp fin-*.zip root@這里填對應服務器的地址:這里填寫對應服務器的路徑
最后整合的deploy.bat就是這樣啦
@echo off
setlocal enabledelayedexpansion
@REM 中電惠融項目構建腳本,Zheng JiangTao(admin@qq.com)
chcp 65001
cls
cd /D %~dp0
echo ==========(∩•?ω•?)⊃-*?中電惠融項目構建腳本?*-⊂(•?ω•?∩)==========
:start
cd %~dp0
call clean.bat
cd /D %~dp0
start /wait call build.bat
cd /D %~dp0
start /wait call upload.bat
echo ========*:??(?´?`)??:*中電惠融項目構建腳本*:??(?´?`)??:*========
:finish
exit /b
這次不是自動擋的車,帶了點手動擋,除了把模塊拆分之外,也給與相關開發手動發車的感覺,嗯。
FAQ
如果項目就單純的一個,沒有這么多子項目有什么好的建議嗎?
那我建議你直接npm一把梭,具體是這樣子的。
有個npm包叫rimraf ,地址是
https://www.npmjs.com/package/rimraf,可以實現刪除文件,安裝一下把package.json構建腳本改下
...
"scripts": {
"clean": "rimraf app-dist-*.zip",
"zip": "node zip.js",
"build:cz": "npm run build && npm run clean && npm run zip",
}
...
如果多個項目,只改了其中一兩個子項目有什么好的建議嗎?
這就是我上面說的手動擋留的口子,在對應的build.bat文件和upload.bat文件下把不要的注釋掉就好了。