GitLab CI: The cached node_modules are not being recognized by npm

Many users online are discussing issues with Gitlab caching, but in my experience, Gitlab CI actually caches correctly. However, npm seems to reinstall everything regardless.

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - vendor/
    - bootstrap/
    - node_modules/

build-dependencies:
  image: ...
  stage: build
  script:
  - cp .env.gitlab-testing .env
  - composer install --no-progress --no-interaction
  - php artisan key:generate
  - npm install
  - npm run prod
  - npm run prod
  artifacts:
    paths:
    - vendor/
    - bootstrap/
    - node_modules/
    - .env
    - public/mix-manifest.json
  tags:
  - docker

This is an excerpt from my gitlab-ci.yml file that I'm struggling with. Even though the composer dependencies are being cached and used properly, the node_modules aren't. I've tried adding everything to cache and artifacts out of desperation as well.

Answer №1

Latest Answer (Dec 2, 2023, GitLab@^15.12 & >13)

In response to valuable feedback, the original approach of using artifacts for caching in GitLab has been revisited and improved upon. With updated documentation from GitLab regarding the use of cache, including support for multiple cache keys per job (up to 4), a more efficient method for managing node_modules across pipelines has emerged.

The strategy behind this implementation is grounded in a thorough understanding of both GitLab's functionality and the behavior of npm. Here are the key principles:

  1. NPM advises the utilization of npm ci over npm install in CI/CD environments. It requires the presence of package-lock.json to ensure package versions remain consistent across builds (npm i lacks this determinism).

  2. npm ci clears the node_modules directory before reinstalling packages listed in package-lock.json. Therefore, it's best to run npm ci once in GitLab and share the resulting node_modules with subsequent jobs.

  3. NPM maintains its own cache at ~/.npm/ for offline builds and speed optimization. The cache location can be customized using the --cache <dir> option.

  4. GitLab cannot cache directories outside the repository, such as the default cache directory ~/.npm.

  5. GitLab's global cache configuration is applied to every job by default, requiring explicit overrides when necessary. YAML anchors can be used to copy and modify the global cache config.

  6. To execute additional npx or npm run <script> commands without reinstallation, caching the node_modules/ folders across the pipeline is recommended.

  7. GitLab encourages utilizing the cache feature for handling dependencies and restricting the use of artifacts to dynamically generated build results. This revised approach aligns better with GitLab's guidelines, acknowledging artifact size restrictions and storage usage quotas.

  8. The use of needs or dependencies affects automatic download or deletion of artifacts between jobs.

  9. GitLab's cache monitors file hash values, updating only when package-lock.json changes. Using package.json would compromise build determinism.

  10. If dealing with multiple packages in a mono-repo, the cache entry limit during the install job might pose challenges. Combining cache definitions and careful key management can address this limitation effectively.

  11. GitLab's cache list order influences cache matching between jobs. Attention must be given to the order of cache entries to ensure proper functioning across stages.

Optimized Solution

  • Execute a single install job as the .pre stage, leveraging cached downloaded packages across the entire repository.
  • Cache all node_modules/ folders for subsequent jobs within the same pipeline execution, preventing unnecessary uploads and streamlining pipeline runtime.
  • Pass the build/ directory via artifacts only when required by other jobs.
# .gitlab-ci.yml

stages:
  - build
  - test
  - deploy

# Global cache settings for all jobs
cache:
    - &global_cache_node_mods
      key:
          files:
              - package-lock.json
      paths:
          - node_modules/
      policy: pull

install:
  image: ...
  stage: .pre
  cache:
    - <<: *global_cache_node_mods
       policy: pull-push

    - key: ${CI_JOB_NAME}
       paths:
         - .npm/
       policy: pull-push

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

build:
  stage: build
  script:
    - npm run build
  artifacts:
    paths:
      - dist/

test:
  stage: test
  needs:
    - job: build
      artifacts: true
  script:
    - npm test

deploy:
  stage: deploy
  when: on_success
  cache: {}
  needs:
    - job: build
      artifacts: true
    - job: test
      artifacts: false
  script:
    - npm publish

Refer to GitLab's documentation for detailed recommendations on caching npm.


[DEPRECATED] Original Approach (Oct 27, 2021, GitLab<13.12)

Prior attempts at caching with npm & GitLab lacked completeness in achieving effective caching strategies.

To realize comprehensive caching with npm & GitLab, consider the following points:

  1. Refer to point #1 above for context.

  2. When using npm ci, clearing the node_modules directory ensures a clean slate for subsequent installations based on package-lock.json. Caching node_modules between build jobs in GitLab becomes redundant under this scenario.

  3. Explore insights outlined in points #3-#4.

  4. Global cache downloads in multiple stages may not align with desired outcomes.

  5. For running additional npx commands without re-installation, transferring the node_modules/ folder as an artifact to other jobs proves beneficial.

[DEPRECATED] Initial Solution

  • Initiate a single install job as the .pre stage, harnessing cached downloaded packages (tar.gz's) across the entire repository.
  • Share node_modules and the build directory with other jobs only when necessary.

stages:
  - build
  - test
  - deploy

install:
  image: ...
  stage: .pre 
  cache:
    key: NPM_DOWNLOAD_CACHE  
    paths:
      - .npm/
  before_script:
    - cp .env.gitlab-testing .env
    - composer install --no-progress --no-interaction
    - php artisan key:generate
  script:
    - npm ci --cache .npm --prefer-offline
  artifacts:
    paths:
    - vendor/
    - bootstrap/
    - node_modules/
    - .env
    - public/mix-manifest.json

build:
  stage: build
  needs:
    - job: install         
      artifacts: true       
  script:
    - npm run build
  artifacts:
    paths:
      - dist/               

test:
  stage: test
  needs:
    - job: install
      artifacts: true      
    - job: build
      artifacts: true      
  script:
    - npm test

deploy:
  stage: deploy
  needs:
    - job: build
      artifacts: true      
    - job: test            
      artifacts: false     
  script:
    - npm publish

Answer №2

It appears that the cache settings are functioning correctly in this scenario. The global cache is being utilized and the key is specific to the current branch ${CI_COMMIT_REF_SLUG}...

This particular build process showcases successful caching of the node_modules directory across different stages.

image: node:latest

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
  - node_modules/
  - .next/

stages:
  - install
  - test
  - build
  - deploy

install_dependencies:
  stage: install
  script:
    - npm install

test:
  stage: test
  script:
    - npm run test

build:
  stage: build
  script:
    - npm run build

Answer №3

Dealing with a similar issue, I discovered that the problem stemmed from my cache settings. By default, the cache does not retain unversioned git files, and since we don't store node_modules in git, the npm files were not being cached at all. To resolve this, I simply added one line "untracked: true" as shown below:

cache:
  untracked: true
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - vendor/
    - bootstrap/
    - node_modules/

After making this adjustment, npm now runs faster. However, there is still a delay while it checks for changes. To further optimize the process, I am considering implementing a specific job to handle npm install tasks, which has already significantly improved efficiency.

Answer №4

By default, the cache path is located at ~/.npm

If you wish to change the npm cache directory:

npm config set cache <path> --global

For additional details, please refer to this resource

Answer №5

Utilizing GitLab, NPM/Yarn Cache, and React Firebase Hosting

stages:
  - test
  - build
  - deploy

default:
  image: node:21
  cache: # Storing modules for later use
    key:
      files:
        - yarn.lock
    paths:
      - node_modules/

##########################
# Firebase Preview Links #
##########################
preview_deploy:
  stage: test
  image: node:21
  
  rules: 
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event' && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop")
    
  before_script:
    - npm install -g firebase-tools
    
  script:
    - yarn install --immutable --immutable-cache
    - yarn build
    - |
      echo "{\"commit\": \"https://gitlab.com/ORG/REPO/-/commit/${CI_COMMIT_SHA}\", \"ref\": \"${CI_COMMIT_REF_NAME}\", \"job\": \"https://gitlab.com/ORG/REPO/-/jobs/${CI_JOB_ID}\"}" > dist/build.json
    - firebase --project "${FIREBASE_PROJECT_ID}" --token "${FIREBASE_TOKEN}" hosting:channel:deploy "${CI_COMMIT_SHA}"
  
  environment:
    name: preview-staging

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountering NPM issues while trying to install zombie version 4.2.1 on Centos 6.7 platform

Currently, I am utilizing a vagrant box with the bento/centos-6.7 image. The versions of node and npm on this setup are v6.9.1 and 3.10.8, respectively. Upon executing npm install <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail=" ...

error encountered in local npm package installation

A necessary dependency was added to the package.json file: "user": "file:./server/models/user" Within the user file, there is a function exported as module.exports = function() {...} npm ERR! addLocal Could not install /home/WebstormProjects/project/ser ...

npm installation raises concerns about unmet peer dependencies despite them being already satisfied

I recently completed an upgrade to the final release of angular 2 from rc-6. Transitioning through different beta/rc versions was smooth and without any complications. My package.json dependencies include: "dependencies": { "@angular/common": "2.0.0" ...

npm lacks compatibility with the Node.js version 12.18.3

Despite multiple attempts, I haven't been able to find a solution for my issue. On my Windows 10 PC, I have installed Node.js version 12.18.3 and when trying to install a package using npm, I noticed that the npm version returned with npm -v is outda ...

The webpack-concat-text-plugin "node" is not compatible

The concat-text-webpack-plugin is located deep within a package, and it throws errors when I have NextJS and Node 18. Error: The engine "node" is incompatible with this module. Expected version ">=8 <=16". Got "18.16.0" Error Found incompatible modul ...

Error occurs when running npm install command in Grunt task using Node.js child_process spawn function

Having an issue with a custom Grunt task I'm working on. My goal is to run npm install, then bower install, followed by a grunt hub target for multiple sub-projects. The problem arises when using child_process. If I uncomment the npm install spawn co ...

Angular 2 - Unable to access the AssetUrl property due to undefined value

Just getting started with angular2 and material-design. Attempting to integrate the two. I decided to clone this material2-app, which is built on angular2 and material2 and ran npm install. However, when I tried running npm start to start a server, I enc ...

unable to process the build compilation

Can you help me figure out what's wrong? I used the create-react-app command to build this project. Here is the content of my package.json file: "name": "front", "version": "1.0.0", "private": true, "proxy": "http://127.0.0.1:8000", "dependencies": { ...

Oh no, my hardhat, truffle, brownie, and react tools have suddenly gone on strike! The command has failed with an exit

While experimenting with brownies on my first useDapp app, everything seemed to be running smoothly and it was a lot of fun. However, when I decided to delve into truffle by installing it through npm, I encountered numerous warnings and the functionality d ...

Is it possible to update a file in a Bitbucket repository using Azure DevOps release pipeline?

I have a npm source code that requires building and pushing to the npmjs repository. Here are the details of the process: Build pipeline: 1) Fetch sources from Bitbucket repository 2) Retrieve the version number from package.json (e.g., 0.0.3), increase ...

The autocomplete feature is not displaying the suggested text at the top when choosing data

Recently started using react native and I'm currently working on implementing an AutoCompleteTextView. I have a json file that contains country names which need to be displayed in the autocomplete view. Although I am able to display the names of all c ...

Unable to locate module named "Gulp"

When attempting to run npm start, I encounter the following error message: module.js:545 throw err; ^ Error: Cannot find module './Gulp' at Function.Module._resolveFilename (module.js:543:15) at Function.Module._load (module.js:470:25) at Modul ...

Ways to resolve the recurring npm ERR! code that appears whenever I enter npm start in the terminal

As I work on creating an application in React, I encountered an issue when trying to run "npm start" in the command line. The error message I received is shown below: npm ERR! code ENOENT npm ERR! syscall open npm ERR! path /Users/a1234/Downloads/meditati ...

Exploring the differences between npm audit fix and npm install

I am confused about how npm audit fix actually works. According to the information provided in the documentation: npm audit fix essentially performs a comprehensive npm install operation behind the scenes. However, I find it puzzling that when vulnerabi ...

Setting Environment Variables using a .ps1 Script

I'm currently exploring a Node.js project and looking to streamline the process of configuring environment variables. I've crafted a script (set_env.ps1) that resembles the following: Write-Host "Setting up environment variables..."; $env:CLIENT ...

Hey there! I recently developed a Quasar App Website, but I'm having trouble pushing it to Heroku. When attempting to do so, I encountered a "Push

While attempting to push my git to Heroku, I encountered an error at the final stage. Upon inspecting the console during project deployment, I realized that warnings are not necessarily catastrophic for app crashing. However, a critical error message caugh ...

The previous method of using `vue/compiler-sfc ::v-deep` as a combinator has been phased out. Instead, opt for the new syntax `:deep(<

When developing with Nuxt 2, I am encountering numerous [@vue/compiler-sfc] ::v-deep usage as a combinator has been deprecated. Use :deep(<inner-selector>) instead. errors when running npm run dev. After attempting to resolve the issue by changing a ...

encountering difficulties while installing node-sass using npm

As I work on creating a local environment for PrestaShop, I am facing an issue during the npm installation process. There seems to be an error occurring when trying to install node-sass. Can someone provide guidance on resolving this issue? ...

Using Sequelize to retrieve data from a relationship where a model belongs to another

Currently, I am developing an application that utilizes an existing MySQL database. Although I am able to successfully retrieve values from the tables, I encounter issues when trying to fetch data from associated models. The Purchase Order model: "use st ...

I encountered an npm start error while trying to run my React JS application in VS Code

Hey everyone, I could really use some help. I've finished all the coding part of my project but when I try npm start at the end, I keep getting errors. Error: npm ERR! code ENOENT npm ERR! syscall open npm ERR! path C:\Users\yateesh\D ...