Skip to content

Commit

Permalink
perf(netlify-legacy): exclude static paths from SSR function
Browse files Browse the repository at this point in the history
Backporting #2822 to the netlify-legacy preset.

Since it's using "v1" Netlify Functions
(https://docs.netlify.com/functions/lambda-compatibility), it doesn't have access to
`excludedPath` and `preferStatic`, so we implement this with redirects.
  • Loading branch information
serhalp committed Oct 31, 2024
1 parent e3a2d6f commit 0220664
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 4 deletions.
4 changes: 2 additions & 2 deletions src/presets/netlify/legacy/preset.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { existsSync, promises as fsp } from "node:fs";
import { promises as fsp } from "node:fs";
import { defineNitroPreset } from "nitropack/kit";
import type { Nitro } from "nitropack/types";
import { dirname, join } from "pathe";
Expand All @@ -24,7 +24,7 @@ const netlify = defineNitroPreset(
},
async compiled(nitro: Nitro) {
await writeHeaders(nitro);
await writeRedirects(nitro);
await writeRedirects(nitro, "/.netlify/functions/server");

if (nitro.options.netlify) {
const configPath = join(
Expand Down
29 changes: 27 additions & 2 deletions src/presets/netlify/legacy/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,25 @@ import { existsSync, promises as fsp } from "node:fs";
import type { Nitro } from "nitropack/types";
import { join } from "pathe";

export async function writeRedirects(nitro: Nitro) {
export function generateCatchAllRedirects(
nitro: Nitro,
catchAllPath?: string
): string {
if (!catchAllPath) return "";

return [
// e.g.: /_nuxt/* /_nuxt/:splat 200
// Because of Netlify CDN shadowing
// (https://docs.netlify.com/routing/redirects/rewrites-proxies/#shadowing),
// this config avoids function invocations for all static paths, even 404s.
...getStaticPaths(nitro).map(
(path) => `${path} ${path.replace("/*", "/:splat")} 200`
),
`/* ${catchAllPath} 200`,
].join("\n");
}

export async function writeRedirects(nitro: Nitro, catchAllPath?: string) {
const redirectsPath = join(nitro.options.output.publicDir, "_redirects");
const staticFallback = existsSync(
join(nitro.options.output.publicDir, "404.html")
Expand All @@ -11,7 +29,7 @@ export async function writeRedirects(nitro: Nitro) {
: "";
let contents = nitro.options.static
? staticFallback
: "/* /.netlify/functions/server 200";
: generateCatchAllRedirects(nitro, catchAllPath);

const rules = Object.entries(nitro.options.routeRules).sort(
(a, b) => a[0].split(/\/(?!\*)/).length - b[0].split(/\/(?!\*)/).length
Expand Down Expand Up @@ -103,6 +121,13 @@ export async function writeHeaders(nitro: Nitro) {
await fsp.writeFile(headersPath, contents);
}

export function getStaticPaths(nitro: Nitro): string[] {
const publicAssets = nitro.options.publicAssets.filter(
(dir) => dir.fallthrough !== true && dir.baseURL && dir.baseURL !== "/"
);
return publicAssets.map((dir) => `${dir.baseURL}/*`);
}

export function deprecateSWR(nitro: Nitro) {
if (nitro.options.future.nativeSWR) {
return;
Expand Down
4 changes: 4 additions & 0 deletions test/presets/netlify-legacy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ describe("nitro:preset:netlify-legacy", async () => {
/rules/isr-ttl/* /.netlify/builders/server 200
/rules/isr/* /.netlify/builders/server 200
/rules/dynamic /.netlify/functions/server 200
/.netlify/* /.netlify/:splat 200
/build/* /build/:splat 200
/with-default-fallthrough/* /with-default-fallthrough/:splat 200
/nested/no-fallthrough/* /nested/no-fallthrough/:splat 200
/* /.netlify/functions/server 200"
`);
});
Expand Down

0 comments on commit 0220664

Please sign in to comment.