pnpm fetch
パッケージマニフェストを無視して、ロックファイルから取得したパッケージを仮想ストアに記録します。
使用シナリオ
このコマンドは、特に docker イメージのビルドを改善するために設計されました。
You may have read the official guide to writing a Dockerfile for a Node.js app, if you haven't read it yet, you may want to read it first.
私たちが公式ガイドを参考にして学んだ、pnpmを使用するプロジェクトに最適化したDockerfileは次のとおりです。
FROM node:20
WORKDIR /path/to/somewhere
RUN corepack enable pnpm && corepack install -g pnpm@latest-10
# Files required by pnpm install
COPY .npmrc package.json pnpm-lock.yaml pnpm-workspace.yaml .pnpmfile.cjs ./
# If you patched any package, include patches before install too
COPY patches patches
RUN pnpm install --frozen-lockfile --prod
# Bundle app source
COPY . .
EXPOSE 8080
CMD [ "node", "server.js" ]
As long as there are no changes to .npmrc
, package.json
, pnpm-lock.yaml
, pnpm-workspace.yaml
, .pnpmfile.cjs
, docker build cache is still valid up to the layer of RUN pnpm install --frozen-lockfile --prod
, which cost most of the time when building a docker image.
しかし、package.json
には依存関係以外にバージョン番号やスクリプト、さまざまなツールの設定情報などが含まれるので、私たちが意図したよりずっと頻繁に変更されるかもしれません。
また、モノリポのプロジェクトをビルドするDockerfileを保守するのは大変です。例えば次のようになっているでしょう。
FROM node:20
WORKDIR /path/to/somewhere
RUN corepack enable pnpm && corepack install -g pnpm@latest-10
# Files required by pnpm install
COPY .npmrc package.json pnpm-lock.yaml pnpm-workspace.yaml .pnpmfile.cjs ./
# If you patched any package, include patches before install too
COPY patches patches
# for each sub-package, we have to add one extra step to copy its manifest
# to the right place, as docker have no way to filter out only package.json with
# single instruction
COPY packages/foo/package.json packages/foo/
COPY packages/bar/package.json packages/bar/
RUN pnpm install --frozen-lockfile --prod
# Bundle app source
COPY . .
EXPOSE 8080
CMD [ "node", "server.js" ]
サブパッケージを追加したり削除したりするとき、Dockerfileも変更しなければなりません。
pnpm fetch
solves the above problem perfectly by providing the ability to load packages into the virtual store using only information from a lockfile and a configuration file (pnpm-workspace.yaml
).
FROM node:20
WORKDIR /path/to/somewhere
RUN corepack enable pnpm && corepack install -g pnpm@latest-10
# pnpm fetch does require only lockfile
COPY pnpm-lock.yaml pnpm-workspace.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
は大幅に時間を節約できるでしょう。
引数
--dev, -D
開発パッケージだけを取得します。
--prod, -P
開発パッケージを取得しません。