From a79fe5c04d402dcdd4a9ae7d9d798edfb6faab38 Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Thu, 12 Dec 2024 17:07:39 +0000 Subject: [PATCH 1/3] temporary patch the `loadInstrumentationModule` methods to support Next.js 15 --- .../cloudflare/src/cli/build/bundle-server.ts | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/packages/cloudflare/src/cli/build/bundle-server.ts b/packages/cloudflare/src/cli/build/bundle-server.ts index bcd5e189..842ef2b8 100644 --- a/packages/cloudflare/src/cli/build/bundle-server.ts +++ b/packages/cloudflare/src/cli/build/bundle-server.ts @@ -5,6 +5,7 @@ import { fileURLToPath } from "node:url"; import type { BuildOptions } from "@opennextjs/aws/build/helper.js"; import { build, Plugin } from "esbuild"; +import * as ts from "ts-morph"; import { Config } from "../config"; import { copyPackageCliFiles } from "./patches/investigated/copy-package-cli-files"; @@ -18,7 +19,7 @@ import { patchExceptionBubbling } from "./patches/to-investigate/patch-exception import { patchFindDir } from "./patches/to-investigate/patch-find-dir"; import { patchReadFile } from "./patches/to-investigate/patch-read-file"; import { patchWranglerDeps } from "./patches/to-investigate/wrangler-deps"; -import { copyPrerenderedRoutes } from "./utils"; +import { copyPrerenderedRoutes, tsParseFile } from "./utils"; /** The dist directory of the Cloudflare adapter package */ const packageDistDir = path.join(path.dirname(fileURLToPath(import.meta.url)), ".."); @@ -139,6 +140,39 @@ globalThis.__dangerous_ON_edge_converter_returns_request = true; console.log(`\x1b[35mWorker saved in \`${openNextServerBundle}\` 🚀\n\x1b[0m`); } +/** + * The `loadInstrumentationModule` method (source: https://github.com/vercel/next.js/blob/5b7833e3/packages/next/src/server/next-server.ts#L301) + * calls `module.findSourceMap` (https://nodejs.org/api/module.html#modulefindsourcemappath) which we haven't implemented causing a runtime error. + * + * To solve this issue this function gets all the `loadInstrumentationModule` declarations found in the file and removes all the statements + * from their bodies (making them no-op methods). + * + * Instrumentation is a Next.js feature for monitoring and logging (see: https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation), + * the removal of this method's logic most likely breaks this feature (see: https://nextjs.org/docs/app/api-reference/file-conventions/instrumentation), + * so this function is likely temporary and something that we'll have to fix in the future. + */ +export function patchLoadInstrumentationModule(file: ts.SourceFile): ts.SourceFile { + const loadInstrumentationModuleDeclarations = file + .getDescendantsOfKind(ts.SyntaxKind.MethodDeclaration) + .filter((methodDeclaration) => { + if (methodDeclaration.getName() !== "loadInstrumentationModule") { + return false; + } + const methodModifierKinds = methodDeclaration.getModifiers().map((modifier) => modifier.getKind()); + if (methodModifierKinds.length !== 1 || methodModifierKinds[0] !== ts.SyntaxKind.AsyncKeyword) { + return false; + } + + return true; + }); + + loadInstrumentationModuleDeclarations.forEach((loadInstrumentationModuleDeclaration) => { + loadInstrumentationModuleDeclaration.setBodyText(""); + }); + + return file; +} + /** * This function applies string replacements on the bundled worker code necessary to get it to run in workerd * @@ -164,6 +198,7 @@ async function updateWorkerBundledCode( patchedCode = await patchCache(patchedCode, openNextOptions); patchedCode = inlineMiddlewareManifestRequire(patchedCode, config); patchedCode = patchExceptionBubbling(patchedCode); + patchedCode = patchLoadInstrumentationModule(tsParseFile(patchedCode)).print(); patchedCode = patchedCode // workers do not support dynamic require nor require.resolve From da55ad40a96981937605bb5609106c6d0dd5ac6c Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Thu, 12 Dec 2024 17:18:14 +0000 Subject: [PATCH 2/3] link to #160 in function's comment --- packages/cloudflare/src/cli/build/bundle-server.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/cloudflare/src/cli/build/bundle-server.ts b/packages/cloudflare/src/cli/build/bundle-server.ts index 842ef2b8..f1b0129c 100644 --- a/packages/cloudflare/src/cli/build/bundle-server.ts +++ b/packages/cloudflare/src/cli/build/bundle-server.ts @@ -150,6 +150,8 @@ globalThis.__dangerous_ON_edge_converter_returns_request = true; * Instrumentation is a Next.js feature for monitoring and logging (see: https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation), * the removal of this method's logic most likely breaks this feature (see: https://nextjs.org/docs/app/api-reference/file-conventions/instrumentation), * so this function is likely temporary and something that we'll have to fix in the future. + * + * TODO: investigate and re-enable instrumentation (https://github.com/opennextjs/opennextjs-cloudflare/issues/160) */ export function patchLoadInstrumentationModule(file: ts.SourceFile): ts.SourceFile { const loadInstrumentationModuleDeclarations = file From c552305dd576e2f9838bca02934667141ab1142b Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Thu, 12 Dec 2024 23:16:20 +0000 Subject: [PATCH 3/3] apply PR suggestions --- .../cloudflare/src/cli/build/bundle-server.ts | 41 ++----------------- .../patch-load-instrumentation-module.ts | 39 ++++++++++++++++++ 2 files changed, 42 insertions(+), 38 deletions(-) create mode 100644 packages/cloudflare/src/cli/build/patches/to-investigate/patch-load-instrumentation-module.ts diff --git a/packages/cloudflare/src/cli/build/bundle-server.ts b/packages/cloudflare/src/cli/build/bundle-server.ts index f1b0129c..ade9c16e 100644 --- a/packages/cloudflare/src/cli/build/bundle-server.ts +++ b/packages/cloudflare/src/cli/build/bundle-server.ts @@ -5,7 +5,6 @@ import { fileURLToPath } from "node:url"; import type { BuildOptions } from "@opennextjs/aws/build/helper.js"; import { build, Plugin } from "esbuild"; -import * as ts from "ts-morph"; import { Config } from "../config"; import { copyPackageCliFiles } from "./patches/investigated/copy-package-cli-files"; @@ -17,9 +16,10 @@ import { inlineMiddlewareManifestRequire } from "./patches/to-investigate/inline import { inlineNextRequire } from "./patches/to-investigate/inline-next-require"; import { patchExceptionBubbling } from "./patches/to-investigate/patch-exception-bubbling"; import { patchFindDir } from "./patches/to-investigate/patch-find-dir"; +import { patchLoadInstrumentationModule } from "./patches/to-investigate/patch-load-instrumentation-module"; import { patchReadFile } from "./patches/to-investigate/patch-read-file"; import { patchWranglerDeps } from "./patches/to-investigate/wrangler-deps"; -import { copyPrerenderedRoutes, tsParseFile } from "./utils"; +import { copyPrerenderedRoutes } from "./utils"; /** The dist directory of the Cloudflare adapter package */ const packageDistDir = path.join(path.dirname(fileURLToPath(import.meta.url)), ".."); @@ -140,41 +140,6 @@ globalThis.__dangerous_ON_edge_converter_returns_request = true; console.log(`\x1b[35mWorker saved in \`${openNextServerBundle}\` 🚀\n\x1b[0m`); } -/** - * The `loadInstrumentationModule` method (source: https://github.com/vercel/next.js/blob/5b7833e3/packages/next/src/server/next-server.ts#L301) - * calls `module.findSourceMap` (https://nodejs.org/api/module.html#modulefindsourcemappath) which we haven't implemented causing a runtime error. - * - * To solve this issue this function gets all the `loadInstrumentationModule` declarations found in the file and removes all the statements - * from their bodies (making them no-op methods). - * - * Instrumentation is a Next.js feature for monitoring and logging (see: https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation), - * the removal of this method's logic most likely breaks this feature (see: https://nextjs.org/docs/app/api-reference/file-conventions/instrumentation), - * so this function is likely temporary and something that we'll have to fix in the future. - * - * TODO: investigate and re-enable instrumentation (https://github.com/opennextjs/opennextjs-cloudflare/issues/160) - */ -export function patchLoadInstrumentationModule(file: ts.SourceFile): ts.SourceFile { - const loadInstrumentationModuleDeclarations = file - .getDescendantsOfKind(ts.SyntaxKind.MethodDeclaration) - .filter((methodDeclaration) => { - if (methodDeclaration.getName() !== "loadInstrumentationModule") { - return false; - } - const methodModifierKinds = methodDeclaration.getModifiers().map((modifier) => modifier.getKind()); - if (methodModifierKinds.length !== 1 || methodModifierKinds[0] !== ts.SyntaxKind.AsyncKeyword) { - return false; - } - - return true; - }); - - loadInstrumentationModuleDeclarations.forEach((loadInstrumentationModuleDeclaration) => { - loadInstrumentationModuleDeclaration.setBodyText(""); - }); - - return file; -} - /** * This function applies string replacements on the bundled worker code necessary to get it to run in workerd * @@ -200,7 +165,7 @@ async function updateWorkerBundledCode( patchedCode = await patchCache(patchedCode, openNextOptions); patchedCode = inlineMiddlewareManifestRequire(patchedCode, config); patchedCode = patchExceptionBubbling(patchedCode); - patchedCode = patchLoadInstrumentationModule(tsParseFile(patchedCode)).print(); + patchedCode = patchLoadInstrumentationModule(patchedCode); patchedCode = patchedCode // workers do not support dynamic require nor require.resolve diff --git a/packages/cloudflare/src/cli/build/patches/to-investigate/patch-load-instrumentation-module.ts b/packages/cloudflare/src/cli/build/patches/to-investigate/patch-load-instrumentation-module.ts new file mode 100644 index 00000000..06d7f0ed --- /dev/null +++ b/packages/cloudflare/src/cli/build/patches/to-investigate/patch-load-instrumentation-module.ts @@ -0,0 +1,39 @@ +import * as ts from "ts-morph"; + +import { tsParseFile } from "../../utils"; + +/** + * The `loadInstrumentationModule` method (source: https://github.com/vercel/next.js/blob/5b7833e3/packages/next/src/server/next-server.ts#L301) + * calls `module.findSourceMap` (https://nodejs.org/api/module.html#modulefindsourcemappath) which we haven't implemented causing a runtime error. + * + * To solve this issue this function gets all the `loadInstrumentationModule` declarations found in the file and removes all the statements + * from their bodies (making them no-op methods). + * + * Instrumentation is a Next.js feature for monitoring and logging (see: https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation), + * the removal of this method's logic most likely breaks this feature (see: https://nextjs.org/docs/app/api-reference/file-conventions/instrumentation), + * so this function is likely temporary and something that we'll have to fix in the future. + * + * TODO: investigate and re-enable instrumentation (https://github.com/opennextjs/opennextjs-cloudflare/issues/171) + */ +export function patchLoadInstrumentationModule(code: string) { + const file = tsParseFile(code); + const loadInstrumentationModuleDeclarations = file + .getDescendantsOfKind(ts.SyntaxKind.MethodDeclaration) + .filter((methodDeclaration) => { + if (methodDeclaration.getName() !== "loadInstrumentationModule") { + return false; + } + const methodModifierKinds = methodDeclaration.getModifiers().map((modifier) => modifier.getKind()); + if (methodModifierKinds.length !== 1 || methodModifierKinds[0] !== ts.SyntaxKind.AsyncKeyword) { + return false; + } + + return true; + }); + + loadInstrumentationModuleDeclarations.forEach((loadInstrumentationModuleDeclaration) => { + loadInstrumentationModuleDeclaration.setBodyText(""); + }); + + return file.print(); +}