前言
本文适合了解node、shell,想自动部署的前端开发。
在上文前端工程--“巨无霸解耦”中,我们已经将 “巨无霸” 工程拆分成多个独立的小工程,那么当我们遇到下面场景的时候,我们需求怎么去维护呢?
- 统一修改小工程的配置项,如何提交?
- 怎么构建部署整个应用?
处理
当面对大量重复工作内容,最好的做法就是交给别人去完成,但前端已经站在生态链最顶端,没别人了,只能交给电脑完成。
逻辑图
stateDiagram-v2
start --> 电脑: 获取指令
电脑 --> dist: 按照指令构建
dist --> nginx: 上传dist目录到nginx
nginx --> end
批处理代码
获取指令
// shell脚本
// 获取构建即将构建app,并保存到变量name
read -p "输入构建childApp名称:" name;
自动构建
// shell脚本
// 跳转目录拉代码并直接构建包
deploy(){
cd $1
git pull
npm i
npm rebuld node-sass
npm run build
}
$1表示执行deploy方法的第一个参数
自动部署
就是由脚本将指定内容上传到指定服务的指定位置,我们前端使用scp2上传的较多。
安装scp2
npm install scp2
使用scp2
// 使用node执行的js
// 服务的配置信息
const SERVER_CONFIG = {
host:*******, //ip
port:*******, //端口
username:****, //用户名
password:****, //密码
readyTimeout:500000,//连接超时
path:******, //上传的ngxin绝对路径
dist:*****, //需要上传的dist路径,相对当前js的路径
}
const scpClient = require("scp2");
scpClient.scp(
SERVER_CONFIG.dist,
{
host:SERVER_CONFIG.host,
port:SERVER_CONFIG.port,
username:SERVER_CONFIG.username,
password:SERVER_CONFIG.password,
path:SERVER_CONFIG.path,
readyTimeout:SERVER_CONFIG.readyTimeout
},
function(err){
if (err) {
logs(chalk.red(`发布失败`))
throw err
} else {
logs(chalk.green(`发布成功`))
}
}
)
PS:单独使用scp虽然已经满足我们的需求,但是用户体验并不好,只会在最后的时候给一个结果,所以我们调整一下,增加清缓存和上传的各种logs。
调整之后的代码如下:
// deploy.sh
# 获取用户输入
run(){
showMapInfo
read -p "输入构建子应用名称:" name
showNginxMapInfo
read -p "设置部署nginx的配置:" config
if [ "$name" == "master" ]; then
deploy master
elif [ $name == "childApp1" ]; then
deploy childApp1
elif [ $name == "childApp2" ]; then
deploy childApp2
elif [ $name == "childAppn" ]; then
deploy childAppn
fi
}
run
# 映射关系
showMapInfo(){
echo "即将构建的childApp:"
echo "childApp1 --> childApp1"
echo "childApp2 --> childApp2"
echo "childApp3 --> childApp3"
}
# nginx配置映射
showNginxMapInfo(){
echo "即将使用的nginx配置:"
echo "childApp1 --> childApp1"
}
# 打包发布
deploy(){
echo "$1 应用开始构建**************"
echo "../$1"
cd ../$1
echo "git pull"
git pull
echo "git branch"
git branch
echo "npm i"
npm i
npm rebuild node-sass
echo "npm run build"
npm run build
echo "$1 应用构建完成"
if [ $config == ""]; then
echo "即将使用默认配置部署**************"
else
echo "即将使用 $config 配置进行部署**************"
fi
node ./index.js $1 $config #构建完成,使用node上传nginx
}
执行deploy.sh:在同一目录下git bash中输入 sh deploy.sh
// index.js
const scpClient = require('scp2');
const ora = require('ora'); // 转圈圈
const chalk = require('chalk'); // 颜色
const SSH2 = require('ssh2'); //清缓存
const childAppName = process.argv[2]; //接受传过来的环境变量$1
const nginxName = process.argv[3]; //接收传过来的环境变量$config
//通过 childAppName 和 nginxName 匹配正在的 SERVER_CONFIG
const SERVER_CONFIG = require(`./${nginxName}`)[childAppName]; //注意这里的数据结构
//开启转圈圈
const spinner = ora()
spinner.start();
// 清缓存
const Client =SSH2.Client;
const conn = new Client();
conn.on("ready", function () {
logs("开始清缓存...");
spinner.text = "正在删除缓存..."
conn.exec(`rm -rf ${server.path}`, rmCallback)
}).connect({
host: SERVER_CONFIG.host,
port: SERVER_CONFIG.port,
username: SERVER_CONFIG.username,
password: SERVER_CONFIG.password,
readyTimeout: SERVER_CONFIG.readyTimeout,
})
function rmCallback(err, steam){
if (err) {
spinner.stop();
logs(chalk.red("删除缓存失败"))
throw err
};
logs("删除缓存成功")
steam.on('close', uploadFile);
conn.end();
}
// 上传包
function uploadFile() {
logs("开始发布...");
logs(`正在发布(${server.host}:${server.port} ${server.path})...`);
spinner.text = `正在发布(${server.host}:${server.port} ${server.path})...`;
scpClient.scp(
server.outputDir,
{
host: SERVER_CONFIG.host,
port: SERVER_CONFIG.port,
username: SERVER_CONFIG.username,
password: SERVER_CONFIG.password,
readyTimeout: SERVER_CONFIG.readyTimeout,
path: SERVER_CONFIG.path,
},
function (err) {
if (err) {
logs(chalk.red(`${appName}发布失败`))
throw err
} else {
logs(chalk.green(`${appName}发布成功`))
}
}
)
}
// 打印日志
function logs(str) {
setTimeout(() => {
console.log(`${new Date().toLocaleTimeString()}:${str}`)
}, 0)
}
最终执行结果:
总结
适用的场景
- 前端解耦后,组装目录,对外提供全量gz包
- 自动部署到nginx
- 自动打tag等相关git操作
常用的命令
命令 | 说明 | 样例 |
---|---|---|
read | 命令行获取输入 | read -p "输入构建子应用名称:" name |
mkdir | 创建目录 | mkdir dist\childApp1 |
copy | window下复制 | copy D:\编程项目\2020\组件库\childApp1\src\components\TongComponents\js\* D:\编程项目\2020\组件库\childApp1\dist\js |
tar | 压缩目录 | tar -czvf childApp1.tar.gz childApp1 |
npm publish | 发布仓库 | npm publish --registry=**** |