ローカルで通るのに CI で npm ci が落ちる時は、 .npmrc もチェックする

ローカルで npm ci が通るのにGitHub に push すると Cloudflare のビルド落ちる。ログを見ると、「Missing from lock file」出てくるのですが、ローカルも CI も同じ pa […]

広告ここから
広告ここまで

目次

    ローカルで npm ci が通るのにGitHub に push すると Cloudflare のビルド落ちる。ログを見ると、「Missing from lock file」出てくるのですが、ローカルも CI も同じ package-lock.json を使っています。コードも同じ、ロックファイルも同じ、それなのになぜ結果が違うのでしょうか。

    このような場面に遭遇したので、簡単にまとめました。

    エラーの正体

    Cloudflare のビルドログには、こう書かれていました。

    npm error `npm ci` can only install packages when your package.json 
    and package-lock.json or npm-shrinkwrap.json are in sync.
    
    npm error Missing: webpack@5.105.2 from lock file
    npm error Missing: @types/eslint-scope@3.7.7 from lock file
    

    npm ci は、package-lock.json を厳密に検証します。package.json と package-lock.json に不一致があれば、エラーで止まります。それが npm ci の仕事です。

    しかし、ローカルでは同じコマンドが成功しています。同じ package-lock.json を使っているのに、ローカルと CI で結果が違います。

    環境の違いを調べるために、ローカルの npm 設定を確認しました。

    $ npm config list
    ; "user" config from /Users/sandbox/.npmrc
    
    //registry.npmjs.org/:_authToken = (protected)
    init-author-name = "hideokamoto"
    legacy-peer-deps = true
    
    ; node version = v22.13.0
    ; npm version = 10.9.2
    

    legacy-peer-deps = true が設定されています。これが問題の原因でした。

    .npmrc は npm の設定ファイルで、グローバル(ユーザーレベル)とプロジェクトレベルの両方に配置できます。グローバルの ~/.npmrc に設定した内容は、すべてのプロジェクトに影響します。

    私のローカル環境では、過去のどこかで legacy-peer-deps = true をグローバルに設定していました。そしてそれを忘れていたために、ローカルとビルドで環境差が発生していたということです。

    グローバル or プロジェクトで .npmrcを調整する

    原因がわかったので、あとは設定を揃えるだけです。グローバルで設定してもいいのですが、プロジェクトルートに .npmrc を作成する形でも対応できます。

    $ echo "legacy-peer-deps=false" > .npmrc

    あとはnode_modules を削除して、npm ci を実行してみましょう。

    $ rm -rf node_modules
    $ npm ci
    npm error code EUSAGE
    npm error Missing: webpack@5.105.2 from lock file
    npm error Missing: @types/eslint-scope@3.7.7 from lock file
    

    CI と同じエラーが出ました。

    プロジェクトレベルの .npmrc は、ユーザーレベル(グローバル)の設定を上書きします。legacy-peer-deps=false を明示することで、グローバル設定の影響を排除し、CI と同じ条件をローカルで再現できました。

    問題が再現できれば、あとは解決するだけです。

    まとめ

    グローバルの .npmrc は便利です。すべてのプロジェクトに適用される設定を一箇所で管理できます。しかし、それは予期しない動作の違いを引き起こす可能性があります。そして何より厄介なのが、「なんでそういう設定にしたかを思い出せないこと」です。

    念の為PJ単位での設定として対応しましたが、将来的にはCIと同じようになるよう調整したいところです。

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark