Skip to content

Always consult npm_config_user_agent first#95879

Open
eps1lon wants to merge 1 commit into
canaryfrom
sebbie/getpkgmanager-npm-user-agent-e82f97
Open

Always consult npm_config_user_agent first#95879
eps1lon wants to merge 1 commit into
canaryfrom
sebbie/getpkgmanager-npm-user-agent-e82f97

Conversation

@eps1lon

@eps1lon eps1lon commented Jul 16, 2026

Copy link
Copy Markdown
Member

The getPkgManager helpers previously consulted the filesystem first for files hinting at the used package manager. Only if none were found did we check process.env.npm_config_user_agent and then shelled out to testing which package manager is available.

This change makes all helpers check the npm_config_user_agent environment variable first. The variable is set by the package manager that invoked the process, so when present it is both the cheapest and the most direct signal, avoiding filesystem access and subprocess spawns entirely. create-next-app already used this user-agent-first approach and is unchanged.

The check order is now consistent across all three implementations: yarn, pnpm, bun, npm for the user agent (the packages/next variant has no bun in its PackageManager type and falls through to lockfile detection there), and the same order for the codemod's lockfile walk, which previously prioritized package-lock.json.

Because the invoking package manager now takes precedence over lockfile inference, running npx next ... or npx @next/codemod ... inside a pnpm or yarn app is now detected as npm. Use pnpx (or pnpm dlx) and yarn dlx instead so the detected package manager matches the project.

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Tests Passed

Commit: a37dc69

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Stats from current PR

✅ No significant changes detected

📊 All Metrics
📖 Metrics Glossary

Dev Server Metrics:

  • Listen = TCP port starts accepting connections
  • First Request = HTTP server returns successful response
  • Cold = Fresh build (no cache)
  • Warm = With cached build artifacts

Build Metrics:

  • Fresh = Clean build (no .next directory)
  • Cached = With existing .next directory

Change Thresholds:

  • Time: Changes < 50ms AND < 10%, OR < 2% are insignificant
  • Size: Changes < 1KB AND < 1% are insignificant
  • All other changes are flagged to catch regressions

⚡ Dev Server

Metric Canary PR Change Trend
Cold (Listen) 812ms 812ms ▂▂▂▂▂
Cold (Ready in log) 781ms 781ms ▁▁▂▂▁
Cold (First Request) 1.309s 1.305s ▁▁▁▂▁
Warm (Listen) 813ms 813ms ▂▂▂▂▂
Warm (Ready in log) 781ms 784ms ▁▁▂▁▁
Warm (First Request) 1.314s 1.310s ▁▁▂▁▁
📦 Dev Server (Webpack) (Legacy)

📦 Dev Server (Webpack)

Metric Canary PR Change Trend
Cold (Listen) 813ms 812ms ███▁█
Cold (Ready in log) 798ms 796ms ▆▆▇▂▄
Cold (First Request) 3.448s 3.528s ▆▅▆▂▄
Warm (Listen) 814ms 813ms ▁██▁▁
Warm (Ready in log) 800ms 802ms ▂▇█▁▃
Warm (First Request) 3.500s 3.488s ▁█▇▁▃

⚡ Production Builds

Metric Canary PR Change Trend
Fresh Build 5.149s 5.233s ▂▁▂▃▃
Cached Build 5.291s 5.394s ▂▁▃▃▃
📦 Production Builds (Webpack) (Legacy)

📦 Production Builds (Webpack)

Metric Canary PR Change Trend
Fresh Build 25.549s 25.935s █▄▇▂▃
Cached Build 25.746s 25.960s █▅█▃▄
node_modules Size 516 MB 516 MB █████
📦 Bundle Sizes

Bundle Sizes

⚡ Turbopack

Client

Main Bundles
Canary PR Change
01e_imjacf07z.js gzip 154 B N/A -
03gmyxr7dukvs.js gzip 10.3 kB N/A -
040t1q17lo593.js gzip 8.77 kB N/A -
0bb0vtp8dwsez.js gzip 450 B N/A -
0cz1d0mv5g_q7.js gzip 39.4 kB 39.4 kB
0eit-_nonzj2s.js gzip 156 B N/A -
0l0sr6gau5xjn.js gzip 3.53 kB N/A -
0nxqz3q165m2l.js gzip 220 B N/A -
0qr-1tnb7_hg5.js gzip 5.72 kB N/A -
0uilzvklme4ea.js gzip 8.76 kB N/A -
0z0y83mfx-l-h.js gzip 10 kB N/A -
1_-g_r52k540c.js gzip 7.4 kB N/A -
1_an7sn6d05rs.js gzip 71 kB N/A -
15igz6de8tbl1.js gzip 156 B N/A -
15ok8ydf274z0.js gzip 10.6 kB N/A -
16cqqcigykfea.js gzip 13.6 kB N/A -
17h18zxt1915l.js gzip 1.46 kB N/A -
1elt1qium-r2m.css gzip 115 B 115 B
1fq1h7dxad4cv.js gzip 9.44 kB N/A -
1fym-adbk_69_.js gzip 13.1 kB N/A -
1gav7nfh4y8ln.js gzip 8.76 kB N/A -
1nd7cq5in04rl.js gzip 156 B N/A -
1o34vh44ndvtu.js gzip 13.2 kB N/A -
222aicw6zfjee.js gzip 168 B N/A -
22adlxvtko43-.js gzip 156 B N/A -
27pui1--s83v1.js gzip 161 B N/A -
2hmvy2eezqhve.js gzip 155 B N/A -
2rtsd8k_9_3wp.js gzip 65.6 kB N/A -
2rypqffktcxqh.js gzip 8.69 kB N/A -
2uqsizxtehgqf.js gzip 8.79 kB N/A -
2vzktdqwbijqc.js gzip 8.74 kB N/A -
3-l1ry5jvjih5.js gzip 156 B N/A -
34ymlfb51t7yk.js gzip 160 B N/A -
3c244akvx_-be.js gzip 8.74 kB N/A -
3dmlemitx3ef3.js gzip 2.29 kB N/A -
3jiffnngz-na-.js gzip 153 B N/A -
3ju4nfc0yn2eu.js gzip 153 B N/A -
3qoudnhxxelar.js gzip 157 B N/A -
3xnirvm94z_xt.js gzip 45.1 kB N/A -
4237vdj6eyslt.js gzip 8.7 kB N/A -
turbopack-0m..7odi.js gzip 3.8 kB N/A -
turbopack-0x..hrn0.js gzip 3.8 kB N/A -
turbopack-1b..x1e0.js gzip 3.8 kB N/A -
turbopack-1i..vmrl.js gzip 3.82 kB N/A -
turbopack-1y..b-7-.js gzip 3.8 kB N/A -
turbopack-2d..17x1.js gzip 3.8 kB N/A -
turbopack-2z..eq0n.js gzip 3.8 kB N/A -
turbopack-37..nh-g.js gzip 3.8 kB N/A -
turbopack-37..om2h.js gzip 3.8 kB N/A -
turbopack-39..z6f_.js gzip 3.8 kB N/A -
turbopack-3c..pabh.js gzip 3.8 kB N/A -
turbopack-3g..ijvr.js gzip 3.8 kB N/A -
turbopack-3h..yd91.js gzip 3.8 kB N/A -
turbopack-3q..-0wi.js gzip 3.78 kB N/A -
00-jmooa35h-r.js gzip N/A 45.2 kB -
0030hp-a_j9-y.js gzip N/A 156 B -
00tc16j5-eos9.js gzip N/A 1.46 kB -
02m7iodv32z8g.js gzip N/A 154 B -
0d7pewi7wgo4-.js gzip N/A 155 B -
0eruqpjj0h_ao.js gzip N/A 161 B -
0gaw1gmpwuwkn.js gzip N/A 8.8 kB -
0mejki6x1gy5u.js gzip N/A 160 B -
0pcox5e50zag8.js gzip N/A 65.6 kB -
1-mrm3ivjbndn.js gzip N/A 157 B -
12gwyaf8lv86s.js gzip N/A 157 B -
12zyjjmq4oad1.js gzip N/A 5.72 kB -
1k9cc4-gpa2cx.js gzip N/A 13.1 kB -
1kfiwrcr725kl.js gzip N/A 13.2 kB -
1n59uogejo81s.js gzip N/A 10.3 kB -
1npei3hlexdv3.js gzip N/A 9.99 kB -
1ssuiwj_rnpc5.js gzip N/A 8.77 kB -
1zp2ipjglr15r.js gzip N/A 166 B -
2-phc9obd3nyd.js gzip N/A 8.77 kB -
24gok_u2-8uee.js gzip N/A 153 B -
24utq57r3l1cw.js gzip N/A 8.7 kB -
2fhjq6ek3srmr.js gzip N/A 8.69 kB -
2g0t7upz_v-hf.js gzip N/A 10.6 kB -
2ia9qqy99aie9.js gzip N/A 13.6 kB -
2k7havh6955t0.js gzip N/A 154 B -
2n5fp99a5xt9s.js gzip N/A 7.4 kB -
2oza28kdqvoay.js gzip N/A 8.74 kB -
2zh8-mmhujy8o.js gzip N/A 2.29 kB -
30h_m0irj-q6p.js gzip N/A 221 B -
37ejbfx1u9lpo.js gzip N/A 8.75 kB -
38c63ct4i1cy7.js gzip N/A 449 B -
3ge7xyod8yvys.js gzip N/A 154 B -
3jimpal3lvz5e.js gzip N/A 9.44 kB -
3psggucft0se9.js gzip N/A 71 kB -
3su6a4l8jbfth.js gzip N/A 3.53 kB -
3vn00s3x0zs4q.js gzip N/A 155 B -
3wb4pe4z4-aim.js gzip N/A 8.77 kB -
40ll_plfwk8s3.js gzip N/A 155 B -
turbopack-0r..9osd.js gzip N/A 3.8 kB -
turbopack-0t..5bzs.js gzip N/A 3.8 kB -
turbopack-0x..20qr.js gzip N/A 3.8 kB -
turbopack-10..78dl.js gzip N/A 3.81 kB -
turbopack-10..nxvf.js gzip N/A 3.8 kB -
turbopack-1a..ccvc.js gzip N/A 3.8 kB -
turbopack-1j..e8j8.js gzip N/A 3.8 kB -
turbopack-1u..nvl8.js gzip N/A 3.79 kB -
turbopack-21..mb7z.js gzip N/A 3.8 kB -
turbopack-2g..jzua.js gzip N/A 3.8 kB -
turbopack-2k..c_qw.js gzip N/A 3.8 kB -
turbopack-3c..alqz.js gzip N/A 3.8 kB -
turbopack-3x..vw7k.js gzip N/A 3.8 kB -
turbopack-40..rxjx.js gzip N/A 3.8 kB -
Total 448 kB 448 kB ⚠️ +41 B

Server

Middleware
Canary PR Change
middleware-b..fest.js gzip 782 B 769 B 🟢 13 B (-2%)
Total 782 B 769 B ✅ -13 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 432 B 434 B
Total 432 B 434 B ⚠️ +2 B

📦 Webpack

Client

Main Bundles
Canary PR Change
2486.HASH.js gzip 169 B N/A -
3146-HASH.js gzip 64.2 kB N/A -
39fcf99b-HASH.js gzip 62.9 kB N/A -
8443-HASH.js gzip 4.68 kB N/A -
9431-HASH.js gzip 5.62 kB N/A -
framework-HASH.js gzip 59.8 kB 59.8 kB
main-app-HASH.js gzip 255 B 252 B 🟢 3 B (-1%)
main-HASH.js gzip 39.7 kB 40.1 kB 🔴 +452 B (+1%)
webpack-HASH.js gzip 1.68 kB 1.68 kB
6105-HASH.js gzip N/A 5.63 kB -
764.HASH.js gzip N/A 169 B -
8898-HASH.js gzip N/A 63.5 kB -
9597-HASH.js gzip N/A 4.65 kB -
e1ccab69-HASH.js gzip N/A 62.9 kB -
Total 239 kB 239 kB ✅ -220 B
Polyfills
Canary PR Change
polyfills-HASH.js gzip 39.4 kB 39.4 kB
Total 39.4 kB 39.4 kB
Pages
Canary PR Change
_app-HASH.js gzip 194 B 194 B
_error-HASH.js gzip 183 B 182 B
css-HASH.js gzip 335 B 335 B
dynamic-HASH.js gzip 1.8 kB 1.8 kB
edge-ssr-HASH.js gzip 255 B 254 B
head-HASH.js gzip 351 B 349 B
hooks-HASH.js gzip 384 B 384 B
image-HASH.js gzip 580 B 580 B
index-HASH.js gzip 259 B 259 B
link-HASH.js gzip 2.49 kB 2.49 kB
routerDirect..HASH.js gzip 319 B 319 B
script-HASH.js gzip 386 B 386 B
withRouter-HASH.js gzip 315 B 313 B
1afbb74e6ecf..834.css gzip 106 B 106 B
Total 7.96 kB 7.95 kB ✅ -7 B

Server

Edge SSR
Canary PR Change
edge-ssr.js gzip 128 kB 128 kB
page.js gzip 283 kB 285 kB 🔴 +2.23 kB (+1%)
Total 411 kB 413 kB ⚠️ +1.9 kB
Middleware
Canary PR Change
middleware-b..fest.js gzip 616 B 614 B
middleware-r..fest.js gzip 156 B 155 B
middleware.js gzip 45.5 kB 45.3 kB
edge-runtime..pack.js gzip 842 B 842 B
Total 47.1 kB 46.9 kB ✅ -220 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 719 B 720 B
Total 719 B 720 B ⚠️ +1 B
Build Cache
Canary PR Change
0.pack gzip 4.82 MB 4.81 MB 🟢 11.3 kB (0%)
index.pack gzip 120 kB 120 kB
index.pack.old gzip 120 kB 119 kB
Total 5.06 MB 5.05 MB ✅ -12.3 kB

🔄 Shared (bundler-independent)

Runtimes
Canary PR Change
app-page-exp...dev.js gzip 364 kB 364 kB
app-page-exp..prod.js gzip 201 kB 201 kB
app-page-tur...dev.js gzip 363 kB 363 kB
app-page-tur..prod.js gzip 201 kB 201 kB
app-page-tur...dev.js gzip 360 kB 360 kB
app-page-tur..prod.js gzip 199 kB 199 kB
app-page.run...dev.js gzip 360 kB 360 kB
app-page.run..prod.js gzip 199 kB 199 kB
app-route-ex...dev.js gzip 81.5 kB 81.5 kB
app-route-ex..prod.js gzip 55.4 kB 55.4 kB
app-route-tu...dev.js gzip 81.5 kB 81.5 kB
app-route-tu..prod.js gzip 55.4 kB 55.4 kB
app-route-tu...dev.js gzip 81.1 kB 81.1 kB
app-route-tu..prod.js gzip 55.1 kB 55.1 kB
app-route.ru...dev.js gzip 81.1 kB 81.1 kB
app-route.ru..prod.js gzip 55.1 kB 55.1 kB
dist_client_...dev.js gzip 324 B 324 B
dist_client_...dev.js gzip 326 B 326 B
dist_client_...dev.js gzip 318 B 318 B
dist_client_...dev.js gzip 317 B 317 B
pages-api-tu...dev.js gzip 45.2 kB 45.2 kB
pages-api-tu..prod.js gzip 33.9 kB 33.9 kB
pages-api.ru...dev.js gzip 45.2 kB 45.2 kB
pages-api.ru..prod.js gzip 33.9 kB 33.9 kB
pages-turbo....dev.js gzip 54.6 kB 54.6 kB
pages-turbo...prod.js gzip 39.6 kB 39.6 kB
pages.runtim...dev.js gzip 54.6 kB 54.6 kB
pages.runtim..prod.js gzip 39.5 kB 39.5 kB
server.runti..prod.js gzip 67.5 kB 67.5 kB
use-cache-pr...dev.js gzip 71.4 kB 71.4 kB
use-cache-pr...dev.js gzip 71.4 kB 71.4 kB
use-cache-pr...dev.js gzip 69.7 kB 69.7 kB
use-cache-pr...dev.js gzip 69.7 kB 69.7 kB
Total 3.49 MB 3.49 MB ⚠️ +5 B
📝 Changed Files (2 files)

Files with changes:

  • pages-api-tu..ntime.dev.js
  • pages-turbo...ntime.dev.js
View diffs
pages-api-tu..ntime.dev.js

Diff too large to display

pages-turbo...ntime.dev.js

Diff too large to display

📎 Tarball URL
https://vercel-packages.vercel.app/next/commits/a37dc695ec859c0738812c3baecd1b4d6c3f5902/next

Commit: a37dc69

@eps1lon eps1lon changed the title Check npm_config_user_agent before lockfiles in getPkgManager Always consilt npm_config_user_agent first Jul 16, 2026
@eps1lon eps1lon changed the title Always consilt npm_config_user_agent first Always consult npm_config_user_agent first Jul 16, 2026
@eps1lon
eps1lon marked this pull request as ready for review July 17, 2026 07:10
The `getPkgManager` helpers previously consulted the filesystem first: the `packages/next` variant checked for lockfiles in the base directory and then probed `yarn --version` / `pnpm --version` via `execSync`, while the `packages/next-codemod` variant walked up parent directories with `find-up` and never read the user agent at all.

This change makes both helpers check the `npm_config_user_agent` environment variable first. The variable is set by the package manager that invoked the process, so when present it is both the cheapest and the most direct signal, avoiding filesystem access and subprocess spawns entirely. `create-next-app` already used this user-agent-first approach and is unchanged.

The check order is now consistent across all three implementations: yarn, pnpm, bun, npm for the user agent (the `packages/next` variant has no `bun` in its `PackageManager` type and falls through to lockfile detection there), and the same order for the codemod's lockfile walk, which previously prioritized `package-lock.json`.

Because the invoking package manager now takes precedence over lockfile inference, running `npx next ...` or `npx @next/codemod ...` inside a pnpm or yarn app is now detected as npm. Use `pnpx` (or `pnpm dlx`) and `yarn dlx` instead so the detected package manager matches the project.
@eps1lon
eps1lon force-pushed the sebbie/getpkgmanager-npm-user-agent-e82f97 branch from e6d570a to a37dc69 Compare July 17, 2026 07:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant