pnpm fetch
Загрузка пакетов из заблокированного файла в виртуальное хранилище, манифест пакета игнорируется.
Сценарий использования
Эта команда специально предназначена для сборки образа в docker.
Возможно, вы прочитали официальное руководство по написанию Dockerfile для Node.js приложения, если вы еще не читали его, возможно, будет полезно ознакомиться с ним.
По этому руководству мы научимся писать оптимизированный Dockerfile для проектов с помощью pnpm, который выглядит как
FROM node:14
RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
# 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:14
RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
# 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: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 не связываться с реестром пакетов, так как все необходимые пакеты уже есть в виртуальном хранилище.
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.