Skip to content

fix(middleware): replace p-limit with in-house limiter to fix Metro CJS load - #393

Merged
V3RON merged 4 commits into
mainfrom
fix/metro-plimit-esm-cjs
Aug 12, 2026
Merged

fix(middleware): replace p-limit with in-house limiter to fix Metro CJS load#393
V3RON merged 4 commits into
mainfrom
fix/metro-plimit-esm-cjs

Conversation

@V3RON

@V3RON V3RON commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • fix(metro): parallelize plugin discovery to stop startup stalls #388 parallelized plugin discovery in @rozenite/middleware using p-limit. p-limit has been ESM-only since v3 (pinned here at ^7.3.1), but Metro loads this package through its CJS build (dist/index.cjs), which does require("p-limit"). On Node versions without require(esm) interop (pre-20.19) this throws ERR_REQUIRE_ESM and breaks Metro startup entirely; on newer Node it silently works, which is what let this ship unnoticed.
  • Replaces the dependency with a small in-house bounded-concurrency limiter (createLimiter) local to auto-discovery.ts, removing the ESM/CJS boundary risk altogether.
  • Adds a ground truth to AGENTS.md: Metro-related changes must be verified by actually running Metro in apps/playground, since this class of failure only shows up at runtime and isn't caught by unit tests or typecheck.

Test plan

  • pnpm --filter @rozenite/middleware run build — verified dist/index.cjs and dist/index.js no longer reference p-limit
  • pnpm --filter @rozenite/middleware run typecheck
  • pnpm --filter @rozenite/middleware run test (81 tests passing)
  • CI=1 pnpm --filter playground start — Metro boots cleanly, all 14 plugins discovered, no ESM/require errors

V3RON added 3 commits August 12, 2026 12:32
…o CJS load

p-limit is ESM-only since v3, but Metro loads @rozenite/middleware's
plugin discovery through its CJS build (dist/index.cjs), which throws
ERR_REQUIRE_ESM on Node versions without require(esm) interop. Swap it
for a small local concurrency limiter with no external dependency.

Also add an agent rule requiring Metro-related changes to be verified
by actually running Metro in apps/playground, since this failure mode
only shows up at runtime, not in unit tests or typecheck.
AGENTS.md should stay routing-only; the actual guidance belongs in
docs/agents/ alongside the other testing guides.
…ests

Move the bounded-concurrency limiter added to replace p-limit out of
auto-discovery.ts into a shared, properly tested utility. Covers the
behaviors that matter: the concurrency cap is enforced, queued work
starts as slots free up, each call resolves with its own result, and
a rejection propagates without breaking the rest of the queue.
@vercel

vercel Bot commented Aug 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
rozenite Skipped Skipped Aug 12, 2026 10:41am

Request Review

Add a vitest test that spawns a real node subprocess (bypassing
Vitest's own module runner, which prefers each package's `development`
export condition and would otherwise mask the failure) to require the
built @rozenite/tools, @rozenite/middleware, and @rozenite/metro CJS
bundles and run withRozenite() end-to-end. This reproduces exactly how
Metro loads these packages and would have caught the p-limit ESM/CJS
break at require-time instead of only in production.

Also note the test in docs/agents/metro-testing.md alongside the
existing guidance to verify Metro-related changes against a real
Metro boot.
@V3RON
V3RON merged commit a1b55ba into main Aug 12, 2026
4 checks passed
@V3RON
V3RON deleted the fix/metro-plimit-esm-cjs branch August 12, 2026 11:12
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