pnpm fetch
パッケージマニフェストを無視して、ロックファイルから取得したパッケージを仮想ストアに記録します。
使用シナリオ
このコマンドは、特に docker イメージのビルドを改善するために設計されました。
Node.jsアプリケーションのDockerfileの書き方に関する公式ガイドを読んだことがなければ、先に読んでおいたほうがいいでしょう。
私たちが公式ガイドを参考にして学んだ、pnpmを使用するプロジェクトに最適化したDockerfileは次のとおりです。
FROM node:14
RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
# pnpm installに必要なファイル
COPY .npmrc package.json pnpm-lock.yaml .pnpmfile.cjs ./
# パッケージにパッチを当てた場合は、インストール前にパッチも含める
COPY patches patches
RUN pnpm install --frozen-lockfile --prod
# アプリケーションのソースをバンドルする
COPY . .
EXPOSE 8080
CMD [ "node", "server.js" ]
.npmrc
、package.json
、pnpm-lock.yaml
、.pnpmfile.cjs
のいずれかを変更しない限り、RUN pnpm install --frozen-lock-file --prod
のレイヤーに関するビルドキャッシュは常に有効です。これは、dockerイメージをビルドするとき、最も時間のかかるレイヤーです。
しかし、package.json
には依存関係以外にバージョン番号やスクリプト、さまざまなツールの設定情報などが含まれるので、私たちが意図したよりずっと頻繁に変更されるかもしれません。
また、モノリポのプロジェクトをビルドするDockerfileを保守するのは大変です。例えば次のようになっているでしょう。
FROM node:14
RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
# pnpm installに必要なファイル
COPY .npmrc package.json pnpm-lock.yaml .pnpmfile.cjs ./
# パッケージにパッチを当てた場合は、インストール前にパッチも含める
COPY patches patches
# 各サブパッケージに対して、マニフェストを正しい場所にコピーする追加のステップが必要となります
# それは、Dockerは単一の指示でpackage.jsonのみをフィルタリングする方法がないためです
COPY packages/foo/package.json packages/foo/
COPY packages/bar/package.json packages/bar/
RUN pnpm install --frozen-lockfile --prod
# アプリケーションのソースをバンドルする
COPY . .
EXPOSE 8080
CMD [ "node", "server.js" ]
サブパッケージを追加したり削除したりするとき、Dockerfileも変更しなければなりません。
pnpm fetch
はそういった問題を完全に解決します。ロックファイルの情報だけを頼りにパッケージをロードして、仮想ストア格納するからです。
FROM node:14
RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
# pnpm fetch does require only lockfile
COPY pnpm-lock.yaml ./
# If you patched any package, include patches before running pnpm fetch
COPY patches patches
RUN pnpm fetch --prod
ADD . ./
RUN pnpm install -r --offline --prod
EXPOSE 8080
CMD [ "node", "server.js" ]
単純なプロジェクトとモノリポのプロジェクトのどちらでも上手く機能します。必要な依存対象は全て仮想ストアに格納されているので、--offline
フラグを指定してpnpmが外部のパッケージレジストリへ通信しないようにします。
ロックファイルを変更しない限り、そのレイヤーに関するビルドキャッシュは有効のため、RUN pnpm install -r --offline --prod
は大幅に時間を節約できるでしょう。
Options
--dev
開発パッケージだけを取得します。
--prod
開発パッケージを取得しません。