👋

npm ci を yarn, pnpm ではどうやるのか

2024/12/28に公開

TL;DR

パッケージマネージャー コマンド
npm npm ci
yarn yarn install --frozen-lockfile
pnpm pnpm i --frozen-lockfile

npm ci とは

ci とは clean install の略です。
npm ipackage.json を基にしてパッケージをインストールしますが、npm cipackage-lock.json のバージョンを基にインストールをします。
他にも以下のような特徴があります。

  • package.jsonpackage-lock.json で異なる依存関係がある場合は失敗する
    • npm ipackage-lock.json を更新する
  • node_modules ディレクトリを削除してからパッケージをインストールする

そのため、CI(Continuous Integration)環境や環境構築の時は npm ci を使う方がバージョン差異が起きない便利コマンドとなっています。

これを他のパッケージマネージャーではどうするのか?

yarn

If yarn.lock is present and is enough to satisfy all the dependencies listed in package.json, the exact versions recorded in yarn.lock are installed, and yarn.lock will be unchanged. Yarn will not check for newer versions.

公式ドキュメントを読むと yarn.lock が存在する場合は yarn.lock のバージョンを基にパッケージをインストールします。

ただ、package.jsonyarn.lock の依存関係で差分がある場合 yarn install だと yarn.lock を更新します。
npm ci だとエラーになるのでこの挙動も同じにするためには --frozen-lockfile をつける必要があります。

pnpm

pnpm も yarn と同様に install コマンドで pnpm-lock.yaml を基にパッケージをインストールします。
ローカル環境の時に npm ci と同じ挙動にするためには --frozen-lockfile が必要ですが、CI 環境ではデフォルトで ON になっているので明示的に指定する必要はないです。

ローカル環境か CI 環境かの判断は以下のようにしています。

exports.isCI = !!(
  env.CI || // Travis CI, CircleCI, Cirrus CI, GitLab CI, Appveyor, CodeShip, dsari
  env.CONTINUOUS_INTEGRATION || // Travis CI, Cirrus CI
  env.BUILD_NUMBER || // Jenkins, TeamCity
  env.RUN_ID || // TaskCluster, dsari
  exports.name ||
  false
)

参考

Discussion