使用 Electron + React 搭建前端一键自动化打包部署应用程序

2,338 阅读4分钟

1 需求的产生

由于目前公司的项目部署发布流程非常麻烦,每一次打包都需要手工花费几分钟的时间,而这几分钟的时间,去摸个鱼岂不美哉?
PS:这世界是由懒人创造的

2 我司的项目部署流程

  1. 执行不同环境打包命令 例如 npm run build:beta(不同项目打包不同环境的命令可能不一样)
  2. 打包后删除所有 sourceMap 文件(安全考虑),由于项目有配置Sentry 正式环境部署会上传soureMap文件到Sentry后台,后删除
  3. 需要复制打包后的dist目录文件 到 SVN 的发布目录去覆盖上传(需要区分不同环境目录)
  4. 覆盖之前需要先 svn update 一下,以免冲突
  5. 覆盖完成,执行 svn commit 提交
  6. 提交成功后,可以在一个叫 Walle 的Web操作界面看到(私有化1.0)
  7. 然后在 Walle 一顿选择操作后(可能就6,7个步骤吧:)?最后点击全量部署就可以更新了...

你瞅瞅这是人应该干的事?

3 解决方案

把每一个步骤都代码化

4 最终效果实现

  • 创建项目与选择项目统一管理
  • 打包部署
  • 项目配置
  • 配置说明

5 开源仓库地址

github: auto-build-deploy-electron

点个小星星你就是我大哥QAQ

重要提示:代码只是参考作用,具体还是得根据自己项目部署的流程去实现

6 具体实现细节

6.1 使用到的包

  • React(界面实现)
  • puppeteer (实现对Walle平台的模拟人为操作)
  • fs-extra(更方便的做对文件做操作)
  • Node [child_process, path]
  • Electron [screen, shell, clipboard, remote]

6.2 执行 Shell 命令

如:拉取svn仓库最新代码,其他Shell命令大同小异

svnUpdate() {
  const { buildInfo } = this.state;
  this.showHint(`正在执行SVN Update... (ง •_•)ง`, 999);
  return new Promise(resolve => {
    const execNow = exec('svn update', { cwd: buildInfo.svnPath }, error => {
      if (error) {
        this.showHint(`SVN Update 失败! (┬_┬) ! 错误信息:${error}`);
        return;
      }
      this.showHint(`SVN Update 成功。 ♪(^∀^●)ノ`);
      resolve();
    });
    this.setState({ execNow });
  });
}

6.2 如何调用puppeteer做模拟人为操作

一些技巧:

  1. 使用puppeteer-core这个包 可以直接引用本地的chrome浏览器,如果使用原包puppeteer 需要去下载一个几百兆 Chromium 浏览器
  2. Mac 系统 Chrome 安装路径是固定的
  3. 配置puppeteerheadless 参数可以看到模拟实现过程,可以更好的调试
  4. Windows 系统 Chrome 安装地址不是固定的,所以需要一个选择 Chrome 位置的文件框

这是使用puppeteer校验 Walle 帐号密码的具体实现

import puppeteer from 'puppeteer-core'
import getChromePath from '../utils/getChromePath';
import { WALLE_ADDRESS } from '../config/index';

const checkWalleUserInfo = (obj) => {
  const WALLE_USERNAME = obj.username;
  const WALLE_PASSWORD = obj.password;
  const deploy = new Promise((resolve) => {
    (async () => {
      let browser;
      try {
        browser = await puppeteer.launch({
          headless: true,
          executablePath: getChromePath()
        });
        const page = await browser.newPage();
        await page.setViewport({
          width: 1920,
          height: 1080
        });
        await page.goto(WALLE_ADDRESS);
        await page.evaluate(() => ({
            width: document.documentElement.clientWidth,
            height: document.documentElement.clientHeight,
            deviceScaleFactor: window.devicePixelRatio
        }));
        /* 1.输入帐号密码进行点击登陆 */
        await page.evaluate((user, pass) => {
          document.querySelector('#loginform-username').value = user;
          document.querySelector('#loginform-password').value = pass;
        }, WALLE_USERNAME, WALLE_PASSWORD);

        const [response] = await Promise.all([
          page.waitForNavigation({
            waitUntil: 'domcontentloaded'
          }),
          page.click('.btn-primary'),
        ]);

        if (response._url === `${WALLE_ADDRESS}/site/login`) {
          resolve(500);
        } else {
          resolve(200);
        }
        await browser.close();
      } catch (error) {
        resolve(500);
        await browser.close();
      }
    })();
  });
  return deploy;
}
export default checkWalleUserInfo;

6.3 安装 svn 环境变量

  • windows安装svn的时候默认是不安装 svn comand line这个东西的,重装下svn客户端,注意在选择安装项目那里点上 svn comand line 就好了
  • 安装后 需要重启电脑,因为 windows 设置环境变量得重启才生效
  • Mac系统. 我忘记了.. 哈哈

7 跟其他自动化部署软件的看法

7.1 区别

  • Jenkins 大家都使用一台 Jenkins 服务器,导致部署会比较慢,无法看到实时看到进度,去配置起来也比较麻烦
  • 看到近期的deploy-cli-service 依赖服务器帐号密码,无法扩展自定义的项目部署流程,不过对个人项目还是挺方便的,也是作者导致我有了写这篇文章的想法~

7.2 优势

  • 可视化的看到每一个步骤的执行过程
  • 可以方便的增加依赖,减少服务器 npm i 的过程
  • 依赖自己电脑的开发环境,最大化利用电脑资源
  • 让机器替代人为工作
  • 打包成功率 = 你本地打包是否能正常,不用考虑服务器的意外情况
  • 可高自由度的扩展自己项目的流程,如build前进行单元测试,打包完成后邮箱通知
  • 可以为所欲为的增加流程,只要你开心

7.3 现有缺陷

  • 无法知道其他同事是否正在部署,可能会引发覆盖

7.4 解决方案

  1. 不推荐:让一位同事统一进行发布..
  2. 推荐:建立部署中心,点击部署的时候,调用接口查看该项目是否正在部署

不过我司目前单项目开发人员不多.. 所以就没去搞,需要的时候可以加上

8 一些思考

  • 不同公司有不同的部署方案,选择适合自己的才是最重要的~
  • 工欲善其事,必先利其器,一个舒适的部署流程也能增加自己的开发体验~

9 最后

  • 如果这篇文章对你有帮助,希望能点个赞,QAQ
  • 另外近期有跳槽想法,求个广州内推...
  • 有什么想法也可以一起交流下

本文使用 mdnice 排版