@opennextjs/cloudflare 1.11.1 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -43,9 +43,10 @@ const optionalDependencies = [
43
43
  export async function bundleServer(buildOpts, projectOpts) {
44
44
  copyPackageCliFiles(packageDistDir, buildOpts);
45
45
  const { appPath, outputDir, monorepoRoot, debug } = buildOpts;
46
- const baseManifestPath = path.join(outputDir, "server-functions/default", getPackagePath(buildOpts), ".next");
47
- const serverFiles = path.join(baseManifestPath, "required-server-files.json");
46
+ const dotNextPath = path.join(outputDir, "server-functions/default", getPackagePath(buildOpts), ".next");
47
+ const serverFiles = path.join(dotNextPath, "required-server-files.json");
48
48
  const nextConfig = JSON.parse(fs.readFileSync(serverFiles, "utf-8")).config;
49
+ const useTurbopack = fs.existsSync(path.join(dotNextPath, "server/chunks/[turbopack]_runtime.js"));
49
50
  console.log(`\x1b[35m⚙️ Bundling the OpenNext server...\n\x1b[0m`);
50
51
  await patchWebpackRuntime(buildOpts);
51
52
  patchVercelOgLibrary(buildOpts);
@@ -118,13 +119,12 @@ export async function bundleServer(buildOpts, projectOpts) {
118
119
  // Note: we need the __non_webpack_require__ variable declared as it is used by next-server:
119
120
  // https://github.com/vercel/next.js/blob/be0c3283/packages/next/src/server/next-server.ts#L116-L119
120
121
  __non_webpack_require__: "require",
122
+ // The 2 following defines are used to reduce the bundle size by removing unnecessary code
123
+ // Next uses different precompiled renderers (i.e. `app-page.runtime.prod.js`) based on if you use `TURBOPACK` or some experimental React features
124
+ ...(useTurbopack ? {} : { "process.env.TURBOPACK": "false" }),
121
125
  // We make sure that environment variables that Next.js expects are properly defined
122
126
  "process.env.NEXT_RUNTIME": '"nodejs"',
123
127
  "process.env.NODE_ENV": '"production"',
124
- // The 2 following defines are used to reduce the bundle size by removing unnecessary code
125
- // Next uses different precompiled renderers (i.e. `app-page.runtime.prod.js`) based on if you use `TURBOPACK` or some experimental React features
126
- // Turbopack is not supported for build at the moment, so we disable it
127
- "process.env.TURBOPACK": "false",
128
128
  // This define should be safe to use for Next 14.2+, earlier versions (13.5 and less) will cause trouble
129
129
  "process.env.__NEXT_EXPERIMENTAL_REACT": `${needsExperimentalReact(nextConfig)}`,
130
130
  // Fix `res.validate` in Next 15.4 (together with the `route-module` patch)
@@ -20,6 +20,7 @@ import { openNextResolvePlugin } from "@opennextjs/aws/plugins/resolve.js";
20
20
  import { getCrossPlatformPathRegex } from "@opennextjs/aws/utils/regex.js";
21
21
  import { getOpenNextConfig } from "../../../api/config.js";
22
22
  import { patchResRevalidate } from "../patches/plugins/res-revalidate.js";
23
+ import { patchTurbopackRuntime } from "../patches/plugins/turbopack.js";
23
24
  import { patchUseCacheIO } from "../patches/plugins/use-cache.js";
24
25
  import { normalizePath } from "../utils/index.js";
25
26
  import { copyWorkerdPackages } from "../utils/workerd.js";
@@ -142,6 +143,7 @@ async function generateBundle(name, options, fnOptions, codeCustomization) {
142
143
  // Cloudflare specific patches
143
144
  patchResRevalidate,
144
145
  patchUseCacheIO,
146
+ patchTurbopackRuntime,
145
147
  ...additionalCodePatches,
146
148
  ]);
147
149
  // Build Lambda code
@@ -16,6 +16,7 @@ export function patchVercelOgLibrary(buildOpts) {
16
16
  for (const traceInfoPath of globSync(path.join(appBuildOutputPath, ".next/server/**/*.nft.json"), {
17
17
  windowsPathsNoEscape: true,
18
18
  })) {
19
+ let edgeFilePatched = false;
19
20
  const traceInfo = JSON.parse(readFileSync(traceInfoPath, { encoding: "utf8" }));
20
21
  const tracedNodePath = traceInfo.files.find((p) => p.endsWith("@vercel/og/index.node.js"));
21
22
  if (!tracedNodePath)
@@ -26,14 +27,20 @@ export function patchVercelOgLibrary(buildOpts) {
26
27
  if (!existsSync(outputEdgePath)) {
27
28
  const tracedEdgePath = path.join(path.dirname(traceInfoPath), tracedNodePath.replace("index.node.js", "index.edge.js"));
28
29
  copyFileSync(tracedEdgePath, outputEdgePath);
30
+ }
31
+ if (!edgeFilePatched) {
32
+ edgeFilePatched = true;
29
33
  // Change font fetches in the library to use imports.
30
34
  const node = parseFile(outputEdgePath);
31
35
  const { edits, matches } = patchVercelOgFallbackFont(node);
32
36
  writeFileSync(outputEdgePath, node.commitEdits(edits));
33
- const fontFileName = matches[0].getMatch("PATH").text();
34
- renameSync(path.join(outputDir, fontFileName), path.join(outputDir, `${fontFileName}.bin`));
37
+ if (matches.length > 0) {
38
+ const fontFileName = matches[0].getMatch("PATH").text();
39
+ renameSync(path.join(outputDir, fontFileName), path.join(outputDir, `${fontFileName}.bin`));
40
+ }
35
41
  }
36
42
  // Change node imports for the library to edge imports.
43
+ // This is only useful when turbopack is not used to bundle the function.
37
44
  const routeFilePath = traceInfoPath.replace(appBuildOutputPath, packagePath).replace(".nft.json", "");
38
45
  const node = parseFile(routeFilePath);
39
46
  const { edits } = patchVercelOgImport(node);
@@ -0,0 +1,2 @@
1
+ import type { CodePatcher } from "@opennextjs/aws/build/patch/codePatcher.js";
2
+ export declare const patchTurbopackRuntime: CodePatcher;
@@ -0,0 +1,78 @@
1
+ import { patchCode } from "@opennextjs/aws/build/patch/astCodePatcher.js";
2
+ import { getCrossPlatformPathRegex } from "@opennextjs/aws/utils/regex.js";
3
+ const inlineChunksRule = `
4
+ rule:
5
+ kind: call_expression
6
+ pattern: require(resolved)
7
+ fix:
8
+ requireChunk(chunkPath)
9
+ `;
10
+ export const patchTurbopackRuntime = {
11
+ name: "inline-turbopack-chunks",
12
+ patches: [
13
+ {
14
+ versions: ">=15.0.0",
15
+ pathFilter: getCrossPlatformPathRegex(String.raw `\[turbopack\]_runtime\.js$`, {
16
+ escape: false,
17
+ }),
18
+ contentFilter: /loadRuntimeChunkPath/,
19
+ patchCode: async ({ code, tracedFiles }) => {
20
+ let patched = patchCode(code, inlineExternalImportRule);
21
+ patched = patchCode(patched, inlineChunksRule);
22
+ return `${patched}\n${inlineChunksFn(tracedFiles)}`;
23
+ },
24
+ },
25
+ ],
26
+ };
27
+ function getInlinableChunks(tracedFiles) {
28
+ const chunks = new Set();
29
+ for (const file of tracedFiles) {
30
+ if (file === "[turbopack]_runtime.js") {
31
+ continue;
32
+ }
33
+ if (file.includes(".next/server/chunks/")) {
34
+ chunks.add(file);
35
+ }
36
+ }
37
+ return Array.from(chunks);
38
+ }
39
+ function inlineChunksFn(tracedFiles) {
40
+ // From the outputs, we extract every chunks
41
+ const chunks = getInlinableChunks(tracedFiles);
42
+ return `
43
+ function requireChunk(chunkPath) {
44
+ switch(chunkPath) {
45
+ ${chunks
46
+ .map((chunk) => ` case "${
47
+ // we only want the path after /path/to/.next/
48
+ chunk.replace(/.*\/\.next\//, "")}": return require("${chunk}");`)
49
+ .join("\n")}
50
+ default:
51
+ throw new Error(\`Not found \${chunkPath}\`);
52
+ }
53
+ }
54
+ `;
55
+ }
56
+ // Turbopack imports `og` via `externalImport`.
57
+ // We patch it to:
58
+ // - add the explicit path so that the file is inlined by wrangler
59
+ // - use the edge version of the module instead of the node version.
60
+ //
61
+ // Modules that are not inlined (no added to the switch), would generate an error similar to:
62
+ // Failed to load external module path/to/module: Error: No such module "path/to/module"
63
+ const inlineExternalImportRule = `
64
+ rule:
65
+ pattern: "$RAW = await import($ID)"
66
+ inside:
67
+ regex: "externalImport"
68
+ kind: function_declaration
69
+ stopBy: end
70
+ fix: |-
71
+ switch ($ID) {
72
+ case "next/dist/compiled/@vercel/og/index.node.js":
73
+ $RAW = await import("next/dist/compiled/@vercel/og/index.edge.js");
74
+ break;
75
+ default:
76
+ $RAW = await import($ID);
77
+ }
78
+ `;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@opennextjs/cloudflare",
3
3
  "description": "Cloudflare builder for next apps",
4
- "version": "1.11.1",
4
+ "version": "1.12.0",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "opennextjs-cloudflare": "dist/cli/index.js"