Recommended node install: npm ci vs npm install?

I am setting up my first Github action, and I have a question regarding npm ci vs npm install. My objective is the fastest possible execution time :sunglasses:

So I have found the cache action actions/cache@v1, and now I have added this section to my workflow:

- name: Cache node modules
      uses: actions/cache@v1
      with:
        path: node_modules
        key: ${{ runner.OS }}-build-${{ hashFiles('**/package-lock.json') }}
        restore-keys: |
          ${{ runner.OS }}-build-${{ env.cache-name }}-
          ${{ runner.OS }}-build-
          ${{ runner.OS }}-

After doing this step, what is the recommended way to install npm packages - install or ci?

I did some tests on my own repo, and currently, my findings suggest that install is fastest. I just find it, well interesting, that the ci command is not the fastest in ci :joy:

Any comments are very welcome - and thanks for a great product.

You should not cache the node_modules folder, this was wrong in the example. See the issue here for a discussion:
https://github.com/actions/cache/issues/67
They corrected it:

I use this in combination with npm ci:

- name: Cache node modules
      uses: actions/cache@v1
      with:
        path: ~/.npm
        key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
        restore-keys: |
           ${{ runner.os }}-node-
2 Likes

Thanks for the answer. Did you benchmark it against npm i?

I didn’t do a benchmark, but just read that npm ci is the official recommended variant

“npm i” asks the registry about each module from your dependencies and then upgrades or not. “npm ci” deleted node_modules and copies them from the cache. The performance will depend on how many modules you have and how fast is your network and disk.

“npm ci” is meant for automated builds, which happen many times a day and the package lock changes as good as never. “npm i” may modify your package lock and is meant to be used when you want to add, remove or update your dependencies. Instead of looking at the perfoprmance, you could use the target scenario as the decisive criterion.

You should use “npm i” if you install dependencies from GIT URLs and you expect the latest state of the requested branch installed. They are cached and “npm ci” does not test if the branch in GIT changed or not since the last run. “npm i” always reinstall these modules.