使用 GitHub Actions 完成 Nest 项目自动打包并发布到服务器


theme: scrolls-light
highlight: atom-one-dark

大家好,我是爱吃鱼的桶哥Z,最近我们使用 Nest.js 开发了一个后端服务,而 Nest.js 其实是一套基于 node 开发的框架,我们都知道 node 项目在服务端运行时需要使用 npm installnode_modules 安装在服务器中,但是 Nest.js 却不同,它本身的可以打包成一个可执行文件的,因此今天我们就一起来学习一下如何对 Nest.js 进行打包,并使用 GitHub Actions 将打包后的文件自动上传到服务器进行安装部署。

起因

我们之前做项目的时候用的是 express.js,但经过这么多年的发展,再用 express.js 开发项目已经不太适合了,因为它太灵活了,有时候太灵活的框架或类库其实并不是一件好事,因此我们需要选择一个更好用的框架。

之前其实也尝试使用过 egg.js 来开发项目,而目前 TS 已经很成熟了,但 egg.js 却不支持,因此我们只能另寻其它框架,刚好这时候就遇到了 Nest.js,它号称是 node 版本的 SprintBoot,可用于构建高效且可伸缩的服务端应用程序的渐进式 Node.js 框架,并且完美支持 Typescript,面向 AOP 编程,以及支持 Typeorm,基于这几点,我们最终选择使用 Nest.js 来开发项目。

当项目开发的差不多的时候,就需要着手考虑打包测试了,而这时候刚好掘金给我推荐了一篇关于 Nest.js 部署的文章,就是这篇文章,参考这篇文章,我们实现了项目的打包,但是在打包的过程中发现了几个问题,首先就是打包的时候会因为过滤的筛选项导致打包控制台报错,虽然最终打包是成功的,但是控制台报错是不能忍的,因此我们修改了这篇文章中给出的参考代码,最终修改了相关的 webpack 配置才正常打包成功,修改后的大致代码如下:

// webpack.config.js
module.exports = { 
    ...other code
    
    plugins: [
        // 需要进行忽略的插件
        new webpack.IgnorePlugin({
            checkResource(resource) {
                const lazyImports = [
                    '@nestjs/microservices',
                    '@nestjs/microservices/microservices-module',
                    '@nestjs/websockets/socket-module',
                    'cache-manager',
                    'class-validator',
                    'class-transformer',
                    'class-transformer/storage',
                ];
                if (!lazyImports.includes(resource)) {
                    return false;
                }
                try {
                    require.resolve(resource, {
                        paths: [process.cwd()],
                    });
                } catch (err) {
                    return true;
                }
                return false;
            },
        }),
        new ForkTsCheckerWebpackPlugin(),
    ],
}

以上 webpack 配置主要参考这篇文章,我们只是修改了其中需要忽略的插件。打包的配置已经准备好了,接下来就需要配置 GitHub Actions 了,毕竟我们也不想每次要上线的时候还手动去打包并将代码上传到服务器中。

使用 Github Actions 完成自动打包

我在掘金写的第一篇文章其实就是关于 Github Actions 自动打包的,而当前主要是使用 Github Actions 来打包 Electron 项目,并不需要将打包后的文件上传到服务器进行自动部署,而这一次我们不仅要实现自动打包,还需要将代码自动上传到服务器中,并自动进行部署运行,那我们该如何做呢?

如果看过我第一篇文章的童鞋应该都知道,要实现 Github Actions 首先就需要在 GitHub 上新建一个项目,然后在项目文件夹中添加 .github/workflows 这样的文件目录,最后还需要添加一个后缀为 .yml 的可执行文件,这样当我们将项目提交到 GitHub 中,GitHub 检测到相关的配置就会自动执行打包了。

下面我们一起来看一下这次项目新建的一个 main.yml ,里面的相关配置会在后面为大家进行介绍,代码如下:

name: Build app and deploy to Tencent
on:
    #监听push操作
    push:
        branches:
            # master 分支,也可以改成其他分支
            - master
jobs:
    # 任务ID
    build:
        # 运行环境
        runs-on: ubuntu-latest
        # 步骤
        steps:
            # 使用别人的action
            - uses: actions/checkout@v2
            # 步骤名称
            - name: Install and Build
              # 步骤执行指令
              run: |
                  yarn install
                  yarn run build
            # 上传文件
            - name: Upload to server
              uses: appleboy/scp-action@master
              with:
                  host: ${{ secrets.HOST }}
                  username: ${{ secrets.NAME }}
                  port: ${{ secrets.PORT }}
                  key: ${{ secrets.KEY }}
                  source: './dist/main.js,.env.prod,pm2.config.json'
                  target: '/usr/share/nginx/api'
            # 运行服务
            - name: Deploy to server
              uses: appleboy/ssh-action@master
              with:
                  host: ${{ secrets.HOST }}
                  username: ${{ secrets.NAME }}
                  port: ${{ secrets.PORT }}
                  key: ${{ secrets.KEY }}
                  script: |
                    cd /usr/share/nginx/api
                    mv pm2.config.json ./dist
                    pm2 reload pm2.config.json

在上面的 yml 配置中,我们主要关注的点只有两个,首先是文件的打包和上传,我们可以看到我们执行了 nameInstall and Build 的命令,在这个命令中,实现了 installbuild,然后我们通过 appleboy/scp-action@master 这个包来执行代码的上传,需要注意的是,我们要配置你需要上传服务器的ip地址,也就是 host,其次是服务器的用户名username,以及上传的端口,一般默认是22,最后是上传需要的ssh key,大家可以搜一下本地如何生成 ssh key,至于如何部署到服务器,这就需要另外的文章来介绍了,这里不做讲解,最后我们找到需要上传的文件,放在 source 属性后面,而 target 则是我们上传到服务器中的文件地址。

至此打包上传已经完成了,但是光有这些还不够,因为我们还需要让项目跑起来,并且下次检测到新的代码发布时能够自动更新代码并重启服务,这就需要用到我们接下来的内容了。

在上述代码中,我们最后还定义了一个 nameDeploy to server 的任务,它主要就是让我们的代码能够自动运行,而使用到的包是 appleboy/ssh-action@master,前面的几个配置与打包上传的类似,唯一需要注意的就是最后的 script 了,它主要是做一些 sheel 操作,我们注意到最后执行了 pm2 reload pm2.config.json 命令,这条命令就是使用 pm2 来让当前的 node 进程重新加载,我们还需要看一下 pm2.config.json 中的内容,代码如下:

{
    "apps": [
        {
            "name": "winner",
            "script": "main.js",
            "env": {
                "NODE_ENV": "production"
            }
        }
    ]
}

pm2 是一个在服务端帮我们运行 nodejs 代码的一个库,它可以有效的帮我们保持项目的稳定,而上述的 pm2.config.json 配置文件中的 script 则是代表当前要执行的代码是哪个文件,添加 env 是环境代码,表示当前为生产环境,最后当代码通过 Github Actions 自动执行打包并上传完成后,通过 sheel 命令就可以完成代码的重新部署,我们可以看一下打包的相关截图,如下所示:

image.png

由于项目是私有项目,不能对外公开,因此无法展示完整的代码。

总结

这次基于这个项目,让我体验了从前端到后端以及到运维的全部过程,包括了如何配置一个Linux服务器,如何搭建自动CI/CD,如何使用Nginx实现反向代理的全过程,虽然在开发的过程中遇到了很多问题,但是好在可以及时通过谷歌查询到相关的内容,从而及时的解决自己的问题,并在开发的过程也学到了很多新的东西。

最后,作为一个程序员,我们不应该将自己局限于前端、后端或某一个特定的岗位,只有对整个开发流程都有一个认识,才能更好的应对后续的工作变换,哪怕你后续不需要做后端或运维的工作,但是你最起码了解他们的运行原理,这样不管是开发也好,沟通也好,都能够对我们的工作产生极大的帮助。

如果这篇文章有帮助到你,❤️关注+点赞❤️鼓励一下作者,谢谢大家

本文正在参加「金石计划 . 瓜分6万现金大奖」

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容