Files
Zoltan Kochan fc2f33912e refactor: move the TypeScript pnpm CLI into a pnpm11/ directory (#12537)
The TypeScript pnpm CLI freezes at v11; pnpm 12 will be the Rust pacquet
port. To make that split legible, all TypeScript source, test, and build
directories move under a new top-level pnpm11/ directory. The name states
the version boundary rather than implying a behavioral fork, since the two
stacks are meant to behave identically.

Scope is source-only: the shared workspace root stays at the repo root.
pnpm-workspace.yaml, package.json, pnpm-lock.yaml, .pnpmfile.cjs,
.meta-updater, __patches__, .changeset, .husky, and the lint/spell configs
remain in place, so one pnpm workspace and one Cargo workspace still span
all three products. pnpr/client and pacquet/tasks/registry-mock stay as
cross-product workspace members.

Rewiring the move required:
- pnpm-workspace.yaml globs prefixed with pnpm11/
- root package.json script paths, eslint.config.mjs, tsconfig.lint.json,
  .gitignore, and CODEOWNERS updated
- .meta-updater/src/index.ts literals repointed (pnpm11/pnpm/package.json,
  pnpm11/__utils__, pnpm11/__typings__, and the main package directory)
- regenerated every moved package's repository/homepage URL via meta-updater
- pnpm11/pnpm/bundle-deps.ts and __utils__/scripts/src/typecheck-only.ts
  climb one more level to reach the repo root

.meta-updater stays at the repo root because @pnpm/meta-updater resolves
its config at <cwd>/.meta-updater/main.mjs.

TS CI (.github/workflows/ci.yml) now only runs when pnpm11/-relevant paths
change, via a dorny/paths-filter changes job plus a TS CI / Success
aggregate gate; branch protection should require only that gate.
2026-06-20 14:36:25 +02:00
..

pnpm Benchmarks

Compares pnpm install performance between the current branch (HEAD) and main, across the six scenarios listed below.

This wrapper builds both pnpm revisions and runs hyperfine through the shared Rust orchestrator at pacquet/tasks/integrated-benchmark, so scenario / fixture / workspace / install-script / report generation stay consistent with the pacquet benchmark.

Prerequisites

  • cargo (install Rust via rustup if you don't have it).
  • hyperfine, pnpm, node, git on $PATH.

Usage

./benchmarks/bench.sh

The script:

  1. Builds the integrated-benchmark binary in release mode.
  2. Clones the current repo into the temp work-env once per revision (HEAD and main) and runs pnpm install && pnpm run compile-only in each to produce pnpm/dist/pnpm.mjs. compile-only skips the update-manifests pass that the root compile script does — it would rewrite tracked files and trigger a second install per revision, neither of which the bench needs.
  3. Runs hyperfine on each scenario with --registry=npm (hits registry.npmjs.org directly, no proxy — same as before).
  4. Writes a per-scenario BENCHMARK_REPORT.md / .json and a consolidated results.md into the temp work-env. The path is printed at the end of the run.
  5. Emits bencher-results.json — a hyperfine-shaped file with one result per scenario (the @HEAD revision only, command renamed to the scenario name) that the Benchmarks GitHub Actions workflow uploads to Bencher for continuous tracking.

Scenarios

Slugs follow <linker>.<action>.<cache state>.<store state> so the leading segment groups runs by linker mode. Today there are two groups (isolated-linker.* and gvs-linker.*); future scenarios will add hoisted-linker.* and pnp-linker.*.

Every current scenario starts with node_modules wiped — "fresh" names that target state; future variants that begin with a populated node_modules will use a different action prefix.

# Slug Lockfile Cache Store Description
1 isolated-linker.fresh-restore.hot-cache.hot-store ✔ frozen hot hot Restore from lockfile with both directories hot (repeat-headless shape)
2 isolated-linker.fresh-add-dep.hot-cache.hot-store ✔ + add dep hot hot pnpm add <dep> against an existing lockfile
3 isolated-linker.fresh-install.hot-cache.hot-store hot hot Resolve from scratch with both directories hot
4 isolated-linker.fresh-restore.cold-cache.cold-store ✔ frozen cold cold Restore from lockfile with cold disks (typical CI shape)
5 isolated-linker.fresh-install.cold-cache.cold-store cold cold True cold start — no lockfile, nothing cached
6 gvs-linker.fresh-restore.hot-cache.hot-store ✔ frozen hot hot + GVS Frozen-lockfile restore with enableGlobalVirtualStore: true, pre-warmed GVS

All scenarios use --ignore-scripts and isolated store/cache directories per revision.

Fixture

The fixture lives at fixture/ — a synthetic package.json with ~80 typical front-end dependencies, plus a committed pnpm-lock.yaml (generated once with pnpm install --lockfile-only). The lockfile is checked in so every CI run starts from the same resolution graph regardless of registry drift.

Configuration

Environment variables read by bench.sh:

  • WARMUP — number of warmup runs before timing (default: 1)
  • RUNS — number of timed runs per benchmark (default: 10)