diff --git a/packages/cloudflare/src/cli/build/patches/to-investigate/wrangler-deps.ts b/packages/cloudflare/src/cli/build/patches/to-investigate/wrangler-deps.ts index 6240999a..09a5a5e6 100644 --- a/packages/cloudflare/src/cli/build/patches/to-investigate/wrangler-deps.ts +++ b/packages/cloudflare/src/cli/build/patches/to-investigate/wrangler-deps.ts @@ -5,6 +5,7 @@ import path from "node:path"; export function patchWranglerDeps(config: Config) { console.log("# patchWranglerDeps"); + const distPath = getDistPath(config); // Patch .next/standalone/node_modules/next/dist/compiled/next-server/pages.runtime.prod.js // // Remove the need for an alias in wrangler.toml: @@ -12,15 +13,7 @@ export function patchWranglerDeps(config: Config) { // [alias] // # critters is `require`d from `pages.runtime.prod.js` when running wrangler dev, so we need to stub it out // "critters" = "./.next/standalone/node_modules/cf/templates/shims/empty.ts" - const pagesRuntimeFile = path.join( - config.paths.standaloneApp, - "node_modules", - "next", - "dist", - "compiled", - "next-server", - "pages.runtime.prod.js" - ); + const pagesRuntimeFile = path.join(distPath, "compiled", "next-server", "pages.runtime.prod.js"); const patchedPagesRuntime = fs .readFileSync(pagesRuntimeFile, "utf-8") @@ -38,16 +31,7 @@ export function patchWranglerDeps(config: Config) { // # try block here: https://github.com/vercel/next.js/blob/9e8266a7/packages/next/src/server/lib/trace/tracer.ts#L27-L31 // # causing the code to require the 'next/dist/compiled/@opentelemetry/api' module instead (which properly works) // #"@opentelemetry/api" = "./.next/standalone/node_modules/cf/templates/shims/throw.ts" - const tracerFile = path.join( - config.paths.standaloneApp, - "node_modules", - "next", - "dist", - "server", - "lib", - "trace", - "tracer.js" - ); + const tracerFile = path.join(distPath, "server", "lib", "trace", "tracer.js"); const pacthedTracer = fs .readFileSync(tracerFile, "utf-8") @@ -55,3 +39,28 @@ export function patchWranglerDeps(config: Config) { writeFileSync(tracerFile, pacthedTracer); } + +/** + * Next.js saves the node_modules/next/dist directory in either the standaloneApp path or in the + * standaloneRoot path, this depends on where the next dependency is actually saved ( + * https://github.com/vercel/next.js/blob/39e06c75/packages/next/src/build/webpack-config.ts#L103-L104 + * ) and can depend on the package manager used, if it is using workspaces, etc... + * + * This function checks the two potential paths for the dist directory and returns the first that it finds, + * it throws an error if it can't find either + * + * @param config + * @returns the node_modules/next/dist directory path + */ +function getDistPath(config: Config): string { + for (const root of [config.paths.standaloneApp, config.paths.standaloneRoot]) { + try { + const distPath = path.join(root, "node_modules", "next", "dist"); + if (fs.statSync(distPath).isDirectory()) return distPath; + } catch { + /* empty */ + } + } + + throw new Error("Unexpected error: unable to detect the node_modules/next/dist directory"); +} diff --git a/packages/cloudflare/src/cli/config.ts b/packages/cloudflare/src/cli/config.ts index 140d40c6..65c34343 100644 --- a/packages/cloudflare/src/cli/config.ts +++ b/packages/cloudflare/src/cli/config.ts @@ -18,6 +18,8 @@ export type Config = { builderOutput: string; // Path to the app's `.next` directory (where `next build` saves the build output) dotNext: string; + // Path to the application standalone root directory + standaloneRoot: string; // Path to the application standalone directory (where `next build` saves the standalone app) standaloneApp: string; // Path to the `.next` directory specific to the standalone application @@ -47,7 +49,8 @@ export type Config = { export function getConfig(appDir: string, outputDir: string): Config { const dotNext = path.join(outputDir, ".next"); const appPath = getNextjsApplicationPath(dotNext).replace(/\/$/, ""); - const standaloneApp = path.join(dotNext, "standalone", appPath); + const standaloneRoot = path.join(dotNext, "standalone"); + const standaloneApp = path.join(standaloneRoot, appPath); const standaloneAppDotNext = path.join(standaloneApp, ".next"); const standaloneAppServer = path.join(standaloneAppDotNext, "server"); @@ -59,6 +62,7 @@ export function getConfig(appDir: string, outputDir: string): Config { nextApp: appDir, builderOutput: outputDir, dotNext, + standaloneRoot, standaloneApp, standaloneAppDotNext, standaloneAppServer, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 69ba3d0d..13ec8594 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1617,9 +1617,6 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} - caniuse-lite@1.0.30001651: - resolution: {integrity: sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==} - caniuse-lite@1.0.30001664: resolution: {integrity: sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==} @@ -4586,7 +4583,7 @@ snapshots: autoprefixer@10.4.20(postcss@8.4.47): dependencies: browserslist: 4.24.0 - caniuse-lite: 1.0.30001651 + caniuse-lite: 1.0.30001664 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.1.0 @@ -4652,8 +4649,6 @@ snapshots: camelcase-css@2.0.1: {} - caniuse-lite@1.0.30001651: {} - caniuse-lite@1.0.30001664: {} capnp-ts@0.7.0: @@ -5861,7 +5856,7 @@ snapshots: '@swc/counter': 0.1.3 '@swc/helpers': 0.5.12 busboy: 1.6.0 - caniuse-lite: 1.0.30001651 + caniuse-lite: 1.0.30001664 graceful-fs: 4.2.11 postcss: 8.4.31 react: 19.0.0-rc-3208e73e-20240730