docs(docker): document the pnpm prune -C test and why it doesn't help

A reviewer asked whether looping `pnpm prune --prod -C <dir>` over
every workspace member could replace the delete-then-reinstall. Tested
it directly: `-C <dir>` does correctly scope to one member's own
devDependencies (unlike bare `pnpm prune --prod`, root-importer only) --
confirmed by running it against all ~30 workspace members and watching
each one's dev-only packages unlink from its own node_modules.

Final size after the full loop: unchanged, 2.8GB to 2.8GB. Prune only
drops a package once every importer that references it has released it,
and `ui` stays a full workspace member throughout -- some of its real
(non-dev) dependencies need typescript/vite/vitest/rolldown as peer
dependencies regardless of classification, so those never fully release.
Per-member pruning can unlink packages from one importer's own
node_modules, but it can never exclude an entire unrelated workspace
member's footprint the way `--filter='@paperclipai/server...'` does,
because it never stops trying to satisfy that member's needs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RD53WaVFqm8pbntKZ5seWy
This commit is contained in:
Nicky Leach 2026-09-08 08:59:36 -07:00
parent 3e581b6821
commit 3d11d7e52d
No known key found for this signature in database
GPG Key ID: 4861541D36B2037E
1 changed files with 15 additions and 5 deletions

View File

@ -121,11 +121,21 @@ RUN rm -rf packages/paperclip-runner/runner/target
# skip the full install: `build` above needs every devDependency present
# (typescript, vite, cargo's crates, ...) to actually compile the ui,
# plugin-sdk, and server. Only once that's done do we know it's safe to
# drop them. `pnpm prune --prod` looked like the narrower tool for this,
# but it only prunes the *root* workspace importer's devDependencies, not
# each member's independently, and takes no --filter -- so it can't scope
# to just server's own graph. A filtered `install --prod` is the only
# primitive that does, and it requires a clean node_modules first.
# drop them. `pnpm prune --prod` looked like the narrower tool for this;
# it isn't. Run bare it only prunes the *root* workspace importer, but
# `pnpm prune --prod -C <dir>` does correctly scope to one member's own
# devDependencies -- verified by running it against every workspace
# member in turn, which measurably unlinked each member's own dev-only
# packages. It still leaves the shipped node_modules unchanged in
# aggregate, because prune only drops a package once *every* importer
# that references it, prod or dev, has released it, and `ui` remains a
# full workspace member throughout with its own real (non-dev)
# dependencies -- some of which need typescript/vite/vitest/rolldown as
# peer dependencies regardless of dev/prod classification. No amount of
# per-member pruning can exclude `ui`'s footprint the way `--filter`
# does, because prune never stops trying to satisfy it. A filtered
# `install --prod` is the only primitive that scopes to just server's
# own graph, and it requires a clean node_modules first.
#
# tsx is deliberately NOT pruned: server/package.json lists it as a
# production dependency (not dev) because the ENTRYPOINT below imports it