pnpm 获取
从锁文件获取包到虚拟存储中,忽略包清单。
使用场景
该命令专门用于优化 Docker 镜像构建。
你可能已经阅读过编写 Node.js 应用 Dockerfile 的官方指南,如果尚未阅读,建议先查看。
从该指南中,我们了解到使用 pnpm 的优化 Dockerfile 应该如下所示:
FROM node:20
WORKDIR /path/to/somewhere
RUN corepack enable pnpm && corepack install -g pnpm@latest-10
# pnpm install 需要的文件
COPY .npmrc package.json pnpm-lock.yaml pnpm-workspace.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
、pnpm-workspace.yaml
、.pnpmfile.cjs
没有变化,Docker 构建缓存在 RUN 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-10
# pnpm install 需要的文件
COPY .npmrc package.json pnpm-lock.yaml pnpm-workspace.yaml .pnpmfile.cjs ./
# 如果修补过任何包,在运行 pnpm install 前也需要包含补丁
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
通过仅使用锁文件和配置文件(pnpm-workspace.yaml
)加载包到虚拟存储中,完美解决了上述问题。
FROM node:20
WORKDIR /path/to/somewhere
RUN corepack enable pnpm && corepack install -g pnpm@latest-10
# pnpm fetch 仅需要锁文件
COPY pnpm-lock.yaml pnpm-workspace.yaml ./
# 如果修补过任何包,在运行 pnpm fetch 前也需要包含补丁
COPY patches patches
RUN pnpm fetch --prod
ADD . ./
RUN pnpm install -r --offline --prod
EXPOSE 8080
CMD [ "node", "server.js" ]