背景介紹
前面在基於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 %~dp0\NotePBL-app
start call build.bat
cd /D %~dp0\NotePBL-biz
start call build.bat
cd /D %~dp0\NotePBL-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
檔案下把不要的註釋掉就好了。
最後
樓下是之前寫的兩篇,和今天這篇構成三姊妹篇,嗯。
- 基於bat指令碼的前端釋出流程設計與實現: https://www.yuque.com/ataola/blog/nul1i4
- 使用Shell指令碼優化Linux伺服器上部署流程: https://www.yuque.com/ataola/blog/ece4x8