Skip to content

Add support for node middleware in cloudflare - #38

Open
conico974 wants to merge 21 commits into
mainfrom
conico/node-middleware
Open

Add support for node middleware in cloudflare#38
conico974 wants to merge 21 commits into
mainfrom
conico/node-middleware

Conversation

@conico974

@conico974 conico974 commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Add support for node middleware in cloudflare


Open in Devin Review

@pkg-pr-new

pkg-pr-new Bot commented Jul 15, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/opennextjs/adapters-api/@opennextjs/aws@62258d3
npm i https://pkg.pr.new/opennextjs/adapters-api/@opennextjs/cloudflare@62258d3
npm i https://pkg.pr.new/opennextjs/adapters-api/@opennextjs/core@62258d3

commit: 62258d3

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 1 additional finding in Devin Review.

Open in Devin Review

Comment thread packages/cloudflare/src/cli/adapter.ts Outdated
@evanlong-me

Copy link
Copy Markdown

Independent validation (build + local runtime)

I hit this via Next 16 proxy.ts on Cloudflare (ERROR Node.js middleware is not currently supported) and tested this branch directly from source (conico/node-middleware @ e34ef09), because the published preview tarball is not installable outside the monorepo (@opennextjs/[email protected] is not on npm; https://pkg.pr.new/@opennextjs/cloudflare@38 currently resolves to the old opennextjs-cloudflare PR #38 / v1.5.3).

Baseline (released @opennextjs/[email protected])

Minimal Next 16.2.11 app with proxy.ts fails at adapter build:

ƒ Proxy (Middleware)
ERROR Node.js middleware is not currently supported. Consider switching to Edge Middleware.

This PR

Built the monorepo packages and ran the existing e2e app that already uses examples-cloudflare/e2e/app-router/proxy.ts:

# from repo root after pnpm install / package build
cd examples-cloudflare/e2e/app-router
node ../../../packages/cloudflare/dist/cli/index.js build
node ../../../packages/cloudflare/dist/cli/index.js preview -- --port 8799

Build: success. Output includes external middleware bundling:

Bundling middleware function...
Copying adapter files for external middleware...
Middleware created
ƒ Proxy (Middleware)
Worker saved in `.open-next/worker.js`

Worker entry wires middleware:

import { handler as middlewareHandler } from "./middleware/handler.mjs";

Runtime checks against local preview (http://127.0.0.1:8799):

Route Result
HEAD / 200, middleware cookies (from=middleware, with=love) + response-header: response-header
HEAD /redirect 307/redirect-destination, Set-Cookie: test=success
HEAD /cookies 200, Set-Cookie: foo=bar
GET /api/middleware 200 {"hello":"middleware"}
HEAD /rewrite 500 SyntaxError: Unexpected end of JSON input (may be HEAD-specific; flagging)

So the core Node/proxy.ts path works end-to-end for cookies / redirect / direct middleware response. This unblocks Next 16 apps that can no longer opt proxy.ts back to Edge.

Merge blockers I can see

  1. PR is stacked on conico/share-build (depends on Make a default overridable adapter in core #35), not main.
  2. GitHub currently reports mergeable_state: dirty vs conico/share-build — needs rebase.
  3. Preview install story is broken for external testers (@opennextjs/core not published; short pkg.pr.new URL points at the wrong repo). Publishing paired @opennextjs/cloudflare + @opennextjs/core previews (or documenting monorepo-only testing) would get more validation.

Happy to re-test after rebase, or run a fuller Playwright pass if useful. Real production apps (including mine) are still stuck on the middleware.ts deprecation workaround until this lands.

…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
…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.
@conico974
conico974 force-pushed the conico/share-build branch from 4e9a367 to cd8f83e Compare August 2, 2026 09:46
@conico974
conico974 force-pushed the conico/node-middleware branch from e34ef09 to 65cdda7 Compare August 2, 2026 09:54
IsmaelSandoval78 added a commit to IsmaelSandoval78/paddockintel-dashboard that referenced this pull request Aug 25, 2026
…dflare

Next.js 16 forces proxy.ts onto the Node.js middleware runtime with no
opt-out, and @opennextjs/cloudflare (1.20.2) doesn't support that yet —
verified locally, `opennextjs-cloudflare build` fails on a real proxy.ts.
middleware.ts + runtime: 'experimental-edge' builds clean on both next
build and opennextjs-cloudflare build, same routing logic unchanged.

Revert to proxy.ts once opennextjs/adapters-api#38 or
opennextjs/opennextjs-cloudflare#1320 (or their successor) ships on npm —
see docs/CLOUDFLARE-MIGRATION.md for the full investigation and why those
specific PR numbers, not "whenever OpenNext adds support" in general.
Base automatically changed from conico/share-build to main August 28, 2026 10:57
vicb added 2 commits August 31, 2026 09:33
# Conflicts:
#	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
Copilot AI lite review requested due to automatic review settings August 31, 2026 10:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class support for Node (non-edge) middleware in the Cloudflare adapter by making the Node middleware handler import path configurable at bundle time and wiring a dedicated middlewareBundle customization surface through the core build pipeline.

Changes:

  • Make the Node middleware handler dynamically import the middleware entry via an esbuild-defined constant (__OPEN_NEXT_NODE_MIDDLEWARE_PATH__).
  • Extend core build APIs to pass adapter outputs into middleware builds and add middlewareBundle customization (plugins/patches/banner/externals).
  • Add/adjust Cloudflare build patches (webpack runtime chunk inlining, Turbopack chunk normalization, OpenTelemetry global utils patch) and add unit/e2e coverage.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/tests-unit/tests/build/copyAdapterFiles.test.ts Adds unit tests for copyAdapterFiles, including custom destination support.
packages/core/src/core/nodeMiddlewareHandler.ts Switches Node middleware loading to a bundle-time-defined import path.
packages/core/src/build/middleware/buildNodeMiddleware.ts Updates external Node middleware build to copy adapter outputs, apply patches, and define the middleware import path.
packages/core/src/build/middleware/buildNodeMiddleware.spec.ts Adds unit tests for buildExternalNodeMiddleware customization and error handling.
packages/core/src/build/createMiddleware.ts Threads adapter outputs + middlewareBundle options into external Node middleware builds.
packages/core/src/build/copyAdapterFiles.ts Adds optional destination override for copying adapter files.
packages/core/src/build/adapter.ts Introduces middlewareBundle option and forwards outputs/bundle config into middleware creation.
packages/core/src/build/adapter.spec.ts Updates expectations for new createMiddleware call signature and adds forwarding test for middlewareBundle.
packages/cloudflare/src/cli/build/patches/plugins/turbopack.ts Normalizes traced Turbopack chunk paths and hardens generated requires.
packages/cloudflare/src/cli/build/patches/plugins/turbopack.spec.ts Adds tests for Turbopack runtime patch behavior (Windows paths, no chunks).
packages/cloudflare/src/cli/build/patches/plugins/opentelemetry.ts Adds patch to replace OpenTelemetry’s platform global usage with globalThis.
packages/cloudflare/src/cli/build/patches/plugins/opentelemetry.spec.ts Adds tests validating the OpenTelemetry global-utils patch.
packages/cloudflare/src/cli/build/patches/ast/webpack-runtime.ts Adds middleware-focused webpack runtime patch using traced chunk IDs; hardens chunks-dir handling.
packages/cloudflare/src/cli/build/patches/ast/webpack-runtime.spec.ts Adds tests for middleware webpack runtime patching behavior.
packages/cloudflare/src/cli/adapter.ts Configures the new middlewareBundle for Cloudflare (banner/plugins/patches) and adds OpenTelemetry + webpack middleware runtime patches.
examples-cloudflare/e2e/app-router/proxy.ts Updates example middleware export style for the app-router e2e setup.
examples-cloudflare/e2e/app-router/e2e/middleware.rewrite.test.ts Adds an e2e assertion for HEAD requests through middleware rewrite.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +194 to +196
await expect(buildExternalNodeMiddleware(options, undefined, {})).rejects.toThrow(
/without adapter outputs\.middleware/
);
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.

4 participants