Summary
pacquet install (no --frozen-lockfile, no usable lockfile) in a pnpm-workspace.yaml repo only resolves the workspace root manifest. Transitive workspace projects' own dependencies are not resolved into the lockfile. This makes pacquet effectively unusable for monorepos in the fresh-resolve path and is the dominant factor in the babylon benchmark's 4-7× slowdown across all variations.
Benchmark evidence
From benchmarks.vlt.sh/latest/chart-data.json — babylon is a pnpm-workspace.yaml monorepo (Babylon.js 3D engine, 86+ packages):
| Variation |
pnpm |
pacquet |
ratio |
clean |
23.68s |
99.51s |
4.2× slower |
cache |
21.60s |
52.70s |
2.4× slower |
lockfile |
16.12s |
100.42s |
6.2× slower |
node_modules |
26.13s |
99.23s |
3.8× slower |
cache+lockfile |
7.96s |
43.65s |
5.5× slower |
cache+lockfile+node_modules |
0.72s |
3.05s |
4.2× slower |
Compare with next (single project) where pacquet wins or ties: the slowdown is specifically a workspace-monorepo phenomenon in the fresh-resolve dispatch.
Current pacquet behavior
After the dispatch at pacquet/crates/package-manager/src/install.rs#L660-L699, the fresh branch passes a single &PackageManifest (the workspace root) into InstallWithFreshLockfile. The code self-documents the gap:
Pacquet's fresh-resolve path has one importer today (workspaces tracked at pnpm/pacquet#431), so the workspace root is the only path to register.
build_workspace_packages_map does load sibling workspace projects so the workspace: protocol resolves, but their own dependencies / devDependencies aren't walked.
Proposed approach
Match pnpm's installing/deps-installer/src/install/index.ts pattern: collect every workspace project's manifest into an importers list, hand the whole list to the resolver, and run one unified tree walk. Transitive packages that multiple workspace projects share get resolved once and deduped via pkgIdsByName.
This is Stage 2 Tier 1 of #11633 ("Resolution graph & recursion engine"), but worth tracking as its own concrete issue because:
- the file/line where the single-importer assumption is hard-coded is known and small;
- it's the dominant factor in one entire fixture column of the vlt benchmarks;
- it composes with the packument-prefetch work and the up-to-date short-circuit, so all three need to land before the vlt average reflects the wins.
Related
Written by an agent (Claude Code, claude-opus-4-7).
Summary
pacquet install(no--frozen-lockfile, no usable lockfile) in apnpm-workspace.yamlrepo only resolves the workspace root manifest. Transitive workspace projects' own dependencies are not resolved into the lockfile. This makes pacquet effectively unusable for monorepos in the fresh-resolve path and is the dominant factor in thebabylonbenchmark's 4-7× slowdown across all variations.Benchmark evidence
From
benchmarks.vlt.sh/latest/chart-data.json—babylonis apnpm-workspace.yamlmonorepo (Babylon.js 3D engine, 86+ packages):cleancachelockfilenode_modulescache+lockfilecache+lockfile+node_modulesCompare with
next(single project) where pacquet wins or ties: the slowdown is specifically a workspace-monorepo phenomenon in the fresh-resolve dispatch.Current pacquet behavior
After the dispatch at
pacquet/crates/package-manager/src/install.rs#L660-L699, the fresh branch passes a single&PackageManifest(the workspace root) intoInstallWithFreshLockfile. The code self-documents the gap:build_workspace_packages_mapdoes load sibling workspace projects so theworkspace:protocol resolves, but their owndependencies/devDependenciesaren't walked.Proposed approach
Match pnpm's
installing/deps-installer/src/install/index.tspattern: collect every workspace project's manifest into animporterslist, hand the whole list to the resolver, and run one unified tree walk. Transitive packages that multiple workspace projects share get resolved once and deduped viapkgIdsByName.This is Stage 2 Tier 1 of #11633 ("Resolution graph & recursion engine"), but worth tracking as its own concrete issue because:
Related
pacquet install --frozen-lockfilepacquet#431 (closed, frozen-path workspace support) — sister gap on the fresh-resolve sideWritten by an agent (Claude Code, claude-opus-4-7).