fix: add Next.js 16.1.0 compatibility for fast-set-immediate module#1055
fix: add Next.js 16.1.0 compatibility for fast-set-immediate module#1055dulapahv wants to merge 3 commits intoopennextjs:mainfrom
Conversation
🦋 Changeset detectedLatest commit: b04debb The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Pull request overview
This PR adds compatibility for Next.js 16.1.0 by introducing an esbuild plugin that shims the problematic fast-set-immediate.external module, which attempts to assign to read-only exports during bundling and causes startup crashes on Cloudflare Workers.
- Created a new esbuild plugin to intercept and replace the
fast-set-immediate.externalmodule with a shim - Integrated the plugin into the server bundling process
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/cloudflare/src/cli/build/patches/plugins/fast-set-immediate.ts | New esbuild plugin that intercepts the fast-set-immediate module and provides shimmed exports to prevent read-only property assignment errors |
| packages/cloudflare/src/cli/build/bundle-server.ts | Imports and registers the new fast-set-immediate shim plugin in the esbuild plugins array |
| .changeset/deep-breads-camp.md | Changeset documentation describing the fix for Next.js 16.1.0 compatibility |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Great finding @dulapahv ! Note that cloudflare/workerd#5662 should help here too |
|
Thanks for the feedback. From what I understand is that the Next.js's function install() {
if (process.env.NEXT_RUNTIME === 'edge') {
// Nothing to patch. The exported functions all error if used in the edge runtime,
// so we're not going to violate any assumptions by not patching.
return
} else {
debug?.('installing fast setImmediate patch')
const nodeTimers = require('node:timers') as typeof import('node:timers')
// ⚠️ THIS LINE FAILS WHEN BUNDLED TO ESM
globalThis.setImmediate = nodeTimers.setImmediate =
// Workaround for missing __promisify__ which is not a real property
patchedSetImmediate as unknown as typeof setImmediate
globalThis.clearImmediate = nodeTimers.clearImmediate =
patchedClearImmediate
const nodeTimersPromises =
require('node:timers/promises') as typeof import('node:timers/promises')
nodeTimersPromises.setImmediate =
patchedSetImmediatePromise as typeof import('node:timers/promises').setImmediate
process.nextTick = patchedNextTick
}
}
// Called at module load time
install()The problem is this part: globalThis.setImmediate = nodeTimers.setImmediate = patchedSetImmediateThis works in Node.js with CommonJS because This happens at module initialization time when I don't fully understand what Next.js relies on this patch for beyond the timing optimization described in this PR. I can't confidently say there are no side effects from shimming this out. |
|
Maybe until this PR is merged you could say it in the documentation. I'm sorry if I'm bothering but I just spent half my day trying to debug this just to find this PR. |
The problem is that a lot of users don't read the docs https://opennext.js.org/cloudflare#supported-nextjs-versions ;) |
Ok my bad but maybe you can put a link to the issue page as I think it could be very relevant for this specific project because Next.js is very easy to pinpoint what the known problem are? |
Yep I think this can be close. |
Next.js 16.1.0 introduced a new internal module (
fast-set-immediate.external.js) that attempts to assign to read-only module exports during the esbuild bundling process. This causes a startup crash on Cloudflare Workers with the error:Fixes #1049
Changes
fast-set-immediate.externalmodule and replaces it with a shim.Verified by building the
playground16example project with Next.js 16.1.0. Shimmed exports exist in the bundle at.open-next/server-functions/default/examples/playground16/handler.mjsand this error no longer occur.