From 3d11d7e52da3dd4e101daf65651c6ecce3ae25e7 Mon Sep 17 00:00:00 2001 From: Nicky Leach Date: Tue, 8 Sep 2026 08:59:36 -0700 Subject: [PATCH] docs(docker): document the pnpm prune -C test and why it doesn't help A reviewer asked whether looping `pnpm prune --prod -C ` over every workspace member could replace the delete-then-reinstall. Tested it directly: `-C ` 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 Claude-Session: https://claude.ai/code/session_01RD53WaVFqm8pbntKZ5seWy --- Dockerfile | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4274841095..5263182808 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 ` 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