Skip to content

Commit 65992c5

Browse files
committed
feat(core): server-side response caching using the Web Cache API
1 parent cea7a2a commit 65992c5

5 files changed

Lines changed: 133 additions & 10 deletions

File tree

bench.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { app } from "./www/main.ts";
2+
3+
const handler = await app.handler();
4+
5+
Deno.bench(
6+
"handler",
7+
async () => {
8+
await handler(
9+
new Request(
10+
"http://localhost:8000/docs/examples/using-fresh-canary-version",
11+
),
12+
);
13+
},
14+
);

deno.lock

Lines changed: 92 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ export class App<State> {
196196
req: Request,
197197
conn: Deno.ServeHandlerInfo = DEFAULT_CONN_INFO,
198198
) => {
199+
if (this.config.cache && req.method === "GET") {
200+
const cachedResponse = await this.config.cache.match(req);
201+
if (cachedResponse) return cachedResponse;
202+
}
203+
199204
const url = new URL(req.url);
200205
// Prevent open redirect attacks
201206
url.pathname = url.pathname.replace(/\/+/g, "/");
@@ -225,24 +230,28 @@ export class App<State> {
225230
span.setAttribute("http.route", pattern);
226231
}
227232

233+
let response: Response;
228234
try {
229-
if (handlers.length === 1 && handlers[0].length === 1) {
230-
return handlers[0][0](ctx);
231-
}
232-
return await runMiddlewares(handlers, ctx);
235+
response = handlers.length === 1 && handlers[0].length === 1
236+
? await handlers[0][0](ctx)
237+
: await runMiddlewares(handlers, ctx);
233238
} catch (err) {
234239
if (err instanceof HttpError) {
235240
if (err.status >= 500) {
236241
// deno-lint-ignore no-console
237242
console.error(err);
238243
}
239-
return new Response(err.message, { status: err.status });
244+
response = new Response(err.message, { status: err.status });
240245
}
241246

242247
// deno-lint-ignore no-console
243248
console.error(err);
244-
return new Response("Internal server error", { status: 500 });
249+
response = new Response("Internal server error", { status: 500 });
250+
}
251+
if (this.config.cache && req.method === "GET") {
252+
this.config.cache.put(req, response.clone());
245253
}
254+
return response;
246255
};
247256
}
248257

src/config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ export interface FreshConfig {
1616
*/
1717
basePath?: string;
1818
staticDir?: string;
19+
/**
20+
* Server-side cache that stores responses for corresponding requests.
21+
*/
22+
cache?: Cache;
1923
}
2024

2125
/**
@@ -32,6 +36,10 @@ export interface ResolvedFreshConfig {
3236
* The mode Fresh can run in.
3337
*/
3438
mode: "development" | "production";
39+
/**
40+
* Server-side cache that stores responses for corresponding requests.
41+
*/
42+
cache?: Cache;
3543
}
3644

3745
export function parseRootPath(root: string, cwd: string): string {
@@ -65,6 +73,7 @@ export function normalizeConfig(options: FreshConfig): ResolvedFreshConfig {
6573
basePath: options.basePath ?? "",
6674
staticDir: options.staticDir ?? path.join(root, "static"),
6775
mode: "production",
76+
cache: options.cache,
6877
};
6978
}
7079

www/main.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import "./telemetry.ts";
22
import { App, fsRoutes, staticFiles, trailingSlashes } from "fresh";
33

4-
export const app = new App({ root: import.meta.url })
4+
const cache = await caches.open("fresh");
5+
6+
export const app = new App({ root: import.meta.url, cache })
57
.use(staticFiles())
68
.use(trailingSlashes("never"));
79

0 commit comments

Comments
 (0)