Skip to content

Commit 2018756

Browse files
committed
patch node-module-loader dynamic require
1 parent 0bd0439 commit 2018756

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

packages/cloudflare/src/cli/build/bundle-server.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { patchFetchCacheSetMissingWaitUntil } from "./patches/plugins/fetch-cach
1616
import { inlineFindDir } from "./patches/plugins/find-dir.js";
1717
import { patchInstrumentation } from "./patches/plugins/instrumentation.js";
1818
import { inlineLoadManifest } from "./patches/plugins/load-manifest.js";
19+
import { inlineNodeModuleLoader } from "./patches/plugins/node-module-loader.js";
1920
import { handleOptionalDependencies } from "./patches/plugins/optional-deps.js";
2021
import { patchDepdDeprecations } from "./patches/plugins/patch-depd-deprecations.js";
2122
import { fixRequire } from "./patches/plugins/require.js";
@@ -89,6 +90,7 @@ export async function bundleServer(buildOpts: BuildOptions): Promise<void> {
8990
plugins: [
9091
shimRequireHook(buildOpts),
9192
inlineRequirePage(updater, buildOpts),
93+
inlineNodeModuleLoader(updater, buildOpts),
9294
setWranglerExternal(),
9395
fixRequire(updater),
9496
handleOptionalDependencies(optionalDependencies),
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { readFile } from "node:fs/promises";
2+
import { join } from "node:path";
3+
4+
import { type BuildOptions, getPackagePath } from "@opennextjs/aws/build/helper.js";
5+
import { getCrossPlatformPathRegex } from "@opennextjs/aws/utils/regex.js";
6+
7+
import { normalizePath } from "../../utils/normalize-path.js";
8+
import { patchCode, type RuleConfig } from "../ast/util.js";
9+
import type { ContentUpdater } from "./content-updater.js";
10+
11+
export function inlineNodeModuleLoader(updater: ContentUpdater, buildOpts: BuildOptions) {
12+
return updater.updateContent(
13+
"inline-node-module-loader",
14+
{
15+
filter: getCrossPlatformPathRegex(
16+
String.raw`/next/dist/server/lib/module-loader/node-module-loader\.js$`,
17+
{ escape: false }
18+
),
19+
contentFilter: /class NodeModuleLoader {/,
20+
},
21+
async ({ contents }) => patchCode(contents, await getRule(buildOpts))
22+
);
23+
}
24+
25+
async function getRule(buildOpts: BuildOptions) {
26+
const { outputDir } = buildOpts;
27+
const serverDir = join(outputDir, "server-functions/default", getPackagePath(buildOpts), ".next/server");
28+
29+
const pagesManifestFile = join(serverDir, "pages-manifest.json");
30+
31+
let pagesManifests: string[] = [];
32+
try {
33+
pagesManifests = Object.values(JSON.parse(await readFile(pagesManifestFile, "utf-8")));
34+
} catch {
35+
// The file does not exist
36+
pagesManifests = [];
37+
}
38+
39+
const files = pagesManifests.map((path) => normalizePath(path));
40+
41+
// Inline fs access and dynamic requires that are not supported by workerd.
42+
const fnBody = `
43+
${files
44+
.map(
45+
(file) => `if (id.endsWith("${file}")) {
46+
return require(${JSON.stringify(join(serverDir, file))});
47+
}`
48+
)
49+
.join("\n")}
50+
`;
51+
52+
return {
53+
rule: {
54+
pattern: `class NodeModuleLoader {
55+
async load($ID) {
56+
$$$_BODY
57+
}
58+
}`,
59+
},
60+
fix: `class NodeModuleLoader {
61+
async load($ID) {
62+
${fnBody}
63+
}
64+
}`,
65+
} satisfies RuleConfig;
66+
}

0 commit comments

Comments
 (0)