Skip to content

Commit 47083f5

Browse files
authored
refactor: patch loadManifest using ast-grep (#393)
1 parent d51c81d commit 47083f5

File tree

4 files changed

+64
-36
lines changed

4 files changed

+64
-36
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { inlineEvalManifest } from "./patches/plugins/eval-manifest.js";
1414
import { patchFetchCacheSetMissingWaitUntil } from "./patches/plugins/fetch-cache-wait-until.js";
1515
import { inlineFindDir } from "./patches/plugins/find-dir.js";
1616
import { patchLoadInstrumentation } from "./patches/plugins/load-instrumentation.js";
17+
import { inlineLoadManifest } from "./patches/plugins/load-manifest.js";
1718
import { handleOptionalDependencies } from "./patches/plugins/optional-deps.js";
1819
import { fixRequire } from "./patches/plugins/require.js";
1920
import { shimRequireHook } from "./patches/plugins/require-hook.js";
@@ -93,6 +94,7 @@ export async function bundleServer(buildOpts: BuildOptions): Promise<void> {
9394
patchFetchCacheSetMissingWaitUntil(updater),
9495
inlineEvalManifest(updater, buildOpts),
9596
inlineFindDir(updater, buildOpts),
97+
inlineLoadManifest(updater, buildOpts),
9698
// Apply updater updaters, must be the last plugin
9799
updater.plugin,
98100
],
@@ -196,7 +198,6 @@ export async function updateWorkerBundledCode(
196198
const patchedCode = await patchCodeWithValidations(code, [
197199
["require", patches.patchRequire],
198200
["`buildId` function", (code) => patches.patchBuildId(code, buildOpts)],
199-
["`loadManifest` function", (code) => patches.patchLoadManifest(code, buildOpts)],
200201
["cacheHandler", (code) => patches.patchCache(code, buildOpts)],
201202
[
202203
"'require(this.middlewareManifestPath)'",

packages/cloudflare/src/cli/build/patches/plugins/eval-manifest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ function evalManifest($PATH, $$$ARGS) {
6161
fix: `
6262
function evalManifest($PATH, $$$ARGS) {
6363
${returnManifests}
64-
throw new Error("Unknown evalManifest: " + $PATH);
64+
throw new Error(\`Unexpected evalManifest(\${$PATH}) call!\`);
6565
}`,
6666
} satisfies RuleConfig;
6767
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Inline `loadManifest` as it relies on `readFileSync`that is not supported by workerd.
3+
*/
4+
5+
import { readFile } from "node:fs/promises";
6+
import { join, relative } from "node:path";
7+
8+
import { type BuildOptions, getPackagePath } from "@opennextjs/aws/build/helper.js";
9+
import { getCrossPlatformPathRegex } from "@opennextjs/aws/utils/regex.js";
10+
import { glob } from "glob";
11+
12+
import { normalizePath } from "../../utils/normalize-path.js";
13+
import { patchCode, type RuleConfig } from "../ast/util.js";
14+
import type { ContentUpdater } from "./content-updater.js";
15+
16+
export function inlineLoadManifest(updater: ContentUpdater, buildOpts: BuildOptions) {
17+
return updater.updateContent(
18+
"inline-load-manifest",
19+
{
20+
filter: getCrossPlatformPathRegex(String.raw`/next/dist/server/load-manifest\.js$`, { escape: false }),
21+
contentFilter: /function loadManifest\(/,
22+
},
23+
async ({ contents }) => patchCode(contents, await getRule(buildOpts))
24+
);
25+
}
26+
27+
async function getRule(buildOpts: BuildOptions) {
28+
const { outputDir } = buildOpts;
29+
30+
const baseDir = join(outputDir, "server-functions/default", getPackagePath(buildOpts));
31+
const dotNextDir = join(baseDir, ".next");
32+
33+
const manifests = await glob(join(dotNextDir, "**/*-manifest.json"));
34+
35+
const returnManifests = (
36+
await Promise.all(
37+
manifests.map(
38+
async (manifest) => `
39+
if ($PATH.endsWith("${normalizePath("/" + relative(dotNextDir, manifest))}")) {
40+
return ${await readFile(manifest, "utf-8")};
41+
}
42+
`
43+
)
44+
)
45+
).join("\n");
46+
47+
return {
48+
rule: {
49+
pattern: `
50+
function loadManifest($PATH, $$$ARGS) {
51+
$$$_
52+
}`,
53+
},
54+
fix: `
55+
function loadManifest($PATH, $$$ARGS) {
56+
${returnManifests}
57+
throw new Error(\`Unexpected loadManifest(\${$PATH}) call!\`);
58+
}`,
59+
} satisfies RuleConfig;
60+
}
Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
import { readFileSync } from "node:fs";
2-
import { join, relative } from "node:path";
3-
4-
import { type BuildOptions, getBuildId, getPackagePath } from "@opennextjs/aws/build/helper.js";
5-
import { globSync } from "glob";
6-
7-
import { normalizePath } from "../../utils/index.js";
1+
import { type BuildOptions, getBuildId } from "@opennextjs/aws/build/helper.js";
82

93
export function patchBuildId(code: string, buildOpts: BuildOptions): string {
104
// The Next code gets the buildId from the filesystem so we hardcode the value at build time.
@@ -15,30 +9,3 @@ export function patchBuildId(code: string, buildOpts: BuildOptions): string {
159
`
1610
);
1711
}
18-
19-
export function patchLoadManifest(code: string, buildOpts: BuildOptions): string {
20-
// Inline manifest that Next would otherwise retrieve from the file system.
21-
22-
const { outputDir } = buildOpts;
23-
24-
const baseDir = join(outputDir, "server-functions/default", getPackagePath(buildOpts));
25-
const dotNextDir = join(baseDir, ".next");
26-
27-
const manifests = globSync(join(dotNextDir, "**/*-manifest.json"));
28-
29-
return code.replace(
30-
/function loadManifest\((.+?), .+?\) {/,
31-
`$&
32-
${manifests
33-
.map(
34-
(manifest) => `
35-
if ($1.endsWith("${normalizePath("/" + relative(dotNextDir, manifest))}")) {
36-
return ${readFileSync(manifest, "utf-8")};
37-
}
38-
`
39-
)
40-
.join("\n")}
41-
throw new Error("Unknown loadManifest: " + $1);
42-
`
43-
);
44-
}

0 commit comments

Comments
 (0)