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.
По этому руководству мы научимся писать оптимизированный Dockerfile для проектов с помощью pnpm, который выглядит как
FROM node:20
WORKDIR /path/to/somewhere
RUN corepack enable pnpm && corepack install -g pnpm@latest-9
# Files required by pnpm install
COPY .npmrc package.json pnpm-lock.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" ]
Пока в .npmrc
, package.json
, pnpm-lock.yaml
, .pnpmfile.cjs
нет изменений, кэш сборки docker останется действителен до слоя pnpm install --frozen-lockfile --prod
, который занимает значительную часть времени при создании образа в docker.
Однако, модификация package.json
может происходить гораздо чаще, чем мы ожидаем, так как он может содержать не только зависимости, но и версию пакета, скрипты и конфигурацию для других инструментов.
Также сложно поддерживать Dockerfile, который создает проект из монорепозитория, он может выглядеть так
FROM node:20
WORKDIR /path/to/somewhere
RUN corepack enable pnpm && corepack install -g pnpm@latest-9
# Files required by pnpm install
COPY .npmrc package.json pnpm-lock.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
отлично решает вышеуказанную проблему, предоставляя возможность для загрузки пакетов в виртуальное хранилище, используя только информацию из lockfile.
FROM node:20
WORKDIR /path/to/somewhere
RUN corepack enable pnpm && corepack install -g pnpm@latest-9
# 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 не связываться с реестром пакетов, так как все необходимые пакеты уже есть в виртуальном хранилище.
As long as the lockfile is not changed, the build cache is valid up to the layer, so RUN pnpm install -r --offline --prod
, will save you much time.
Опции
--dev, -D
Будут загружены только пакеты разработки
--prod, -P
Пакеты разработки не будут загружены