[英]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
andnpm ci
are:简而言之,使用
npm install
和npm ci
的主要区别是:
- The project must have an existing
package-lock.json
ornpm-shrinkwrap.json
.该项目必须具有现有的
package-lock.json
或npm-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 beforenpm ci
begins its install.如果
node_modules
已经存在,它将在npm ci
开始安装之前自动删除。- It will never write to
package.json
or any of thepackage-locks
: installs are essentially frozen.它永远不会写入
package.json
或任何package-locks
:安装基本上被冻结。
Some tests having ~/.npm
and node_modules
populated:填充了
~/.npm
和node_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.