Skip to content

Commit a64aa4c

Browse files
authored
fix(vercel): generate prerender config for o11y routes matching isr route rule (#3562)
1 parent 4871c9c commit a64aa4c

2 files changed

Lines changed: 54 additions & 36 deletions

File tree

src/presets/vercel/utils.ts

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import fsp from "node:fs/promises";
22
import { defu } from "defu";
33
import { writeFile } from "nitropack/kit";
4-
import type { Nitro } from "nitropack/types";
4+
import type { Nitro, NitroRouteRules } from "nitropack/types";
55
import { dirname, relative, resolve } from "pathe";
66
import { joinURL, withLeadingSlash, withoutLeadingSlash } from "ufo";
77
import type {
@@ -10,6 +10,7 @@ import type {
1010
VercelServerlessFunctionConfig,
1111
} from "./types";
1212
import { isTest } from "std-env";
13+
import { createRouter as createRadixRouter, toRouteMatcher } from "radix3";
1314

1415
// https://vercel.com/docs/build-output-api/configuration
1516

@@ -61,31 +62,6 @@ export async function generateFunctionFiles(nitro: Nitro) {
6162
continue;
6263
}
6364

64-
// Normalize route rule
65-
let isrConfig = value.isr;
66-
if (typeof isrConfig === "number") {
67-
isrConfig = { expiration: isrConfig };
68-
} else if (isrConfig === true) {
69-
isrConfig = { expiration: false };
70-
} else {
71-
isrConfig = { ...isrConfig };
72-
}
73-
74-
// Generate prerender config
75-
const prerenderConfig: PrerenderFunctionConfig = {
76-
expiration: isrConfig.expiration ?? false,
77-
bypassToken: nitro.options.vercel?.config?.bypassToken,
78-
...isrConfig,
79-
};
80-
81-
// Allow query parameter for wildcard routes
82-
if (key.includes("/**") /* wildcard */) {
83-
isrConfig.allowQuery = isrConfig.allowQuery || [];
84-
if (!isrConfig.allowQuery.includes("url")) {
85-
isrConfig.allowQuery.push("url");
86-
}
87-
}
88-
8965
const funcPrefix = resolve(
9066
nitro.options.output.serverDir,
9167
"..",
@@ -97,13 +73,22 @@ export async function generateFunctionFiles(nitro: Nitro) {
9773
funcPrefix + ".func",
9874
"junction"
9975
);
100-
await writeFile(
76+
await writePrerenderConfig(
10177
funcPrefix + ".prerender-config.json",
102-
JSON.stringify(prerenderConfig, null, 2)
78+
value.isr,
79+
nitro.options.vercel?.config?.bypassToken
10380
);
10481
}
10582

10683
// Write observability routes
84+
if (o11Routes.length === 0) {
85+
return;
86+
}
87+
const _routeRulesMatcher = toRouteMatcher(
88+
createRadixRouter({ routes: nitro.options.routeRules })
89+
);
90+
const _getRouteRules = (path: string) =>
91+
defu({}, ..._routeRulesMatcher.matchAll(path).reverse()) as NitroRouteRules;
10792
for (const route of o11Routes) {
10893
const funcPrefix = resolve(
10994
nitro.options.output.serverDir,
@@ -116,6 +101,14 @@ export async function generateFunctionFiles(nitro: Nitro) {
116101
funcPrefix + ".func",
117102
"junction"
118103
);
104+
const routeRules = _getRouteRules(route.src);
105+
if (routeRules.isr) {
106+
await writePrerenderConfig(
107+
funcPrefix + ".prerender-config.json",
108+
routeRules.isr,
109+
nitro.options.vercel?.config?.bypassToken
110+
);
111+
}
119112
}
120113
}
121114

@@ -405,3 +398,27 @@ function normalizeRouteDest(route: string) {
405398
.join("/") || "index"
406399
);
407400
}
401+
402+
async function writePrerenderConfig(
403+
filename: string,
404+
isrConfig: NitroRouteRules["isr"],
405+
bypassToken?: string
406+
) {
407+
// Normalize route rule
408+
if (typeof isrConfig === "number") {
409+
isrConfig = { expiration: isrConfig };
410+
} else if (isrConfig === true) {
411+
isrConfig = { expiration: false };
412+
} else {
413+
isrConfig = { ...isrConfig };
414+
}
415+
416+
// Generate prerender config
417+
const prerenderConfig: PrerenderFunctionConfig = {
418+
expiration: isrConfig.expiration ?? false,
419+
bypassToken,
420+
...isrConfig,
421+
};
422+
423+
await writeFile(filename, JSON.stringify(prerenderConfig, null, 2));
424+
}

test/presets/vercel.test.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ describe("nitro:preset:vercel", async () => {
457457
);
458458
expect(JSON.parse(isrRouteConfig)).toMatchObject({
459459
expiration: false,
460-
allowQuery: ["q", "url"],
460+
allowQuery: ["q"],
461461
});
462462
});
463463

@@ -480,6 +480,7 @@ describe("nitro:preset:vercel", async () => {
480480
);
481481
}
482482
}
483+
items.sort();
483484
return items;
484485
};
485486

@@ -511,10 +512,10 @@ describe("nitro:preset:vercel", async () => {
511512
"functions/api/import-meta.func (symlink)",
512513
"functions/api/kebab.func (symlink)",
513514
"functions/api/meta/test.func (symlink)",
515+
"functions/api/methods.func (symlink)",
514516
"functions/api/methods/default.func (symlink)",
515517
"functions/api/methods/foo.get.func (symlink)",
516518
"functions/api/methods/get.func (symlink)",
517-
"functions/api/methods.func (symlink)",
518519
"functions/api/param/[test-id].func (symlink)",
519520
"functions/api/serialized/date.func (symlink)",
520521
"functions/api/serialized/error.func (symlink)",
@@ -531,14 +532,14 @@ describe("nitro:preset:vercel", async () => {
531532
"functions/api/typed/catchall/some/[...test].func (symlink)",
532533
"functions/api/typed/todos/[...].func (symlink)",
533534
"functions/api/typed/todos/[todoId]/comments/[...commentId].func (symlink)",
535+
"functions/api/typed/user/[userId].func (symlink)",
534536
"functions/api/typed/user/[userId]/[userExtends].func (symlink)",
535537
"functions/api/typed/user/[userId]/post/[postId].func (symlink)",
536538
"functions/api/typed/user/[userId]/post/firstPost.func (symlink)",
537-
"functions/api/typed/user/[userId].func (symlink)",
539+
"functions/api/typed/user/john.func (symlink)",
538540
"functions/api/typed/user/john/[johnExtends].func (symlink)",
539541
"functions/api/typed/user/john/post/[postId].func (symlink)",
540542
"functions/api/typed/user/john/post/coffee.func (symlink)",
541-
"functions/api/typed/user/john.func (symlink)",
542543
"functions/api/upload.func (symlink)",
543544
"functions/api/wildcard/[...param].func (symlink)",
544545
"functions/assets/[id].func (symlink)",
@@ -565,14 +566,14 @@ describe("nitro:preset:vercel", async () => {
565566
"functions/rules/_/cached/[...].isr.prerender-config.json",
566567
"functions/rules/_/noncached/cached.isr.func (symlink)",
567568
"functions/rules/_/noncached/cached.isr.prerender-config.json",
568-
"functions/rules/isr/[...].isr.func (symlink)",
569-
"functions/rules/isr/[...].isr.prerender-config.json",
570569
"functions/rules/isr-ttl/[...].isr.func (symlink)",
571570
"functions/rules/isr-ttl/[...].isr.prerender-config.json",
572-
"functions/rules/swr/[...].isr.func (symlink)",
573-
"functions/rules/swr/[...].isr.prerender-config.json",
571+
"functions/rules/isr/[...].isr.func (symlink)",
572+
"functions/rules/isr/[...].isr.prerender-config.json",
574573
"functions/rules/swr-ttl/[...].isr.func (symlink)",
575574
"functions/rules/swr-ttl/[...].isr.prerender-config.json",
575+
"functions/rules/swr/[...].isr.func (symlink)",
576+
"functions/rules/swr/[...].isr.prerender-config.json",
576577
"functions/static-flags.func (symlink)",
577578
"functions/stream.func (symlink)",
578579
"functions/tasks/[...name].func (symlink)",

0 commit comments

Comments
 (0)