|
1 | | -import { defu } from "defu"; |
2 | 1 | import { glob } from "tinyglobby"; |
3 | | -import { resolve } from "pathe"; |
| 2 | +import { resolve } from "pathe"; |
4 | 3 | import { joinURL, withLeadingSlash } from "ufo"; |
5 | | -import type { Nitro, NitroRouteRules } from "nitro/types"; |
| 4 | +import type { Nitro } from "nitro/types"; |
6 | 5 | import { writeFile } from "../_utils/fs.ts"; |
7 | 6 |
|
8 | 7 | // Immutable Static Files |
@@ -37,54 +36,25 @@ export async function generateImmutableManifest(nitro: Nitro) { |
37 | 36 | return; |
38 | 37 | } |
39 | 38 |
|
40 | | - const isImmutable = createImmutableMatcher(nitro); |
41 | | - |
42 | | - // Walk every emitted static file and hash the immutable (content-addressed) |
43 | | - // ones. The output public dir already includes the site `baseURL`, so scanned |
44 | | - // paths are relative to it. |
45 | 39 | const publicDir = nitro.options.output.publicDir; |
46 | | - const files = await glob("**", { cwd: publicDir, absolute: false, dot: true }); |
| 40 | + const files = await glob(`${IMMUTABLE_DIR}/**`, { |
| 41 | + cwd: publicDir, |
| 42 | + absolute: false, |
| 43 | + dot: true, |
| 44 | + }); |
47 | 45 |
|
48 | | - const hashes: Record<string, string> = {}; |
| 46 | + const manifest: ImmutableManifest = { version: 1, hashes: {} }; |
49 | 47 | for (const file of files) { |
50 | 48 | const pathname = withLeadingSlash(file); |
51 | | - if (!isImmutable(pathname)) { |
52 | | - continue; |
53 | | - } |
54 | | - const url = joinURL(nitro.options.baseURL, pathname); |
55 | | - hashes[url] = "" |
| 49 | + manifest.hashes[joinURL(nitro.options.baseURL, pathname)] = ""; |
56 | 50 | } |
57 | 51 |
|
58 | | - const manifest: ImmutableManifest = { version: 1, hashes }; |
59 | 52 | await writeFile( |
60 | 53 | resolve(nitro.options.output.dir, IMMUTABLE_MANIFEST), |
61 | 54 | JSON.stringify(manifest, null, 2) |
62 | 55 | ); |
63 | 56 |
|
64 | 57 | nitro.logger |
65 | 58 | .withTag("vercel") |
66 | | - .info(`Generated immutable manifest (${Object.keys(hashes).length} files).`); |
67 | | -} |
68 | | - |
69 | | -// A static file is immutable when it is served with a long-lived `immutable` |
70 | | -// cache-control. That covers content-addressed bundler output emitted under an |
71 | | -// assets dir (marked via a route rule, e.g. Vite's `/assets/**`) as well as |
72 | | -// non-fallthrough public asset dirs, while excluding user-authored files in the |
73 | | -// fallthrough `public/` dir. |
74 | | -function createImmutableMatcher(nitro: Nitro): (pathname: string) => boolean { |
75 | | - const immutableBaseURLs = nitro.options.publicAssets |
76 | | - .filter((asset) => !asset.fallthrough) |
77 | | - .map((asset) => withLeadingSlash(asset.baseURL || "/")) |
78 | | - .filter((baseURL) => baseURL !== "/"); |
79 | | - |
80 | | - const getRouteRules = (pathname: string) => |
81 | | - defu({}, ...nitro.routing.routeRules.matchAll("", pathname).reverse()) as NitroRouteRules; |
82 | | - |
83 | | - return (pathname: string) => { |
84 | | - if (immutableBaseURLs.some((baseURL) => pathname.startsWith(baseURL + "/"))) { |
85 | | - return true; |
86 | | - } |
87 | | - const cacheControl = getRouteRules(pathname).headers?.["cache-control"]; |
88 | | - return !!cacheControl && cacheControl.includes("immutable"); |
89 | | - }; |
| 59 | + .info(`Generated immutable manifest (${Object.keys(manifest.hashes).length} files).`); |
90 | 60 | } |
0 commit comments