简体   繁体   English

在 GitLab CI/CD 中缓存 Node.js 依赖项的便捷方式

[英]Convenient way to cache Node.js dependencies in GitLab CI/CD

I'm using npm to install Node.js dependencies in my project.我正在使用npm在我的项目中安装 Node.js 依赖项。 I want to cache Node.js packages ( node_modules ) globally to speed up jobs in pipelines when deploying to Heroku. An example from the official docs of GitLab:我想在全局缓存 Node.js 包( node_modules )以在部署到 Heroku 时加速管道中的作业。来自 GitLab 官方文档的示例:

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
  - .npm/

before_script:
  - npm ci --cache .npm --prefer-offline

And here is another example in GitLab:这是 GitLab 中的另一个示例

cache:
  paths:
    - node_modules/

Found some articles ( Deploy Node.js App with GitLab CI/CD , Continuous Integration with Node.js, Heroku and GitLab CI/CD -Part 2 ) that used the second configuration above.找到一些使用上述第二个配置的文章( 使用 GitLab CI/CD 部署 Node.js 应用程序,使用 Node.js、Heroku 和 GitLab CI/CD 持续集成 - 第 2 部分)。 I did give it a shot and I was able to deploy my app to Heroku with these settings successfully.我确实尝试了一下,并且能够使用这些设置成功地将我的应用程序部署到 Heroku。 But I'm not sure caching mechanism is working properly.但我不确定缓存机制是否正常工作。

What is the difference between these configurations?这些配置之间有什么区别? Which one is the most convenient way to cache Node.js packages?缓存 Node.js 包最方便的方法是哪一种?

My current setup for gitlab-ci.yml file:我当前的gitlab-ci.yml文件设置:

image: node:latest

cache:
  paths:
    - node_modules/

stages:
  - build
  - deploy

build:
  stage: build
  script:
    - npm i
    - npm i -g gulp-cli
    - gulp build

deploy:
  image: ruby:latest
  stage: deploy
  script:
    - apt-get update -qy
    - apt-get install -y ruby-dev
    - gem install dpl
    - dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_API_KEY
  only:
    - master

Not sure if I'm doing it the right way.不确定我是否以正确的方式进行操作。

It depends if you want to use npm install , aka npm i , or if you want to use npm ci .这取决于您是要使用npm install ,又名npm i ,还是要使用npm ci

npm install will look first for an existent node_modules folder and will re-use it. npm install将首先查找现有的node_modules文件夹并将重新使用它。 If not, will fetch the dependencies.如果没有,将获取依赖项。 Check the full algorithm .检查完整的算法

npm ci instead, removes an existing node_modules folder to perform a clean install of the dependencies. npm ci而是删除现有的node_modules文件夹以执行依赖项的全新安装。 From the docs :文档

In short, the main differences between using npm install and npm ci are:简而言之,使用npm installnpm ci的主要区别是:

  • The project must have an existing package-lock.json or npm-shrinkwrap.json .该项目必须具有现有的package-lock.jsonnpm-shrinkwrap.json shrinkwrap.json 。
  • If dependencies in the package lock do not match those in package.json, npm ci will exit with an error, instead of updating the package lock. If dependencies in the package lock do not match those in package.json, npm ci will exit with an error, instead of updating the package lock.
  • npm ci can only install entire projects at a time: individual dependencies cannot be added with this command. npm ci一次只能安装整个项目:无法使用此命令添加单个依赖项。
  • If a node_modules is already present, it will be automatically removed before npm ci begins its install.如果node_modules已经存在,它将在npm ci开始安装之前自动删除。
  • It will never write to package.json or any of the package-locks : installs are essentially frozen.它永远不会写入package.json或任何package-locks :安装基本上被冻结。

Some tests having ~/.npm and node_modules populated:填充了~/.npmnode_modules的一些测试:

$ npm i --prefer-offline
#...
updated 2 packages in 17.472s

$ rm -rf ~/.npm/ # removes global npm cache
$ npm i --prefer-offline
#...
up to date in 16.271s # removing npm cache does not affects to npm i

$ rm -rf node_modules/
$ npm i --prefer-offline
#...
added 2525 packages from 1197 contributors in 55.388s # removing node_modules affetcs to npm i
$ npm ci --prefer-offline
#...
updated 2 packages in 17.201s

$ rm -rf ~/.npm/ # removes global npm cache
$ npm ci --prefer-offline
#...
added 2532 packages in 48.362s # removing npm cache affects to npm ci

$ rm -rf node_modules/
$ npm ci --prefer-offline
#...
added 2532 packages in 18.695s # removing node_modules does not affetcs to npm ci

So ending up, npm ci has CI oriented features which can be interesting to use with but if there are no benefits for you just cache node_modules and use npm install instead.最后, npm ci具有面向 CI 的功能,使用起来可能很有趣,但如果对您没有好处,只需缓存node_modules并使用npm install代替。

You should be using npm ci over npm install regardless of the solution you choose.无论您选择哪种解决方案,您都应该使用npm ci而不是npm install

In the GitLab recommended approach: GitLab中推荐的做法:

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
  - .npm/

before_script:
  - npm ci --cache .npm --prefer-offline

You are caching all of the files that npm needs to install your project (and effectively create node_modules).您正在缓存 npm 安装项目(并有效创建 node_modules)所需的所有文件。 Subsequent jobs will run before_script ( npm ci ) and re-generate node_modules from the cache.后续作业将运行 before_script ( npm ci ) 并从缓存中重新生成 node_modules。 This will be fast if the cache exists.如果缓存存在,这将很快。

The main advantage of this method is resilience.这种方法的主要优点是弹性。 The cache is truly optional.缓存确实是可选的。 If it doesn't download properly or doesn't exist because of some TTL (maybe you are re-running a job), your pipeline stage using npm ci will fetch all the necessary files from the inte.net.如果由于某些 TTL 而无法正确下载或不存在(也许您正在重新运行作业),则使用npm ci的管道阶段将从 inte.net 获取所有必要的文件。 The operative argument is --prefer-offline操作参数是--prefer-offline

You can code up a way to be resilient using the latter approach, but it'd be more complicated.您可以使用后一种方法编写一种具有弹性的方法,但它会更复杂。

EDIT To amend my answer.编辑修改我的答案。 I suspect the latter approach is faster, as you don't need to rebuild node_modules/ with each stage.我怀疑后一种方法更快,因为您不需要在每个阶段都重建 node_modules/ 。 Although I haven't verified this.虽然我没有证实这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM