Gitlab CI 加速Node项目编译

通过分析build日志,我们发现慢的地方三处

1. yarn install安装依赖慢

2. 缓存node_modules到gitlab和从gitlab拉取缓存的node_modules慢

3. yarn run build慢

解决问题的思路:

如果缓存node_modules会不会变快呢?我们每次执行yarn install时会从远程或从本地yarn缓存拉取依赖解压到node_modules,这个过程很慢很耗时,我们第一想到的是,如果我把node_modules缓存到gitlab每次执行CI时拉取这个node_modules,这样就会快一些,由于我们的runner节点有多个,这个node_modules要么缓存在集中缓存,要么每个节点都缓存一份,集中式缓存需要依赖像MinIO这类存储,续要单独部署,而redis我们是现成的可以直接用。当我们把node_modules缓存后发现yarn install过程虽然速度确实快了一些但还是有些慢,我们这时想到,如果我的yarn install过程不执行不就快了吗?我们通过redis记录yarn.lock的MD5值,如果当前yarn.lock的MD5值和redis存储的上次某个runner上该yarn.lock的MD5做比较,如果相等则不执行yarn install,此时直接执行的是编译步骤和cache步骤,这样确实发现缓存存在且yarn.lock文件没有变化时很快,基本就等于yarn run build 的时间,大部分时间yarn.lock基本不会变化,所以该方案凑合能解决问题。

该方案代码实例如下:
 

build:
  stage: build
  only:
    - dev
    - test
    - master
  tags:
    - nodejs
  before_script:
    - |
      REDIS_KEY=${CI_RUNNER_ID}:${CI_PROJECT_NAME}:$CI_BUILD_REF_NAME:yarn.lock
      FILE_MD5=`md5sum yarn.lock|cut -d ' ' -f1`
      REDIS_MD5=`redis-cli -h 172.16.x.x -p 6379 -a tangwan get $REDIS_KEY`
      echo "redisKey:$REDIS_KEY ;fileMD5:$FILE_MD5 ;redisMD5:$REDIS_MD5"
  script:
    - |
      if [[ "$REDIS_MD5"x != "$FILE_MD5"x ]]; then
        echo "依赖安装开始时间:$(date +'%Y-%m-%d %H:%M:%S')"
        yarn config set ignore-engines true
        yarn config set cache-folder ~/.yarn
        yarn install --prefer-offline --frozen-lockfile --mutex network --registry=https://registry.npmmirror.com
        echo "依赖安装结束时间:$(date +'%Y-%m-%d %H:%M:%S')"
      fi
      export NODE_OPTIONS=--max_old_space_size=8192
      echo "打包开始时间:$(date +'%Y-%m-%d %H:%M:%S')"
      yarn run build
      echo "打包结束时间:$(date +'%Y-%m-%d %H:%M:%S')"
      redis-cli -h 172.16.x.x -p 6379 -a tangwan set $REDIS_KEY $FILE_MD5
  artifacts:
    paths:
      - dist/
  after_script:
    - rm -rf node_modules/.cache
  cache:
    key: $CI_PROJECT_NAME_$CI_BUILD_REF_NAME
    policy: pull-push
    paths:
      - node_modules/
      - src/.umi
      - src/.umi-production

上面方案存在的问题:

yarn.lock对于依赖自己的node_modues这种需要频繁修改版本的场景不适用,绕不开yarn install步骤cache node_modules和pull cache node_modules时非常耗时,对于大一点的项目,node_modules几个G这种情况尤其明显。

继续分析,有没有办法不删除这个node_modules?当我们查看gitlab pipeline日志时发现,gitlab默认每次运行时都会先清理工作空间,删除未受版本控制的目录和文件,保持工作目录和代码库一致。而删除node_modules这一步其实也会消耗一定时间,而且我们确实不需要每次清理node_modules,使用npm ci和yarn install就会保持当前node_modules和package.json和yarn.lock文件声明的依赖一致,我们本地开发时也不见得每次都把node_modules删除后再build。所以我也不打算删除这个node_modules了。

最终的方案:

# gitlab执行git clean时的参数
variables:
  GIT_CLEAN_FLAGS: -ffdx -e node_modules/

stages:
  - build

build:
  stage: build
  only:
    - dev
    - test
    - master
  tags:
    - nodejs
  script:
    - |
      ls -al
      echo "依赖安装开始时间:$(date +'%Y-%m-%d %H:%M:%S')"
      yarn config set ignore-engines true
      yarn config set cache-folder ~/.yarn
      yarn install --prefer-offline --frozen-lockfile --mutex network --registry=https://registry.npmmirror.com
      echo "依赖安装结束时间:$(date +'%Y-%m-%d %H:%M:%S')"
      export NODE_OPTIONS=--max_old_space_size=8192
      echo "打包开始时间:$(date +'%Y-%m-%d %H:%M:%S')"
      yarn run build
      echo "打包结束时间:$(date +'%Y-%m-%d %H:%M:%S')"
  artifacts:
    paths:
      - dist/

果然,使用方式二速度就提上来了,yarn install在没修改依赖的情况下就只需要几秒,修改了依赖也只安装变更的依赖,也是秒级别完成,此方案也避免了node_modules缓存和拉取缓存的过程(压缩打包和解压)耗时问题,只剩下yarn run build耗时了,至此web项目编译慢的问题算是解决了。

参考官方文档:

Configuring runners | GitLab

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值