Use @next/routing - #41
Conversation
commit: |
…y into core adapter feat: enhance build process with additional server bundle customization options chore: update package.json scripts for improved build and testing workflow test: add unit tests for adapter build process and server bundle generation fix: ensure proper handling of external dependencies and edge configuration in server bundle
…ests for resolve plugin
…specific overrides
…udflare specific overrides" This reverts commit 37c4d90.
…ad of throwing - Extract ValidateConfigResult type with success/message/shouldThrow/level - Convert validateFunctionOptions and validateSplittedFunctionOptions to return result objects - Remove logger dependency from validateConfig.ts - Preserve compatibilityMatrix, TODO comment, @ts-expect-error pragmas - Add 5 characterization tests in validateConfig.spec.ts - No caller impact: compileConfig.ts is the sole importer (updated in T3)
- Export OpenNextOutput interface (was internal) - Extract buildOpenNextOutput(buildOpts) for construction-only (no fs write) - Keep legacy generateOutput as thin wrapper (construction + file write) - Preserve all construction logic verbatim, including @ts-expect-error - Add 3 characterization tests in generateOutput.spec.ts - Backward compatible: byte-equivalent output to today
- Replace bare validateConfig(config) call with result-handling block - Throw on shouldThrow:true (bad routes — preserves existing behavior) - Log at appropriate level on shouldThrow:false (level field from T1) - All 3 export signatures and edge-runtime detection block unchanged - Direct callers (aws/build.ts, cloudflare/utils.ts) unaffected
…OpenNextAdapterOptions - Make OpenNextAdapterOptions<T = OpenNextOutput> and buildAdapter<T> generic - Add validateConfig override hook (runs after callback in modifyConfig) - Add generateOutput override hook (returns T, gated by skipGenerateOutput) - buildAdapter serializes override return via fs.writeFileSync (override never touches fs) - Default path uses buildOpenNextOutput (extracted in T2) - Add 5 new tests covering override behaviors + default path + skipGenerateOutput - All 16 existing adapter tests preserved; AWS/Cloudflare adapters compile with default T
When an adapter config specifies full package-specifier paths (e.g., @opennextjs/aws/overrides/wrappers/aws-lambda.js), esbuild cannot resolve them during bundling. Use createRequire(args.path).resolve() in the openNextResolvePlugin to convert package specifiers to filesystem-relative paths at build time, falling back to the original value if resolution fails. This fixes the openbuild:local build error: ERROR: Could not resolve "@opennextjs/aws/overrides/wrappers/aws-lambda.js" ERROR: Could not resolve "@opennextjs/aws/overrides/tagCache/dynamodb.js" Added test I verifying resolution of a mock package in node_modules.
…solution and improve path handling
4e9a367 to
cd8f83e
Compare
…ldInvokeMiddleware to use pathname test(middleware): add tests for getMiddlewareMatchPath function test(routingHandler): implement middleware matching tests for routingHandler
…ted types and tests
…figuration and tests
…d types and tests
8dc3628 to
c5833a3
Compare
# Conflicts: # create-cloudflare/next/package.json # packages/cloudflare/src/cli/adapter.ts # packages/core/src/build/adapter.spec.ts # packages/core/src/build/adapter.ts # packages/core/src/build/createMiddleware.ts # packages/core/src/build/middleware/buildNodeMiddleware.ts # packages/core/src/build/validateConfig.spec.ts # packages/core/src/build/validateConfig.ts # packages/tests-unit/tests/core/routing/matcher.test.ts # pnpm-lock.yaml
Await the Playwright response assertion in both the shared and Cloudflare middleware suites. This prevents each test from finishing before the expected 403 rewrite status has actually been verified.
Raise the minimum supported Next.js version to 16.2.1, where the adapter callback provides the routing metadata and build ID consumed by the Cloudflare build. Add boundary tests for the last unsupported and first supported versions.
Use Next.js output IDs and prerender parentOutputId metadata to identify the executable route that owns each prerender. This correctly indexes concrete prerenders and PPR segment payloads as ISR content while retaining pathname-based fallback resolution for unmatched metadata.
Assert that standalone Node middleware bundles receive open-next-routing.json beside their copied Next.js artifacts. Document the bundle builder contract so the packaging requirement and failure modes remain explicit.
Rename condition captures only when the complete placeholder name matches. This prevents a capture such as from corrupting longer destination placeholders such as .
Return the first complete matching priority redirect and allocate headers per candidate. This preserves route order and prevents status or headers from incomplete earlier candidates leaking into a later redirect.
Return Next-compatible JSON 404 responses for _next/data requests whose build ID does not match the active build. Rejecting them before route and middleware resolution prevents stale client requests from being treated as page navigation.
Merge incoming request query parameters with the external rewrite destination, giving destination values precedence on conflicts. Rebuild the invocation URL and normalized event query together so record-based proxy adapters do not drop either source or destination parameters.
Assert that middleware receives the user-visible page pathname when routing a matching _next/data request. This protects the URL normalization behavior in addition to merely checking that middleware was invoked.
Tee request streams before invoking middleware so downstream internal routes, external rewrites, and 404 handlers receive an unread body branch. Cancel the unused branch for terminal middleware, redirect, asset, and cache responses to avoid retaining stream resources.
There was a problem hiding this comment.
🟡 Changes recommended
The updated routing implementation introduces concrete correctness/type-safety issues in routingHandler.ts and an invalid routing mock shape in adapter.spec.ts that should be addressed before merging.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR migrates OpenNext’s routing resolution to Next’s @next/routing package, replacing the project’s custom route matching/redirect/rewrite logic. It also introduces a build-time generated routing index (open-next-routing.json) that is packaged into runtime bundles and used by the new resolver-based routingHandler.
Changes:
- Replace custom routing matcher/route matcher flow with
@next/routing(resolveRoutes) and add priority-redirect handling to match Next’s canonicalization semantics. - Generate and bundle a runtime routing config (
.next/open-next-routing.json) and update config loaders/bundlers to consume it. - Add/adjust unit + e2e tests for resolver behavior (middleware matching, trailingSlash, priority redirects, routing normalization) and bump Next peer dependency to
16.2.1.
File summaries
| File | Description |
|---|---|
| pnpm-lock.yaml | Locks @next/routing@16.2.1 and updates Next versions to 16.2.1. |
| packages/tests-unit/tests/core/routing/routingHandler.trailingSlash.test.ts | Adds unit coverage for trailing-slash canonicalization and _next/data behavior. |
| packages/tests-unit/tests/core/routing/routingHandler.test.ts | Adds unit coverage for resolver-based routing outputs (redirects/rewrites/ISR flags). |
| packages/tests-unit/tests/core/routing/routingHandler.middleware.test.ts | Adds unit coverage for middleware matcher behavior and body forwarding. |
| packages/tests-unit/tests/core/routing/routeMatcher.test.ts | Removes tests for deleted custom route matcher. |
| packages/tests-unit/tests/core/routing/priorityRoutes.test.ts | Adds unit coverage for hoisted “priority” redirect behavior. |
| packages/tests-unit/tests/core/routing/middleware.test.ts | Adds tests for _next/data normalization used by middleware matching. |
| packages/tests-unit/tests/core/routing/matcher.test.ts | Removes tests for deleted custom matcher/redirect/rewrite implementation. |
| packages/tests-unit/tests/build/normalizeRouting.test.ts | Adds tests for build-time route normalization to match resolver expectations. |
| packages/tests-unit/tests/build/createRoutingConfig.test.ts | Adds tests for generating open-next-routing.json route index + pathnames. |
| packages/tests-e2e/tests/appRouter/middleware.rewrite.test.ts | Fixes missing await on async assertion. |
| packages/tests-e2e/tests/appRouter/headers.test.ts | Updates test doc comment after removal of dangerous flag. |
| packages/core/src/types/open-next.ts | Removes deprecated dangerous option and adds ResolvedRoute.isISR?. |
| packages/core/src/types/adapter.ts | Types outputs/routing config around resolver (ResolveRoutesParams) and adds routing config shape. |
| packages/core/src/plugins/edge.ts | Switches edge config embedding to use loadRoutingConfig instead of multiple manifests. |
| packages/core/src/core/routingHandler.ts | Reimplements routing via @next/routing, adds priority redirects, routing config lookup, and new middleware invocation plumbing. |
| packages/core/src/core/routing/routeMatcher.ts | Deletes custom route matcher implementation. |
| packages/core/src/core/routing/priorityRoutes.ts | Adds support for matching Next “priority” redirects against the incoming request. |
| packages/core/src/core/routing/middleware.ts | Adds getMiddlewareMatchPath + refactors middleware gating into shouldInvokeMiddleware. |
| packages/core/src/core/routing/matcher.ts | Deletes custom redirect/rewrite/data normalization implementation. |
| packages/core/src/build/normalizeRouting.ts | Adds build-time normalization (localization variants, redirect destinations, has-capture alignment). |
| packages/core/src/build/middleware/buildNodeMiddleware.ts | Ensures routing config file is bundled for external node middleware output. |
| packages/core/src/build/middleware/buildNodeMiddleware.spec.ts | Updates expectations for bundling open-next-routing.json and output typing changes. |
| packages/core/src/build/createServerBundle.ts | Copies open-next-routing.json into the server bundle output for runtime consumption. |
| packages/core/src/build/createRoutingConfig.ts | Generates open-next-routing.json with pathnames and an executable-route index (incl. prerenders). |
| packages/core/src/build/adapter.ts | Adds routing config generation step during onBuildComplete. |
| packages/core/src/build/adapter.spec.ts | Updates tests for new build context fields and routing config generation (mock routing shape needs adjustment). |
| packages/core/src/adapters/config/util.ts | Adds loadRoutingConfig and removes old routes-manifest/header helpers. |
| packages/core/src/adapters/config/index.ts | Exposes RoutingConfig and drops exports for removed manifests/headers. |
| packages/core/package.json | Adds dependency on @next/routing and pins next peer dependency to 16.2.1. |
| packages/cloudflare/src/cli/utils/nextjs-support.ts | Raises minimum supported Next.js version to 16.2.1. |
| packages/cloudflare/src/cli/utils/nextjs-support.spec.ts | Adds tests for the updated minimum supported Next.js version logic. |
| packages/cloudflare/package.json | Aligns Next peer dependency/version sourcing with 16.2.1. |
| packages/aws/package.json | Pins Next peer dependency to 16.2.1. |
| examples/app-router/proxy.ts | Updates comments after removal of the dangerous middleware header override flag. |
| examples/app-router/open-next.config.ts | Removes dangerous.middlewareHeadersOverrideNextConfigHeaders example config. |
| examples-cloudflare/playground16/package.json | Updates Next dependency to 16.2.1. |
| examples-cloudflare/e2e/app-router/proxy.ts | Updates comments after removal of the dangerous middleware header override flag. |
| examples-cloudflare/e2e/app-router/open-next.config.ts | Removes dangerous.middlewareHeadersOverrideNextConfigHeaders from e2e config. |
| examples-cloudflare/e2e/app-router/e2e/middleware.rewrite.test.ts | Fixes missing await on async assertion. |
| examples-cloudflare/e2e/app-router/e2e/headers.test.ts | Updates test doc comment after removal of dangerous flag. |
Review details
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
- Files reviewed: 40/41 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Replace the obsolete redirects fixture key with the beforeMiddleware and onMatch groups required by @next/routing. This keeps the adapter build test representative of the routing contract emitted by Next.js.
Only decode the OpenNext city header when it is present. This prevents middleware requests without geo metadata from receiving the literal string 'undefined' as their city.
Keep array-valued headers on direct InternalResult responses, but serialize them when response headers are prefixed onto an InternalEvent. This preserves the request event's Record<string, string> contract while retaining multi-value response support.
vicb
left a comment
There was a problem hiding this comment.
Thanks @conico974 for the PR 🎉
I have moved @next/routing to a peer dep as you suggested.
The last couple commits merge the latest main and use pnpm@11
Use @next/routing instead of our own