Skip to content

Commit c526347

Browse files
authored
Adopt pnpm catalogs for devDependencies (vercel#93071)
### What? Adopt pnpm [catalogs](https://pnpm.io/catalogs) for shared hoisted devDependencies: `typescript`, `jest`, `eslint`, and `prettier`. Each is pinned once in `pnpm-workspace.yaml` and referenced as `"<name>": "catalog:"` by every consumer. Also adds the missing `dom.iterable` lib to `@next/routing`'s tsconfig, required by `URLSearchParams.entries()` in TypeScript 6. ### Why? Several packages invoke these binaries in their build, test, or lint scripts but do not declare them in their own `devDependencies` — they rely on the hoisted root install. This breaks Turborepo's cache invalidation: without a declared dep, a package has no lockfile edge to the tool, so bumping its version (e.g. vercel#91257's TypeScript 5 → 6 upgrade) does not invalidate that package's task hash. `@next/routing`'s `types` task has been a remote-cache hit on canary since the TS 6 bump, even though it now fails locally on a cold cache — CI is replaying a stale pre-bump success. The same latent hazard exists for `jest` (`@next/codemod`), `eslint` (`@next/bundle-analyzer-ui`), and `prettier` (`create-next-app`). ### How? - `pnpm-workspace.yaml` defines `catalog:` entries for each tool. - Consumer packages declare `"<name>": "catalog:"`. pnpm still hoists one copy, but each consumer now has a real lockfile edge to the resolved version. - Root `package.json` migrates each pin to `"catalog:"` so the workspace file is the single source of truth. Turborepo needs no changes — its existing per-package hashing picks up lockfile edge changes automatically. Future catalog bumps will invalidate every consumer's cache. `@types/node` is a deliberate omission from this round: several packages intentionally pin different majors (`^22`, `^20`, `20.14.2`), so migrating it needs per-package intent review rather than bulk conversion. <!-- NEXT_JS_LLM_PR -->
1 parent 2b846de commit c526347

11 files changed

Lines changed: 150 additions & 53 deletions

File tree

apps/bundle-analyzer/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@
3535
"@types/react": "^18",
3636
"@types/react-dom": "^18",
3737
"cross-env": "10.1.0",
38+
"eslint": "catalog:",
3839
"inliner": "1.13.1",
3940
"postcss": "^8.5",
4041
"tailwindcss": "^4.1.9",
4142
"tw-animate-css": "1.3.3",
42-
"typescript": "6.0.2"
43+
"typescript": "catalog:"
4344
}
4445
}

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@
198198
"dd-trace": "4.12.0",
199199
"es5-ext": "0.10.53",
200200
"escape-string-regexp": "2.0.0",
201-
"eslint": "9.37.0",
201+
"eslint": "catalog:",
202202
"eslint-config-next": "workspace:*",
203203
"eslint-formatter-codeframe": "7.32.1",
204204
"eslint-plugin-eslint-plugin": "5.2.1",
@@ -230,7 +230,7 @@
230230
"image-size": "1.2.1",
231231
"is-animated": "2.0.2",
232232
"isomorphic-unfetch": "3.0.0",
233-
"jest": "29.7.0",
233+
"jest": "catalog:",
234234
"jest-diff": "29.7.0",
235235
"jest-environment-jsdom": "29.7.0",
236236
"jest-extended": "4.0.2",
@@ -262,7 +262,7 @@
262262
"postcss-pseudoelements": "5.0.0",
263263
"postcss-short-size": "4.0.0",
264264
"postcss-trolling": "0.1.7",
265-
"prettier": "3.6.2",
265+
"prettier": "catalog:",
266266
"pretty-bytes": "5.3.0",
267267
"pretty-ms": "7.0.0",
268268
"random-seed": "0.3.0",
@@ -302,7 +302,7 @@
302302
"tsec": "0.2.1",
303303
"tsx": "4.19.2",
304304
"turbo": "2.9.4",
305-
"typescript": "6.0.2",
305+
"typescript": "catalog:",
306306
"typescript-eslint": "8.46.0",
307307
"unfetch": "4.2.0",
308308
"wait-port": "0.2.2",

packages/create-next-app/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"cross-spawn": "7.0.3",
4242
"fast-glob": "3.3.1",
4343
"picocolors": "1.1.1",
44+
"prettier": "catalog:",
4445
"prettier-plugin-tailwindcss": "0.6.2",
4546
"prompts": "2.4.2",
4647
"tar": "7.5.7",

packages/eslint-plugin-next/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
},
1818
"devDependencies": {
1919
"@types/eslint": "9.6.1",
20-
"eslint": "9.37.0"
20+
"eslint": "9.37.0",
21+
"typescript": "catalog:"
2122
},
2223
"scripts": {
2324
"dev": "pnpm build",

packages/next-codemod/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"@types/jscodeshift": "0.11.0",
4141
"@types/prompts": "2.4.2",
4242
"@types/semver": "7.3.1",
43-
"typescript": "6.0.2"
43+
"jest": "catalog:",
44+
"typescript": "catalog:"
4445
}
4546
}

packages/next-env/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"devDependencies": {
3333
"@vercel/ncc": "0.34.0",
3434
"dotenv": "16.3.1",
35-
"dotenv-expand": "10.0.0"
35+
"dotenv-expand": "10.0.0",
36+
"typescript": "catalog:"
3637
}
3738
}

packages/next-routing/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"@types/jest": "^29.5.0",
3535
"@vercel/ncc": "0.34.0",
3636
"jest": "^29.5.0",
37-
"ts-jest": "^29.1.0"
37+
"ts-jest": "^29.1.0",
38+
"typescript": "catalog:"
3839
}
3940
}

packages/next-routing/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"resolveJsonModule": true,
88
"esModuleInterop": true,
99
"skipLibCheck": false,
10-
"lib": ["es2022", "dom"],
10+
"lib": ["es2022", "dom", "dom.iterable"],
1111
"rootDir": "src",
1212
"types": ["jest"]
1313
},

packages/react-refresh-utils/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
},
2828
"devDependencies": {
2929
"react-refresh": "0.12.0",
30+
"typescript": "catalog:",
3031
"webpack": "^4 || ^5"
3132
}
3233
}

0 commit comments

Comments
 (0)