zoukankan      html  css  js  c++  java
  • 前端自动化部署的深度实践

    年前我也在自动化部署这方面下了点功夫,将自己的学习所得在自动化部署的一小步,前端搬砖的一大步这篇博客中做了分享。感谢两位网友@_shanks@TomCzHen的意见,让我有了继续优化部署流程的动力。本文主要是在自动化部署流程中,对版本管理流程合理性等方面做了一些改进,配合规范的工作流,使用体验更佳!

    更新日志自动生成

    之前我都是手动修改CHANGELOG.md,用来记录更新日志,感觉操作起来有点心累,也不是很规范。好在已有前人种树,于是我就考虑利用conventional-changelog-cli自动生成和更新CHANGELOG.md,真的好用!

    真香警告

    什么是conventional-changelog

    Generate a changelog from git metadata

    根据git元数据生成更新日志,而conventional-changelog-cli则是相关的命令行工具。

    安装conventional-changelog-cli

    npm install -g conventional-changelog-cli
    

    初始化生成CHANGELOG.md

    cd my-project
    conventional-changelog -p angular -i CHANGELOG.md -s
    

    以上命令是基于最后一次的Feature, Fix, Performance Improvement or Breaking Changes等类型的commit记录生成或更新CHANGELOG.md。如果你希望根据之前所有的commit记录生成完整的CHANGELOG.md,那么可以试试下面这条命令:

    conventional-changelog -p angular -i CHANGELOG.md -s -r 0
    

    工作流

    代码添加到暂存区

    这一步没有什么特殊,日常撸代码,然后将工作区的内容添加到暂存区。

    git add .
    

    规范commit message

    一个规范的commit message一般分为三个部分Header,Body 和 Footer。Header包含type, scope, subject等部分,分别用于描述commit类型,影响范围,commit简述。Body则是详细描述,可以分多行写。Footer主要用于描述不兼容改动(Breaking Change)或者关闭issue(Closes #issue)。

    格式如下:

    <type>(<scope>): <subject>
    
    <body>
    
    <footer>
    

    举个栗子:

    feat(支持自动部署): 结合conventional-changelog,配合部署脚本完成部署任务
    
    conventional-changelog是一个很好的工具,用于自动生成changelog,再配上自定义的部署脚本,整个部署流程就显得更规范了
    
    Breaking Change: 比较大的更新
    Closes #315
    

    其中,Header是必需的,BodyFooter可以省略。

    大致了解规范后,就可以上工具了,这里我们用到的是commitizen

    npm install -g commitizen
    

    接着在项目根目录运行以下命令:

    commitizen init cz-conventional-changelog --save --save-exact
    

    运行成功后,package.json会新增如下内容:

    "devDependencies": {
      "cz-conventional-changelog": "^3.1.0"
    },
    "config": {
      "commitizen": {
        "path": "./node_modules/cz-conventional-changelog"
      }
    }
    

    git commit这一步用git cz替代cz就是指commitizen,通过交互式命令行完成commit操作。

    PS D:
    obinfrontendspa-blog-frontend> git cz
    cz-cli@4.0.3, cz-conventional-changelog@3.1.0
    
    ? Select the type of change that you're committing: feat:     A new feature
    ? What is the scope of this change (e.g. component or file name): (press enter to skip) 支持自动部署
    ? Write a short, imperative tense description of the change (max 86 chars):
     (37) 结合conventional-changelog,配合部署脚本完成部署任务
    ? Provide a longer description of the change: (press enter to skip)
    
    ? Are there any breaking changes? No
    ? Does this change affect any open issues? No
    [master ee41f35] feat(支持自动部署): 结合conventional-changelog,配合部署脚本完成部署任务
     3 files changed, 15 insertions(+), 3 deletions(-)
    

    处理版本号,更新CHANGELOG

    接着我们要更新npm包的版本号,结合npm versionconventional-changelog使用,可以同时更新CHANGELOG.md

    好的,我们先准备好脚本:

    "scripts": {
        "start": "vue-cli-service serve",
        "build": "vue-cli-service build",
        "deploy": "node deploy",
        "version": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md",
        "postversion": "npm run deploy"
    }
    

    根据实际版本情况选择更新patch/minor/major版本。假设我们更新的是minor版本号,那么操作命令如下:

    npm version minor -m '特性版本更新'
    

    执行这条命令会更新package.json中的version字段,

    同时会执行conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md,更新CHANGELOG.md

    执行完这条命令后,可以看到CHANGELOG.md已经被修改了。

    CHANGELOG自动更新

    npm钩子触发部署脚本

    通过postversion钩子触发部署脚本node deploy,开始进行部署工作。deploy.js文件内容如下:

    const { execFile } = require('child_process');
    
    const version = process.env.npm_package_version;
    
    execFile('deploy.sh', [version], { shell: true }, (err, stdout, stderr) => {
        if (err) {
            throw err;
        }
        console.log(stdout);
    });
    

    这里利用了nodejschild_process模块执行子进程,调用了execFile执行了 deploy.sh,并将npm包版本号作为参数传递给了deploy.sh

    deploy.sh文件内容如下:

    #!/bin/bash
    npm run build
    htmldir="/usr/share/nginx/html"
    uploadbasedir="${htmldir}/upgrade_blog_vue_ts"
    appenddir=$1
    uploaddir="${uploadbasedir}/${appenddir}"
    projectdir="/usr/share/nginx/html/blog_vue_ts"
    scp -r ./dist/. txcloud:${uploaddir}
    ssh txcloud > /dev/null 2>&1 << eeooff
    ln -snf ${uploaddir} ${projectdir}
    exit
    eeooff
    echo done
    

    以上命令主要做的事情是:

    • npm run build执行构建任务
    • 将构建得到的dist文件夹中的内容通过scp传输到服务器,通过版本号区分各个版本。
    • nginx配置的是监听80端口,指向/usr/share/nginx/html/blog_vue_ts,而我通过软连接将blog_vue_ts再次指向到upgrade_blog_vue_ts下的版本目录,如upgrade_blog_vue_ts/0.5.4。每次发布版本时,以上脚本会修改软连接,指向目标版本,如upgrade_blog_vue_ts/0.6.0,完成版本过渡。

    我这里使用了软连接改进了之前的部署脚本,既可以在服务器保留各个历史版本文件夹,也不用考虑处理index.html与静态资源分离的问题。

    强烈建议结合自动化部署的一小步,前端搬砖的一大步这篇文章一起看。

    lrwxrwxrwx 1 root root   47 Feb  3 21:35 blog_vue_ts -> /usr/share/nginx/html/upgrade_blog_vue_ts/0.6.0
    

    linux服务器项目版本文件夹

    如果要回退版本,也可以通过修改软连接的方式实现,还是比较方便的。

    推送到remote

    最后别忘了把代码push到远程仓库。

    git push
    

    更新日志changelog查看也变得很方便了,修改了什么内容一目了然,并且可以直接跳转到commit历史,issue等。

    github上的changelog

    番外

    可以看到,我是通过deploy.js调用了deploy.sh。之前本想直接在npm scripts中调用deploy.sh并传入版本号参数的,但是试了几种写法都不行,这里也记录一下。

    "deploy": "deploy.sh npm_package_version"
    
    "deploy": "deploy.sh $npm_package_version"
    

    看起来在npm scripts中调用sh脚本时,只能写字面量参数,传变量作为参数好像行不通。

    下面这种字面量参数写法是可以的,但是就有点呆呆的感觉了,而且与自动化部署的主题不符。

    "deploy": "deploy.sh 0.6.0"
    

    所以我目前还是选择通过deploy.js作为中间者来调用deploy.sh的。

    结语

    需要承认的是,我以上所述的部署流程是以我的个人项目为例说明,可能不是很规范,但是也算是通过自己的理解和摸索,完整地搞了一套部署流程,并没有借用jenkins等工具。有了这段自动化部署的学习经历后,相信学习和使用jenkins会变得更轻松。接下来我会继续优化和规范自己的部署流程,jenkins理所当然会出现在我的计划表中。

    我是Tusi,一个创业公司前端小leader,每天依然为写不完的业务代码烦恼,在打磨产品道路上沉淀技术,探索成长路线。如果你与我一样,正在思考自己的技术成长与价值,欢迎加我微信交流探讨,微信号ice_lloly。我会在公众号猿出道和小程序Tusi博客同步博客内容,快来撩我!

    欢迎关注

  • 相关阅读:
    JavaScript
    94.Binary Tree Inorder Traversal
    144.Binary Tree Preorder Traversal
    106.Construct Binary Tree from Inorder and Postorder Traversal
    105.Construct Binary Tree from Preorder and Inorder Traversal
    90.Subsets II
    78.Subsets
    83.Merge Sorted Array
    80.Remove Duplicates from Sorted Array II
    79.Word Search
  • 原文地址:https://www.cnblogs.com/wenbinjiang/p/12259137.html
Copyright © 2011-2022 走看看