pnpm fetch
Завантажити пакунки з файлу блокування у віртуальне сховище, маніфест пакунків ігнорується. A missing package manifest is not created.
pnpm fetch requires pnpm-lock.yaml and does not update it. When the project pins a pnpm version that commands would switch to, pnpm fetch also downloads that pnpm into the store, so a later pnpm install --offline finds it.
Сценарій використання#
Ця команда спеціально розроблена для покращення створення образів docker.
A typical Dockerfile for a project using pnpm looks like this (see also Working with Docker):
FROM ghcr.io/pnpm/pnpm:12
RUN pnpm runtime set node 22 -g
WORKDIR /app
# Files required by pnpm install. Leave out .pnpmfile.mjs if the project has none,
# because COPY fails on a missing source.
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .pnpmfile.mjs ./
# 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 package.json, pnpm-lock.yaml, pnpm-workspace.yaml,
.pnpmfile.mjs, 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 ghcr.io/pnpm/pnpm:12
RUN pnpm runtime set node 22 -g
WORKDIR /app
# Files required by pnpm install. Leave out .pnpmfile.mjs if the project has none,
# because COPY fails on a missing source.
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .pnpmfile.mjs ./
# 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 чудово розвʼязує вищезгадану проблему, надаючи можливість завантажувати пакунки до віртуального сховища, використовуючи лише інформацію з файлу блокування та конфігураційного файлу (pnpm-workspace.yaml).
FROM ghcr.io/pnpm/pnpm:12
RUN pnpm runtime set node 22 -g
WORKDIR /app
# 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
COPY . ./
RUN pnpm install -r --offline --prod
EXPOSE 8080
CMD [ "node", "server.js" ]
Це працює для простих проєктів і монорепозиторіїв, --offline змусить pnpm не спілкуватись з реєстром пакунків, бо усі потрібні пакунки вже присутні в віртуальному сховищі.
Поки файл блокування не змінено, кеш збірки чинний, тому RUN pnpm install -r --offline --prod, збереже багато часу.
нотатка
Локальні залежності протоколу file: пропускаються під час pnpm fetch, оскільки вони посилаються на теки, які можуть бути недоступними під час завантаження (наприклад, у збірках Docker).
Параметри#
--dev, -D#
Будуть завантажені лише пакунки для розробки
--prod, --production, -P#
Пакунки для розробки не будуть завантажені
--ignore-pnpmfile#
Don't run the hooks of the pnpmfile.