前端自动化部署简单实践

1,981 阅读4分钟

写在开头

为何写这篇文章

最近交付了一个多端小项目,部署这块动静尽量最小话,没有必要为了它搭建一套 ci pipeline,于是我就走上了自动化部署方案的调研之路,掘金上大多是讲Jenkins + docker,通过调研用纯nodejs得出两套我觉得可行的方案,写下来作为学习记录。

为何起名为简单实践

很显然是因为操作起来很简单那,尤其适用小型敏捷开发的项目
前端无需了解传统CI工具,如jenkins circle ci等,也无需去关注持续集成的环境问题,只要一个node环境即可完成自动化部署。

思路

假设现在我们开发完成,准备把代码发布到沙盒环境,我们可以:

  • 土方法
    • 登录 ssh
    • cd 到对应资源目录
    • 把打包好的资源文件拖到该目录
  • 第一次升级
    • 写一个脚本文件,通过ftp的方式,把文件提交到服务器
    • 可以手动运行 npm run deploy 运行该js脚本
    • 可以用husky在提交代码之前,运行该js脚本
  • 第二次升级
    • 利用gitweb hook,每次push触发该钩子,向服务器发送一次请求,剩下部署工作在服务器中完成

首先,土方法可能是最不需要成本,但是效率最低的方式,尤其是在bugfix阶段一直需要不断提交代码,每次都手动打包,手动部署很是耗精力。第一次升级是通过ftp的方式,本地打包代码,手动运行脚本,连接服务器然后提交到服务器的资源文件夹下,这个方案其实不错,但是连接ssh需要把服务器账号密码暴露在代码,不推荐。第三次升级也就是终极解决方案,所有的打包部署交给服务器完成。
所以,我们可以有两种部署方案,如果你对ftp或者web hook不了解,没关系,下文会细讲~

代码实现(伪代码)

case1: ftp

const path = require('path');
const gulp = require('gulp');
const sftp = require('gulp-sftp-up4');

const config = {
    remotePath: '静态资源在服务器的路径',
    host: '服务器ip',
    password: '密码'
};

gulp.src(path.resolve(__dirname, '../dist/**')).pipe(sftp(config));

实现很简单,就是直接从本机把dist里的内容推送到服务器xx目录,gulp作为载体,推送逻辑由gulp-sftp-up4实现

case2: web hook

web hook的原理是,在某个节点(push commit pull ...)会提交一次请求,请求的request body中会携带该仓库的信息
首先需要在git上找到web hook settings,我司用的是gogs作为代码仓库 web hook 截图 填写推送地址,选择hook触发事件为每次代码push,这样每次push代码都会请求上面的地址,这里我用pm2起了个简单的node server

const childProcess = require('child_process');
const Koa = require('koa');
const Router = require('koa-router');
var bodyParser = require('koa-bodyparser');
const app = new Koa();
const router = new Router();

app.use(bodyParser());

router.post('/web-hook', async (ctx, next) => {
    childProcess.exec('sh deploy.sh', { maxBuffer: 1024 * 1024 * 1024 }, (error, stdout, stderr) => {});
    await next();
});

...
...
...

app.use(router.routes()).use(router.allowedMethods());
app.listen(8082, () => {
    console.log('server is starting on port 8082!');
});

server端接收到请求,做了唯一一件事,执行deploy.sh,下方为shell脚本伪代码

#!/bin/bash
set -e

SOURCE_PATH='项目源码存放的目录'
DEPLOY_PATH='打包文件对应的目录'
TAR="output.tar"

cd $SOURCE_PATH
git pull
git checkout master

echo 'git pull finished'

echo "Node version:"
node -v
echo "npm version:"
npm -v
echo "yarn version:"
yarn --version

yarn

if [ $? -ne 0 ]; then
    echo "yarn install failed!"
    exit 1
fi

rm -rf output
mkdir output

yarn build

if [ $? -ne 0 ]; then
    echo "build failed!"
    exit 1
fi

# 压缩
cd build
tar cvf $TAR ./*

cd $DEPLOY_PATH
rm -rf *
mkdir dir
cd dir

mv $SOURCE_PATH/output/$TAR $DEPLOY_PATH/dir

# 解压
cd $DEPLOY_PATH/dir
tar xvf $TAR
rm -rf $TAR
echo '部署完成'

以上就完成了每次提交代码,服务器端会代码更新、打包、部署,做到了对开发人员无感知,成功解放双手!实现非常简单,如果是多项目部署,可以把路径通过环境变量传给脚本。遗憾的是子进程的错误提示不会反馈给客户端,如果要做错误提示,只能开个定时任务抓取日志,但不影响核心功能正常运行。

总结

不管是ftporweb hook实现部署,他们都不是最终解决方案,只能说是自动化部署的一点影子,好处是多多少少可以提高一些工作效率,未来我也会在掘金记录一些工程化的调研成果