永恆的前言
簡單實用的前端部署, 一條命令搞定, 省去繁瑣的步驟!
主要是** nodejs shelljs(命令列命令) node-ssh(連線伺服器)**
(這個git專案是我自己搭的一個比較low的vue腳手架,整合ts)
(第一次寫文章, 文筆不行, 多多包涵,有不對的地方儘管指出)
(主要看 自動部署 在 upload 目錄 )
如何在你專案中使用( 五步曲 )
第一步, 把專案裡 upload 資料夾複製到你專案根目錄
第二步, 下載該js相關依賴
npm 或 cnpm i chalk ora shelljs node-ssh inquirer compressing -D
第三步, 開啟 upload/config.js 配置檔案, 配置ssh地址, 使用者名稱, 驗證方式,需要上傳的目錄
第四步, 在你專案中 package.json 檔案中 加上 "deploy": "node ./upload/upload.js"
最後 在命令列輸入 npm run deploy 選擇釋出環境 然後就ojbk了
大功告成~~
來看主要檔案 upload.js
專案依賴
const chalk = require('chalk') //命令列顏色
const ora = require('ora') // 載入流程動畫
const spinner_style = require('./spinner_style') //載入動畫樣式
const shell = require('shelljs') // 執行shell命令
const node_ssh = require('node-ssh') // ssh連線伺服器
const inquirer = require('inquirer') //命令列互動
const zipFile = require('compressing')// 壓縮zip
const fs = require('fs') // nodejs內建檔案模組
const path = require('path') // nodejs內建路徑模組
const CONFIG = require('./config') // 配置
複製程式碼
一些常量,變數和logs
const SSH = new node_ssh();
let config; // 用於儲存 inquirer 命令列互動後選擇正式|測試版的配置
//logs
const defaultLog = log => console.log(chalk.blue(`---------------- ${log} ----------------`));
const errorLog = log => console.log(chalk.red(`---------------- ${log} ----------------`));
const successLog = log => console.log(chalk.green(`---------------- ${log} ----------------`));
//資料夾目錄
const distDir = path.resolve(__dirname, '../dist'); //待打包
const distZipPath = path.resolve(__dirname, `../dist.zip`);
//打包後地址(dist.zip是檔名,不需要更改, 主要在config中配置 PATH 即可)
複製程式碼
打包
首先 執行專案打包命令
//專案打包程式碼 npm run build
const compileDist = async () => {
const loading = ora( defaultLog('專案開始打包') ).start();
loading.spinner = spinner_style.arrow4;
shell.cd(path.resolve(__dirname, '../'));
const res = await shell.exec('npm run build'); //執行shell 打包命令
loading.stop();
if(res.code === 0) {
successLog('專案打包成功!');
} else {
errorLog('專案打包失敗, 請重試!');
process.exit(); //退出流程
}
}
複製程式碼
壓縮
然後 對打包的程式碼 /dist 目錄打包 (如果不是dist, 請更改上面的 disDir 常量結尾的dist)
//壓縮程式碼
const zipDist = async ()=>{
defaultLog('專案開始壓縮');
try {
await zipFile.zip.compressDir(distDir, distZipPath)
successLog('壓縮成功!');
} catch (error) {
errorLog(error);
errorLog('壓縮失敗, 退出程式!');
process.exit(); //退出流程
}
}
複製程式碼
連線伺服器
再然後 通過ssh連線伺服器 有兩種方式: 一是通過祕鑰連線(推薦), 二是密碼連線 祕鑰連線需要把本機公鑰放伺服器指定目錄 (在upload/config.js 有說明)
//連線伺服器
const connectSSH = async ()=>{
const loading = ora( defaultLog('正在連線伺服器') ).start();
loading.spinner = spinner_style.arrow4;
try {
await SSH.connect({
host: config.SERVER_PATH,
username: config.SSH_USER,
// privateKey: config.PRIVATE_KEY, //祕鑰登入(推薦) 方式一
password: config.PASSWORD // 密碼登入 方式二
});
successLog('SSH連線成功!');
} catch (error) {
errorLog(error);
errorLog('SSH連線失敗!');
process.exit(); //退出流程
}
loading.stop();
}
複製程式碼
上傳檔案
緊接著 通過ssh執行線上命令 進行目標目錄清空, 然後上傳zip到伺服器 並解壓 等操作
//線上執行命令
/**
*
* @param {String} command 命令操作 如 ls
*/
const runCommand = async (command)=> {
const result = await SSH.exec(command, [], { cwd: config.PATH})
// defaultLog(result);
}
//清空線上目標目錄裡的舊檔案
const clearOldFile = async () =>{
const commands = ['ls', 'rm -rf *'];
await Promise.all(commands.map(async (it)=>{
return await runCommand(it);
}));
}
//傳送zip檔案到伺服器
const uploadZipBySSH = async () =>{
//連線ssh
await connectSSH();
//線上目標檔案清空
await clearOldFile();
const loading = ora( defaultLog('準備上傳檔案') ).start();
loading.spinner = spinner_style.arrow4;
try {
await SSH.putFiles([{ local: distZipPath, remote: config.PATH + '/dist.zip' }]); //local 本地 ; remote 伺服器 ;
successLog('上傳成功!');
loading.text = '正在解壓檔案';
await runCommand('unzip ./dist.zip'); //解壓
await runCommand(`rm -rf ${config.PATH}/dist.zip`); //解壓完刪除線上壓縮包
//將目標目錄的dist裡面檔案移出到目標檔案
//舉個例子 假如我們部署在 /test/html 這個目錄下 只有一個網站, 那麼上傳解壓後的檔案在 /test/html/dist 裡
//需要將 dist 目錄下的檔案 移出到 /test/html ; 多網站情況, 如 /test/html/h5 或者 /test/html/admin 都和上面同樣道理
await runCommand(`mv -f ${config.PATH}/dist/* ${config.PATH}`);
await runCommand(`rm -rf ${config.PATH}/dist`); //移出後刪除 dist 資料夾
SSH.dispose(); //斷開連線
} catch (error) {
errorLog(error);
errorLog('上傳失敗!');
process.exit(); //退出流程
}
loading.stop();
}
複製程式碼
整合
把這些整合在一個函式
//------------釋出程式---------------
const runUploadTask = async () => {
console.log(chalk.yellow(`---------> 歡迎使用 波哥牌 2020年自動部署工具 <---------`));
//打包
await compileDist();
//壓縮
await zipDist();
//連線伺服器上傳檔案
await uploadZipBySSH();
successLog('大吉大利, 部署成功!');
process.exit();
}
複製程式碼
釋出前的檢查配置
// 開始前的配置檢查
/**
*
* @param {Object} conf 配置物件
*/
const checkConfig = (conf) =>{
const checkArr = Object.entries(conf);
checkArr.map(it=>{
const key = it[0];
if(key === 'PATH' && conf[key] === '/') { //上傳zip前會清空目標目錄內所有檔案
errorLog('PATH 不能是伺服器根目錄!');
process.exit(); //退出流程
}
if(!conf[key]) {
errorLog(`配置項 ${key} 不能為空`);
process.exit(); //退出流程
}
})
}
複製程式碼
釋出
執行互動 選擇釋出環境 然後啟動釋出程式
// 執行互動後 啟動釋出程式
inquirer
.prompt([{
type: 'list',
message: '請選擇釋出環境',
name: 'env',
choices: [{
name: '測試環境',
value: 'development'
},{
name: '正式環境',
value: 'production'
}]
}])
.then(answers => {
config = CONFIG[answers.env];
checkConfig(config); // 檢查
runUploadTask(); // 釋出
});
複製程式碼
大功告成
結尾
咳咳, 放心, 不會有公眾號啥廣告, 也不會求打賞, 如果您覺得對您有一點點幫助 點個贊或者去GitHub點個star 那就非常感謝了 專案git 地址