-
第一種方式: gulp 打包後的檔案上傳至伺服器
下載下傳:
package.json:npm install -D gulp-sftp-up4 gulp-ssh
"scripts": { "server-dev": "cross-env NODE_ENV=dev gulp default },
const { task, src, series } = require('gulp'); const sftp = require('gulp-sftp-up4'); const devConfig = { host: '119.23.**.***', port: 888, user: 'root', pass: '****', remotePath: '/usr/local/nginx/html/test' } const testConfig = { host: '47.106.***.***', port: 888, user: 'root', pass: '****', remotePath: '/usr/local/nginx/html/webapps/test' } const gulpConfig = process.env.NODE_ENV === 'dev' ? devConfig : testConfig task('upload', function (done) { return src('./build/**') .pipe(sftp(gulpConfig)); }) task('default', series('upload'));
-
第二種方式: node 打包
打包、壓縮、删除源代碼、上傳 一條龍。
效果:
前端指令上傳伺服器
1、commander : 在執行的時候增加參數,判斷環境
const { program } = require('commander');
program
.option('-c, --cheese <type>', 'add the specified type of cheese', 'blue'); // 預設值 blue
program.parse(process.argv);
console.log(`cheese: ${program.cheese}`);
終端執行node:
--cheese
得到結果: cheese: blue
--cheese green
得到結果: cheese: green
2、ora:處理終端轉輪狀态
成功、失敗、運作中等狀态
ora 優雅的終端轉輪
const ora = require('ora')
ora().fail('請配置部署環境')
如圖顯示:
3、inquirer:使用者與指令行互動
詢問是否進行環境的部署:
const inquirer = require('inquirer')
const answer = await inquirer.prompt([{
type: 'confirm',
message: '是否進行部署?',
name: 'confirm', // 互動的關鍵字,如果有多條資料可以在這邊擷取到
}])
console.log("answer", answer.confirm)
const chalk = require('chalk')
const ora = require('ora')
// 成功資訊
const succeed = (message) => {
ora().succeed(chalk.greenBright.bold(message))
}
// 提示資訊
const info = (message) => {
ora().info(chalk.blueBright.bold(message))
}
// 錯誤資訊
const error = (message) => {
ora().fail(chalk.redBright.bold(message))
}
// 下劃線重點資訊
const underline = (message) => {
return chalk.underline.blueBright.bold(message)
}
// 使用
succeed("成功啦~~~")
error("失敗了- -")
info(`提示 。。。${underline("下劃線* *")}`)
// 執行打包
const childProcess = require('child_process');
const maxBuffer = 5120 * 1024
const ora = require('ora')
function execBuild() {
const spinner = ora('正在打包中...\n')
spinner.start()
return new Promise((resolve, reject) => {
childProcess.exec('yarn build', {
cwd: process.cwd(),
maxBuffer: maxBuffer,
}, (error, stdout, stderr) => {
spinner.stop()
if (error) {
error(`打包出錯: ${error}`)
reject(error)
return;
}
succeed('打包成功')
resolve(stdout)
})
})
}
const { program } = require('commander')
const chalk = require('chalk')
const ora = require('ora')
const inquirer = require('inquirer')
const childProcess = require('child_process')
const fs = require('fs')
const archiver = require('archiver')
const { NodeSSH } = require('node-ssh')
const ssh = new NodeSSH()
const maxBuffer = 5120 * 1024
let taskList = [] // 任務隊列
const config = {
dev: {
host: '119.23.**.***',
port: 888,
username: 'root',
password: '****',
local: 'build',
remote: '/usr/local/nginx/html/test', // 伺服器部署路徑(不可為空或'/')
script: 'yarn build',
},
test: {
host: '47.106.**.***',
port: 888,
username: 'root',
password: '****',
local: 'build',
remote: '/usr/local/nginx/html/test', // 伺服器部署路徑(不可為空或'/')
script: 'yarn build',
}
}
// 成功資訊
const succeed = (message) => {
ora().succeed(chalk.greenBright.bold(message))
}
// 提示資訊
const info = (message) => {
ora().info(chalk.blueBright.bold(message))
}
// 錯誤資訊
const error = (message) => {
ora().fail(chalk.redBright.bold(message))
}
// 下劃線重點資訊
const underline = (message) => {
return chalk.underline.blueBright.bold(message)
}
// 執行打包
async function execBuild(sshConfig, index) {
const spinner = ora('正在打包中...\n')
spinner.start()
const { script } = sshConfig
return new Promise((resolve, reject) => {
childProcess.exec(script, {
cwd: process.cwd(),
maxBuffer: maxBuffer,
}, (error, stdout, stderr) => {
spinner.stop()
if (error) {
error(`打包出錯: ${error}`)
reject(error)
return;
}
succeed(`${index}. 打包成功`)
resolve(stdout)
})
})
}
// 壓縮檔案
async function buildZip(sshConfig, index) {
const { local } = sshConfig
return new Promise((resolve, reject) => {
const output = fs.createWriteStream(`${process.cwd()}/${local}.zip`);
const archive = archiver('zip', {
zlib: { level: 9 } // Sets the compression level.
});
output.on('close', function (e) {
if (e) {
error(`壓縮失敗${e}`)
reject(e)
} else {
succeed(`${index}. 壓縮成功`)
resolve()
}
});
archive.pipe(output);
archive.directory(local, false)
archive.finalize();
})
}
// 連接配接伺服器
async function connectSSH(sshConfig, index) {
try {
await ssh.connect(sshConfig)
succeed(`${index}. ssh連接配接成功`)
} catch (e) {
error('連接配接失敗')
process.exit(1)
}
}
// 上傳檔案
async function putFileRemote(sshConfig, index) {
try {
const { local, remote } = sshConfig
const spinner = ora('正在上傳中...\n')
spinner.start()
await ssh.putFile(`${process.cwd()}/${local}.zip`, `${remote}.zip`, null, { concurrency: 1 })
spinner.stop()
succeed(`${index}. 檔案成功上傳ssh`)
} catch (e) {
console.log(e)
error(`檔案上傳ssh失敗${e}`)
process.exit(1)
}
}
// 删除服務端檔案
async function removeRemoteFile(sshConfig, index) {
try {
const { local, remote } = sshConfig
const spinner = ora('正在删除服務端檔案中...\n')
spinner.start()
await ssh.execCommand(`rm -rf ${remote}/static`)
spinner.stop()
succeed(`${index}. 删除服務端檔案成功`)
} catch (e) {
error(`删除服務端檔案失敗${e}`)
process.exit(1)
}
}
// 解壓服務端檔案
async function unzipRemoteFile(sshConfig, index) {
try {
const { local, remote } = sshConfig
const zipFileName = `${remote}.zip`
const spinner = ora('正在解壓服務端檔案中...\n')
spinner.start()
await ssh.execCommand(`unzip -o ${zipFileName} -d ${remote} && rm -rf ${zipFileName}`)
spinner.stop()
succeed(`${index}. 解壓服務端檔案成功`)
} catch (e) {
error(`解壓服務端檔案失敗${e}`)
process.exit(1)
}
}
// 删除本地檔案
async function removeLocalFile(sshConfig, index) {
try {
const { local } = sshConfig
const localFileName = `${local}.zip`
await fs.unlinkSync(localFileName)
succeed(`${index}. 删除本地檔案成功`)
} catch (e) {
error(`删除本地檔案失敗${e}`)
process.exit(1)
}
}
// 斷開連接配接
async function disconnectSSH(sshConfig, index) {
try {
await ssh.dispose()
succeed(`${index}. 成功斷開連接配接`)
} catch (e) {
error(`斷開連接配接失敗${e}`)
process.exit(1)
}
}
// 任務執行隊列
function handleTaskList() {
taskList.push(execBuild)
taskList.push(buildZip)
taskList.push(connectSSH)
taskList.push(putFileRemote)
taskList.push(removeRemoteFile)
taskList.push(unzipRemoteFile)
taskList.push(removeLocalFile)
taskList.push(disconnectSSH)
}
// 執行任務隊列
async function executeTaskList(sshConfig) {
for (let index = 0; index < taskList.length; index++) {
const exectue = taskList[index];
await exectue(sshConfig, index + 1)
}
}
// 檢查環境配置
function checkEnvCorrect(sshConfig, mode) {
const keys = [,
'host',
'port',
'username',
'password',
'local',
'remote',
'script'
]
keys.forEach((item) => {
const key = sshConfig[item]
if (!key || key === '/') {
error(`配置錯誤: ${underline(`${mode}環境`)} ${underline(`${item}屬性`)} 配置不正确`)
process.exit(1)
}
})
}
const main = async (mode) => {
if (mode) {
const answer = await inquirer.prompt([{
type: 'confirm',
message: '是否進行部署?',
name: 'confirm', // 互動的關鍵字,如果有多條資料可以在這邊擷取到
}])
const currentTime = new Date().getTime()
if (answer.confirm) {
const sshConfig = config[mode]
checkEnvCorrect(sshConfig, mode)
handleTaskList()
await executeTaskList(sshConfig)
const nowTime = new Date().getTime()
succeed(`????????????恭喜,項目部署成功,耗時${(nowTime - currentTime) / 1000}s \n`)
process.exit(0)
} else {
info('取消部署')
}
} else {
error('請配置部署環境 --mode')
process.exit(1)
}
}
program
.option('-m, --mode <type>', 'add the specified type of dev', 'dev')
.action((options) => {
// console.log(options.mode);
main(options.mode)
});;
program.parse(process.argv);