diff --git a/.changeset/friendly-ears-ring.md b/.changeset/friendly-ears-ring.md new file mode 100644 index 00000000..b3dd561d --- /dev/null +++ b/.changeset/friendly-ears-ring.md @@ -0,0 +1,10 @@ +--- +"@opennextjs/cloudflare": patch +--- + +fix: make sure that the `initOpenNextCloudflareForDev()` logic runs only once + +Currently calling `initOpenNextCloudflareForDev()` in the Next.js config file causes +this initialization logic to run twice, consuming more resources and causing extra +noise in the terminal logs, this change makes sure that the initialization logic +is run only once instead diff --git a/packages/cloudflare/src/api/cloudflare-context.ts b/packages/cloudflare/src/api/cloudflare-context.ts index e9c39edf..6a71c503 100644 --- a/packages/cloudflare/src/api/cloudflare-context.ts +++ b/packages/cloudflare/src/api/cloudflare-context.ts @@ -89,6 +89,9 @@ export function getCloudflareContext< * Note: this function should only be called inside the Next.js config file, and although async it doesn't need to be `await`ed */ export async function initOpenNextCloudflareForDev() { + const shouldInitializationRun = shouldContextInitializationRun(); + if (!shouldInitializationRun) return; + const context = await getCloudflareContextFromWrangler(); addCloudflareContextToNodejsGlobal(context); @@ -96,6 +99,22 @@ export async function initOpenNextCloudflareForDev() { await monkeyPatchVmModuleEdgeContext(context); } +/** + * Next dev server imports the config file twice (in two different processes, making it hard to track), + * this causes the initialization to run twice as well, to keep things clean, not allocate extra + * resources (i.e. instantiate two miniflare instances) and avoid extra potential logs, it would be best + * to run the initialization only once, this function is used to try to make it so that it does, it returns + * a flag which indicates if the initialization should run in the current process or not. + * + * @returns boolean indicating if the initialization should run + */ +function shouldContextInitializationRun(): boolean { + // via debugging we've seen that AsyncLocalStorage is only set in one of the + // two processes so we're using it as the differentiator between the two + const AsyncLocalStorage = (globalThis as unknown as { AsyncLocalStorage?: unknown })["AsyncLocalStorage"]; + return !!AsyncLocalStorage; +} + /** * Adds the cloudflare context to the global scope in which the Next.js dev node.js process runs in, enabling * future calls to `getCloudflareContext` to retrieve and return such context