刚进入公司的时候,公司的前端项目部署使用的Jenkins和GitLab进行部署,但是后来不知道什么原因舍弃了这种方法,开始了手动部署,前端则开始使用fileZilla这个软件进行部署,每次都要将项目打包后再使用该工具进行上传打包好的项目,多少还是感觉有些麻烦,所以想要自己写一个适用于前端部署的一个工具。
初始化
首先运行npm init
进行初始化package.json文件
将package.json文件中增加bin选项,值为命令行中的入口文件
{...
"name": "mycmd",
"bin":"./src/cmds/index"
...}
依赖
"chalk": "^4.0.0", // 命令行样式
"commander": "^10.0.0", // 命令行
"compressing": "^1.9.0", // 文件压缩解压
"inquirer": "^8.0.0", // 命令行交互
"node-ssh": "^13.0.1", // 连接服务器
"ora": "^5.0.0", // 命令行loading样式
"shelljs": "^0.8.5" // 执行shell语句
代码
/src/cmds/index
文件
需要在文件首行加上#!/usr/bin/env node
标记为使用node解析
#!/usr/bin/env node
const program = require('commander')
program
.version('0.1.0')
program.command('deploy','部署项目').alias('dp');
program.parse(process.argv);
新建/src/cmds/index-deploy
文件,commander会根据program.command('deploy','部署项目').alias('dp');
找到该文件,action中就是要执行的方法。
#!/usr/bin/env node
const program = require('commander')
program
.command('deploy')
.alias('dp')
.description('deploy project')
.action(function () {
const { NodeSSH } = require('node-ssh') // 连接服务器
const ssh = new NodeSSH()
const chalk = require('chalk')
const ora = require('ora') // 命令行loading动画
const shell = require('shelljs')
const compressing = require('compressing') // 进行压缩文件
const inquirer = require('inquirer') // 命令行交互
// 引入配置文件
const { CONFIG } = require('../utils/config.js')
let config
const fullname = shell.pwd().toString()
const path = require('path')
const distDir = path.resolve(fullname, './dist')
const zipDistDir = fullname + '\\dist.zip'
// 拉取当前分支的最新代码
const pullCode = async () => {
const loading = ora('拉取代码').start()
shell.cd(fullname)
const res = await shell.exec('git pull')
loading.stop()
if(res.code === 0) {
console.log(chalk.green("拉取代码成功"))
} else {
console.log(chalk.red('拉取代码失败'))
process.exit()
}
}
// 项目打包
const build = async () => {
const loading = ora('开始打包').start()
console.log(fullname)
shell.cd(fullname)
const res = await shell.exec('yarn build')
loading.stop()
if (res.code === 0) {
console.log(chalk.green('打包成功'))
} else {
console.log(chalk.red('打包失败'))
process.exit()
}
}
// 压缩文件
const zipDist = async () => {
console.log(chalk.blue('开始压缩'))
const loading = ora('开始压缩').start()
try {
await compressing.zip.compressDir(distDir, zipDistDir)
console.log(chalk.green('压缩成功'))
loading.stop()
} catch (error) {
loading.stop()
console.log(chalk.red(error))
console.log(chalk.red('压缩失败'))
process.exit()
}
}
// 连接服务器
const connectSHH = async () => {
console.log(chalk.blue('开始连接服务器'))
try {
await ssh.connect({
host: config.SERVE_HOST,
port: config.SERVE_PORT,
username: config.SERVE_ROOT,
password: config.SERVE_PASSWORD
})
console.log(chalk.green('连接成功'))
} catch (err) {
console.log(chalk.red(err))
console.log(chalk.red('连接失败'))
process.exit()
}
}
// 执行linux 语句
const runCommand = async (command) => {
const result = await ssh.exec(command, [], { cwd: config.DEPLOY_PATH })
console.log(result)
}
// 删除目录下所有文件
const clearFile = async () => {
const commands = ['ls', 'rm -rf *']
await Promise.all(commands.map(async (it) => {
return await runCommand(it)
}))
}
// 部署
const uploadFile = async () => {
await pullCode() // 拉取当前分支代码
await build() // 打包
await zipDist() // 压缩
await connectSHH() // 连接服务器
await clearFile() // 清理原来部署的文件
try {
console.log(chalk.blue('开始上传压缩包'))
await ssh.putFiles([{ local: zipDistDir, remote: `${config.DEPLOY_PATH}/dist.zip` }])
console.log(chalk.green('上传成功'))
console.log(chalk.blue('开始解压压缩包'))
await runCommand('unzip ./dist.zip')
console.log(chalk.green('解压完成'))
console.log(chalk.blue('开始删除压缩包'))
await runCommand(`rm -rf ${config.DEPLOY_PATH}/dist.zip`) //解压完删除线上压缩包
console.log(chalk.green('删除成功'))
// 将dist目录中的文件移出来
await runCommand(`mv -f ${config.DEPLOY_PATH}/dist/* ${config.DEPLOY_PATH}`)
await runCommand(`rm -rf ${config.DEPLOY_PATH}/dist`) //移出后删除 dist 文件夹
console.log(chalk.green('部署完成'))
ssh.dispose()
console.log(chalk.yellow('断开连接'))
} catch (err) {
console.log(chalk.red(err))
console.log(chalk.red('上传失败'))
process.exit()
}
}
inquirer
.prompt([{
type: 'list',
message: '请选择发布环境',
name: 'env',
choices: [{
name: '96',
value: 96
}, {
name: '95',
value: 95
}, {
name: '181',
value: 181
}, {
name: '183',
value: 183
}]
}])
.then(answers => {
config = CONFIG[answers.env]
uploadFile()
})
}).parse(process.argv)
其中CONFIG
提前写好的配置,格式如下
CONFIG : {
96:{
DEPLOY_PATH: "/root/project", // 服务器部署路径
SERVE_HOST: '122.1.0.96', // 服务器地址
SERVE_PORT: '22', // 端口
SERVE_ROOT: 'root', // 用户名
SERVE_PASSWORD: 'root' // 密码
}
}
运行
代码写好后运行 npm link
,就可以在项目所在目录里运行命令行指令mycmd dp
(mycmd
根据你的项目名称而定)进行部署
运行npm unlink
接触连接