使用Jenkins部署React项目的方法步骤


Posted in Javascript onMarch 11, 2019

背景

公司的前端项目部署方式比较简单,整个过程基本上是手动的;

目标

通过工具实现以下几个任务:

  • 编译、部署自动化;
  • 选择指定版本进行回滚;
  • 区分不同的分支(环境);

技术方案

  • 选用 jenkins 作为部署工具;也便于后续 CI 的接入;
  • 使用 docker 进行编译,确保每次编译的环境的稳定;

步骤

步骤一:搭建 Jenkins

搭建 Jenkins 有很多方案,这里选择使用 docker 搭建。

docker-compose.yml 的内容如下:

version: '3'
services:
 fejenkins:
  user: root
  image: jenkinsci/blueocean
  ports:
   - "8080:8080"
   - "50000:50000"
  volumes:
   - /data/jenkins_home:/var/jenkins_home
   - /data/nm_cache:/var/nm_cache
   - /var/run/docker.sock:/var/run/docker.sock

通过 docker-compose up 命令启动;启动后通过初始密码进行第一个用户的创建和 Jenkins 初始化的一些列操作,初始密码会打印在 jenkins docker 启动命令行的输出中,注意查看。

当然也可以不使用 docker-compose:

docker run --rm -u root -v /data/jenkins_home:/var/jenkins_home -v /data/nm_cache:/var/nm_cache -v /var/run/docker.sock:/var/run/docker.sock -p 8080:8080 -p 50000:50000 jenkinsci/blueocean

稍做解释:

  • /data/jenkins_home:/var/jenkins_home /var/jenkins_home 是 jenkinsci image 的默认数据存放路径,这里将路径映射到宿主机的指定文件夹;
  • /data/nm_cache:/var/nm_cache nm_cache 涵义是 node_modules cache,顾名思义,这里是想对编译所需的 node_modules 做缓存,将缓存文件夹也映射到宿主机;
  • /var/run/docker.sock:/var/run/docker.sock 这里是将宿主机运行 docker 后产生的 sock 文件映射到了 jenkins container 中。这样,jenkins 中使用 docker 进行编译时,其实是使用宿主机的 docker 来运行的,而不是在 docker container 中又启动了 docker。这里稍微有点绕,若是暂时看不明白,需要找一些深入介绍 docker 的文章阅读;

步骤二:配置 Jenkins

添加 Credentials

通过 Jenkins 进行 git 操作需要对应 git repo 的权限,这里需要用到有 git repo 权限的密钥文件。同样,通过 Jenkins 将编译产物 scp 到服务器上的时候,也需要服务器的密钥文件。

这两类密钥文件需要配置在 Jenkins 中,在:Jenkins > Credentials > System > Global credentials (unrestricted) 里进行 Add Credentials 的操作。

添加 Jenkins Item

Jenkins > New Item,然后选择 Pipeline,在下面的 Pipeline 配置区域的 Definition 中选择 Pipeline script,Script 如下:

pipeline {
  environment {
    SERVER_IP_1 = "11.22.33.44"
    SERVER_CREDENTIALSID = "abcd1234-abcd-abcd-abcd-abcd1234abcd"
    SERVER_DEPLOY_DIR = "/your/www/path/"

    CACHE_DIR = "/var/nm_cache/your_project_name/"

    GIT_URL = "git@github.com:example/example.git"
    GIT_BRANCH = "master"
    GIT_CREDENTIALSID = "abcd1234-abcd-abcd-abcd-abcd1234abcd"
  }
  agent none
  stages {
    stage('Checkout code') {
      agent any
      steps {
        git (
          branch: "${GIT_BRANCH}",
          credentialsId: "${GIT_CREDENTIALSID}",
          url: "${GIT_URL}",
          changelog: true
        )
        sh '''
          ls -al
          cache_dir="${CACHE_DIR}"
          cache_nm="${CACHE_DIR}node_modules"
          cache_lock="${CACHE_DIR}yarn.lock"

          if [ ! -d "$cache_dir" ]; then mkdir ${cache_dir}; fi
          if [ ! -d "$cache_nm" ]; then mkdir ${cache_nm}; fi
          if [ -d "$cache_nm" ]; then ln -sf ${cache_nm} ./; fi
          if [ -f "$cache_lock" ]; then mv -n ${cache_lock} .; fi

          ls -al
        '''
      }
    }
    stage('Build') {
      agent {
        docker {
          image 'node:8-alpine'
          args ''
        }
      }
      steps {
        sh '''
          npm config set registry https://registry.npm.taobao.org
          yarn install
          yarn build
          tar -cvf build.tar build

          ls -al
          mv ./yarn.lock ${CACHE_DIR}
          rm -rf ./node_modules
          ls -al
        '''
        archiveArtifacts artifacts: 'build.tar', fingerprint: true
      }
    }
    stage('Deploy') {
      agent any
      steps {
        unarchive mapping: ['build.tar': 'build.tar']
        echo '--- Deploy ---'

        sshagent(["${SERVER_CREDENTIALSID}"]) {
         sh "scp -o StrictHostKeyChecking=no build.tar root@${SERVER_IP_1}:${SERVER_DEPLOY_DIR}"
         sh "ssh -o StrictHostKeyChecking=no root@${SERVER_IP_1} \"rm -rf ${SERVER_DEPLOY_DIR}build; tar -xvf ${SERVER_DEPLOY_DIR}build.tar -C ${SERVER_DEPLOY_DIR}\""
        }

      }
    }
  }
}

稍做解释:

这个部署脚本分为三个步骤:

  • Checkout code(在指定 git 仓库通过指定证书文件获取代码)
  • Build(通过指定命令进行编译,将编译后的产物存档)
  • Deploy(通过指定命令部署)

在 Build 阶段前后,我们各做了一些工作,以求每次部署可以复用 node_modules,因为下载 node_modules 的时间可能很长,而并不是每次都会修改 package.json,所以其实 node_modules 大概率可以复用;

编译前:

  • 看指定 node_modules 缓存文件夹是否存在,不存在则新建该文件夹;
  • 看缓存文件夹中是否有 node_modules 文件夹,如果没有则新建该文件夹;并且将该文件夹软连接到当前目录;
  • 看缓存文件夹中是否有 yarn.lock 文件,如果有则移动到当前文件夹;

编译后:

  • 移除 node_modules 文件夹的软连接;
  • 将 yarn.lock 文件移动到缓存文件夹中;

这里使用了 yarn install 的某些特性:

  • 没有 node_modules 或者 yarn.lock 时会安装全量依赖;
  • 有 node_modules 和 yarn.lock 但是 yarn.lock 和 package.json 不匹配时,会安装所需依赖;
  • 有 node_modules 和 yarn.lock,且 yarn.lock 和 packge.json 配置时,跳过安装依赖;

使用

编译和部署

编译和部署直接点击 Build Now 即可;

回滚

回滚的本质其实是:重新部署某个历史版本。在 Build History 找到想要重新部署的版本,点击 Restart from Stage,在新页面中选择 Stage Name 为 Deploy。

其他

若是想要进入 docker container 交互,可以通过以下命令

docker exec -i -t [dockername] /bin/bash

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
非常好用的JsonToString 方法 简单实例
Jul 18 Javascript
jQuery函数的第二个参数获取指定上下文中的DOM元素
May 19 Javascript
javascript实现点击按钮让DIV层弹性移动的方法
Feb 24 Javascript
JavaScript基于ajax编辑信息用法实例
Jul 15 Javascript
Javascript HTML5 Canvas实现的一个画板
Apr 12 Javascript
JS控制弹出悬浮窗口(一览画面)的实例代码
May 30 Javascript
javascript显示系统当前时间代码
Dec 29 Javascript
BootStrap 导航条实例代码
May 18 Javascript
vue实现移动端悬浮窗效果
Dec 01 Javascript
vue element-ui读取pdf文件的方法
Nov 26 Javascript
JS前端面试必备——基本排序算法原理与实现方法详解【插入/选择/归并/冒泡/快速排序】
Feb 24 Javascript
微信小程序吸底区域适配iPhoneX的实现
Apr 09 Javascript
vue基础之v-bind属性、class和style用法分析
Mar 11 #Javascript
配置eslint规范项目代码风格
Mar 11 #Javascript
vue基础之事件简写、事件对象、冒泡、默认行为、键盘事件实例分析
Mar 11 #Javascript
vue基础之事件v-onclick="函数"用法示例
Mar 11 #Javascript
每天学点Vue源码之vm.$mount挂载函数
Mar 11 #Javascript
JavaScript中常用的简洁高级技巧总结
Mar 10 #Javascript
angular 实现下拉列表组件的示例代码
Mar 09 #Javascript
You might like
PHP SPL标准库之数据结构堆(SplHeap)简单使用实例
2015/05/12 PHP
php简单处理XML数据的方法示例
2017/05/19 PHP
php微信开发之关注事件
2018/06/14 PHP
记录Yii2框架开发微信公众号遇到的问题及解决方法
2018/07/20 PHP
学习YUI.Ext 第六天--关于树TreePanel(Part 2异步获取节点)
2007/03/10 Javascript
javascript 系统文件夹文件操作及参数介绍
2013/01/08 Javascript
javascript怎么禁用浏览器后退按钮
2014/03/27 Javascript
jQuery实现鼠标可拖动调整表格列宽度
2014/05/26 Javascript
分享一款基于jQuery的视频播放插件
2014/10/09 Javascript
node.js中的fs.utimes方法使用说明
2014/12/15 Javascript
jQuery插件jRumble实现网页元素抖动
2015/06/05 Javascript
AngularJS控制器controller正确的通信的方法
2016/01/25 Javascript
JS获取中文拼音首字母并通过拼音首字母快速查找页面内对应中文内容的方法【附demo源码】
2016/08/19 Javascript
jquery实现网页定位导航
2016/08/23 Javascript
Vue.js实战之通过监听滚动事件实现动态锚点
2017/04/04 Javascript
JS判断两个对象内容是否相等的方法示例
2017/04/10 Javascript
小发现之浅谈location.search与location.hash的问题
2017/06/23 Javascript
微信小程序之电影影评小程序制作代码
2017/08/03 Javascript
vue实现点击关注后及时更新列表功能
2018/06/26 Javascript
解决vue项目本地启动时无法携带cookie的问题
2021/02/06 Vue.js
TensorFlow实现随机训练和批量训练的方法
2018/04/28 Python
Django之模型层多表操作的实现
2019/01/08 Python
Django中使用Whoosh进行全文检索的方法
2019/03/31 Python
python 修改本地网络配置的方法
2019/08/14 Python
利用Python校准本地时间的方法教程
2019/10/31 Python
Python箱型图处理离群点的例子
2019/12/09 Python
Pytorch实验常用代码段汇总
2020/11/19 Python
Pytorch如何切换 cpu和gpu的使用详解
2021/03/01 Python
美国蔬菜和植物种子公司:Burpee
2017/02/01 全球购物
客户代表实习人员自我鉴定
2013/09/27 职场文书
简历的个人自我评价范文
2014/01/03 职场文书
心理健康课教学反思
2014/02/13 职场文书
2014年“世界无车日”活动方案
2014/09/21 职场文书
英文产品推荐信
2015/03/27 职场文书
使用Python脚本对GiteePages进行一键部署的使用说明
2021/05/27 Python
手把手带你彻底卸载MySQL数据库
2022/06/14 MySQL