Skip to content

Commit 6b685dd

Browse files
authored
fix: serve internal JS from path containing build ID (#2753)
Previously imported chunks were not cached at all. They are now cached properly with immutable cache headers.
1 parent 96e520a commit 6b685dd

File tree

6 files changed

+42
-27
lines changed

6 files changed

+42
-27
lines changed

src/context.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
setRenderState,
1515
} from "./runtime/server/preact_hooks.tsx";
1616
import { DEV_ERROR_OVERLAY_URL } from "./constants.ts";
17-
import { asset } from "./runtime/shared.ts";
17+
import { BUILD_ID } from "./runtime/build_id.ts";
1818

1919
export interface Island {
2020
file: string | URL;
@@ -240,13 +240,13 @@ function preactRender<State, Data>(
240240
} finally {
241241
// Add preload headers
242242
const basePath = ctx.config.basePath;
243-
const runtimeUrl = asset(`${basePath}/fresh-runtime.js`);
243+
const runtimeUrl = `${basePath}/_fresh/js/${BUILD_ID}/fresh-runtime.js`;
244244
let link = `<${encodeURI(runtimeUrl)}>; rel="modulepreload"; as="script"`;
245245
state.islands.forEach((island) => {
246246
const chunk = buildCache.getIslandChunkName(island.name);
247247
if (chunk !== null) {
248248
link += `, <${
249-
encodeURI(asset(`${basePath}${chunk}`))
249+
encodeURI(`${basePath}${chunk}`)
250250
}>; rel="modulepreload"; as="script"`;
251251
}
252252
});

src/dev/builder.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,11 @@ export class Builder implements FreshBuilder {
182182
denoJsonPath: denoJson.filePath,
183183
});
184184

185+
const prefix = `/_fresh/js/${BUILD_ID}/`;
186+
185187
for (let i = 0; i < output.files.length; i++) {
186188
const file = output.files[i];
187-
const pathname = `/${file.path}`;
189+
const pathname = `${prefix}${file.path}`;
188190
await buildCache.addProcessedFile(pathname, file.contents, file.hash);
189191
}
190192

@@ -196,7 +198,7 @@ export class Builder implements FreshBuilder {
196198
`Missing chunk for ${island.file}#${island.exportName}`,
197199
);
198200
}
199-
buildCache.islands.set(island.name, `/${chunk}`);
201+
buildCache.islands.set(island.name, `${prefix}${chunk}`);
200202
}
201203

202204
await buildCache.flush();

src/dev/builder_test.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as path from "@std/path";
33
import { Builder } from "./builder.ts";
44
import { App } from "../app.ts";
55
import { RemoteIsland } from "@marvinh-test/fresh-island";
6+
import { BUILD_ID } from "../runtime/build_id.ts";
67

78
Deno.test({
89
name: "Builder - chain onTransformStaticFile",
@@ -114,7 +115,15 @@ Deno.test({
114115
await builder.build(app);
115116

116117
const code = await Deno.readTextFile(
117-
path.join(tmp, "dist", "static", "RemoteIsland.js"),
118+
path.join(
119+
tmp,
120+
"dist",
121+
"static",
122+
"_fresh",
123+
"js",
124+
BUILD_ID,
125+
"RemoteIsland.js",
126+
),
118127
);
119128
expect(code).toContain('"remote-island"');
120129
},

src/middlewares/static_files.ts

+20-16
Original file line numberDiff line numberDiff line change
@@ -61,26 +61,30 @@ export function staticFiles<T>(): MiddlewareFn<T> {
6161
vary: "If-None-Match",
6262
});
6363

64-
if (cacheKey === null || ctx.config.mode === "development") {
64+
const ifNoneMatch = req.headers.get("If-None-Match");
65+
if (
66+
ifNoneMatch !== null &&
67+
(ifNoneMatch === etag || ifNoneMatch === `W/"${etag}"`)
68+
) {
69+
file.close();
70+
return new Response(null, { status: 304, headers });
71+
} else if (etag !== null) {
72+
headers.set("Etag", `W/"${etag}"`);
73+
}
74+
75+
if (
76+
ctx.config.mode !== "development" &&
77+
(BUILD_ID === cacheKey ||
78+
url.pathname.startsWith(
79+
`${ctx.config.basePath}/_fresh/js/${BUILD_ID}/`,
80+
))
81+
) {
82+
headers.append("Cache-Control", "public, max-age=31536000, immutable");
83+
} else {
6584
headers.append(
6685
"Cache-Control",
6786
"no-cache, no-store, max-age=0, must-revalidate",
6887
);
69-
} else {
70-
const ifNoneMatch = req.headers.get("If-None-Match");
71-
if (
72-
ifNoneMatch !== null &&
73-
(ifNoneMatch === etag || ifNoneMatch === `W/"${etag}"`)
74-
) {
75-
file.close();
76-
return new Response(null, { status: 304, headers });
77-
} else if (etag !== null) {
78-
headers.set("Etag", `W/"${etag}"`);
79-
}
80-
}
81-
82-
if (BUILD_ID === cacheKey) {
83-
headers.append("Cache-Control", "public, max-age=31536000, immutable");
8488
}
8589

8690
headers.set("Content-Length", String(file.size));

src/runtime/server/preact_hooks.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
import type { Signal } from "@preact/signals";
1313
import type { Stringifiers } from "../../jsonify/stringify.ts";
1414
import type { PageProps } from "../../context.ts";
15-
import { asset, Partial, type PartialProps } from "../shared.ts";
15+
import { Partial, type PartialProps } from "../shared.ts";
1616
import { stringify } from "../../jsonify/stringify.ts";
1717
import type { ServerIslandRegistry } from "../../context.ts";
1818
import type { Island } from "../../context.ts";
@@ -438,7 +438,7 @@ function FreshRuntimeScript() {
438438
}
439439
return {
440440
exportName: island.exportName,
441-
chunk: asset(chunk),
441+
chunk,
442442
name: island.name,
443443
};
444444
});
@@ -467,7 +467,7 @@ function FreshRuntimeScript() {
467467
const named = island.exportName === "default"
468468
? island.name
469469
: `{ ${island.exportName} }`;
470-
return `import ${named} from "${asset(`${basePath}${chunk}`)}";`;
470+
return `import ${named} from "${`${basePath}${chunk}`}";`;
471471
}).join("");
472472

473473
const islandObj = "{" + islandArr.map((island) => island.name)
@@ -478,7 +478,7 @@ function FreshRuntimeScript() {
478478
stringify(islandProps, stringifiers),
479479
);
480480

481-
const runtimeUrl = asset(`${basePath}/fresh-runtime.js`);
481+
const runtimeUrl = `${basePath}/_fresh/js/${BUILD_ID}/fresh-runtime.js`;
482482
const scriptContent =
483483
`import { boot } from "${runtimeUrl}";${islandImports}boot(${islandObj},${serializedProps});`;
484484

tests/islands_test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,7 @@ Deno.test({
764764

765765
const link = res.headers.get("Link");
766766
expect(link).toMatch(
767-
/<\/fresh-runtime\.js\?__frsh_c=[^>]+>; rel="modulepreload"; as="script", <\/SelfCounter\.js\?__frsh_c=[^>]+>; rel="modulepreload"; as="script"/,
767+
/<\/_fresh\/js\/[a-zA-Z0-9]+\/fresh-runtime\.js>; rel="modulepreload"; as="script", <\/_fresh\/js\/[a-zA-Z0-9]+\/SelfCounter\.js>; rel="modulepreload"; as="script"/,
768768
);
769769
},
770770
sanitizeResources: false,

0 commit comments

Comments
 (0)