目前項目一套代碼會打包多個版本,進入測試階段經常一個bug就要部署多套代碼。為了節約時間(當然不可能是bug太多啦),寫了一個自動批量打包部署的js腳本。
一、批量打包
- 通過node-cmd 批量執行打包命令 npm run build --client=${buildName} 不需要再去手動輸入啦
const cmd = require("node-cmd");//通過js代碼執行cmd命令的插件
const systemConfig = require("./client/config.json");//打包不同環境的配置
var deploy = require("./client/deploy-server");//自動部署邏輯
var args = require("node-args");//拿到命令行參數
// 獲取所有系統名字集合
let systemName = Object.keys(systemConfig);//本次打包對應的環境參數
// 獲取命令行參數 1234順序對應系統名字
let buildArr = "";
try {
buildArr = args.s.toString().split("");//用數組表示批量部署時每次的環境參數
console.log(
`begin run build
預計打包時間${buildArr.length * 25}s`
);
} catch (e) {
console.log("缺少必填參數,例如 node runbuild.js --s=1234 -d=true");
//這里的1234分別代表四個環境的代碼
return;
}
//用foreach 執行批量部署每次部署的任務
buildArr.forEach((item, i, arr) => {
let buildName = systemName[item - 1];
console.log(`
--------------------------begin build ${buildName}--------------------------------`);
let { err, data, stderr } = cmd.runSync(
`npm run build --client=${buildName}`
);
console.log(`
Sync Err ${err}
Sync stderr: ${stderr}
Sync Data ${data}
`);
if (!err) {
console.log(
`===============${buildName}打包完成=============================`
);
} else {
return;
}
//計數,等待全部打包完成,才開始部署
if (i === arr.length - 1 && args.d) {
console.log(`==============開始部署=============================、
${arr}
`);
deploy.conn(arr);
}
});
二、 自動壓縮
- 用到了webpack的插件,每次webpack打包會自動執行這個插件
- 如果本地運行也是用的同一個配置文件,需要檢查是否是生產的打包(如下),因為這個插件會拖慢本地項目響應的時間。
- 打包之后的文件操作是在這里配置的,基本邏輯是:將根目錄下打包完成的dist文件壓縮成zip、重命名並且存到根目錄的zip目錄中(等待部署),
const FileManagerPlugin = require("filemanager-webpack-plugin");
configureWebpack: {
plugins:
process.env.NODE_ENV === "production"
? [
new FileManagerPlugin({
events: {
onEnd: {
delete: [`./zip/${siteName}.zip`],
archive: [
{
source: path.join(__dirname, "./dist"),
destination: path.join(
__dirname,
`./zip/${siteName}.zip`
),
},
],
},
},
}),
]
: [],
},
三、自動部署
// 打包完成之后部署服務器
const Client = require("ssh2").Client;
var basename = require("path").basename;
//服務器的配置
const server = {
host: "172.18.10.114", // 服務器地址
port: "22", // 端口號
username: "root", // 用戶名
password: "123456", // 密碼
readyTimeout: 50000,
};
const connect = new Client();
const systemConfig = require("./config.json");
let systemName = Object.keys(systemConfig);
var fun = {
buildArr: null,
// 連接服務器
conn: function (buildArr = [1]) {
this.buildArr = buildArr;
connect
.on("ready", () => {
console.log("*******連接服務器*******");
this.upload();
})
.on("error", (err) => {
console.error(err);
console.log("*******連接出錯*******");
})
.on("end", () => {
console.log("*******連接關閉*******");
})
.on("close", (err) => {
if (err) {
console.log("*******連接出錯*******");
}
})
.connect(server);
},
upload: function () {
//用到了ssh2中的sftp 模塊
connect.sftp((err, sftp) => {
if (err) {
console.log("sftp模塊啟動失敗");
throw err;
}
console.log("sftp模塊啟動成功,開始批量上傳文件");
let sucCount = 0;
let buildArrLen = this.buildArr.length;
this.buildArr.forEach((index) => {
let buildName = systemName[index - 1];
let remoteDir = `服務器前端部署路徑-${buildName}/`;
let localDir = `./zip/${buildName}.zip`;
console.log(`*******${buildName}.zip 開始上傳*******`);
sftp.fastPut(
localDir,
`${remoteDir}${basename(localDir)}`,
{},
(err, res) => {
if (err) {
console.log(err);
console.error("*******上傳失敗*******");
connect.end();
return;
}
sucCount++;
// 上傳zip文件成功后
console.log(`*******${buildName}.zip上傳成功*******`);
if (sucCount === buildArrLen) {
// 全部壓縮包成功上傳
console.log(`*******壓縮包上傳已完成,結束此次任務*******`);
process.exit();
}
}
);
});
});
},
};
module.exports = fun;
只需要手動輸入 node runbuild.js --s=1234 -d=true 一條命令即可,這里的1234分別代表四個環境的代碼 -d=true 代表需要自動部署
后面還可以優化:sftp模塊支持傳命令到服務器,不用去服務器操作文件了,真正實現了全自動部署哈哈。