缓存响应
缓存响应对于保持网站尽可能快至关重要,无论是对于 页面 还是 中间件。
一个好的默认做法是为所有响应使用 stale-while-revalidate 缓存。
例如,我们可以向根 布局 (src/routes/layout.tsx
) 添加一个 onGet
导出,如下所示,以在整个站点范围内应用良好的缓存默认值
import { component$, Slot } from "@builder.io/qwik";
import type { RequestHandler } from "@builder.io/qwik-city";
export const onGet: RequestHandler = async ({ cacheControl }) => {
cacheControl({
// Always serve a cached response by default, up to a week stale
staleWhileRevalidate: 60 * 60 * 24 * 7,
// Max once every 5 seconds, revalidate on the server to get a fresh version of this page
maxAge: 5,
});
};
export default component$(() => {
return (
<main class="mx-auto max-w-[2200px] relative">
<Slot />
</main>
);
});
通过上述设置,您不仅可以获得更好的性能(页面始终从缓存中立即提供),而且还可以显著降低托管成本,因为我们的服务器或边缘函数每页最多每 5 秒运行一次。
cacheControl
任何接受 请求事件 的方法都可以调用 request.cacheControl
来设置响应的缓存控制头。
import type { RequestHandler } from "@builder.io/qwik-city";
export const onGet: RequestHandler = async ({ cacheControl }) => {
cacheControl({
public: true,
maxAge: 5,
sMaxAge: 10,
staleWhileRevalidate: 60 * 60 * 24 * 365,
});
};
如果您在根目录设置了默认缓存,但希望为特定页面禁用缓存,则可以使用嵌套布局来覆盖此设置。以下示例覆盖了仪表板页面的缓存。
import type { RequestHandler } from "@builder.io/qwik-city";
// Override caching for /dashboard pages to not cache as they are unique per visitor
export const onGet: RequestHandler = async ({ cacheControl }) => {
cacheControl({
public: false,
maxAge: 0,
sMaxAge: 0,
staleWhileRevalidate: 0,
});
};
您可以查看完整的 API 参考,了解您可以传递给 request.cacheControl
的选项。
何时不缓存
缓存通常是有益的,但并非始终适用于所有页面。如果您的网站包含对不同用户显示不同内容的 URL(例如,仅供已登录用户访问的页面或根据用户位置显示内容的页面),则应避免使用缓存控制头来缓存这些页面。相反,应在服务器端为每个访问者渲染这些页面的内容。
对于对所有人看起来都一样的流量很大的页面(例如主页),缓存非常适合提高性能和降低成本。对于专门针对已登录用户且流量可能较少的页面,建议禁用缓存。
您可以使用任何您喜欢的逻辑有条件地更改缓存行为。
import type { RequestHandler } from "@builder.io/qwik-city";
export const onGet: RequestHandler = async ({ cacheControl, url }) => {
// Only our homepage is public and should be CDN cached. Other pages are unique per visitor
if (url.pathname === '/') {
cacheControl({
public: true,
maxAge: 5,
staleWhileRevalidate: 60 * 60 * 24 * 365,
});
}
};
CDN 缓存控制
为了更精细地控制您的缓存策略,您的 CDN 可能具有另一层缓存控制头。
cacheControl
方便方法可以接收第二个参数(默认设置为 "Cache-Control"
)。您可以传入任何特定于您的 CDN 的字符串值,例如 "CDN-Cache-Control"、"Cloudflare-CDN-Cache-Control"、"Vercel-CDN-Cache-Control" 等。
cacheControl({
maxAge: 5,
staleWhileRevalidate: 60 * 60 * 24 * 365,
}, "CDN-Cache-Control");
缺少控制
某些 CDN(例如 Vercel Edge)可能会剥离一些 "Cache-Control" 头。
如果您设置了 Cache-Control 但没有 CDN-Cache-Control,Vercel Edge 网络会在将响应发送到浏览器之前从响应中剥离 s-maxage 和 stale-while-revalidate。要确定响应是否来自缓存,请检查响应中的 x-vercel-cache 头。
如果您的 CDN(例如 Vercel Edge)自动删除某些缓存控制头,并且您希望在浏览器中实现 "stale-while-revalidate" 或 "s-maxage" 等缓存策略,则可以指定一个额外的 cacheControl
import type { RequestHandler } from "@builder.io/qwik-city";
export const onGet: RequestHandler = async ({ cacheControl }) => {
// If you want the browser to use "stale-while-revalidate" or "s-maxage" Cache Control headers, you have to add the second cacheControl with "CDN-Cache-Control" or "Vercel-CDN-Cache-Control" on Vercel Edge
cacheControl({
staleWhileRevalidate: 60 * 60 * 24 * 365,
maxAge: 5,
});
cacheControl({
maxAge: 5,
staleWhileRevalidate: 60 * 60 * 24 * 365,
}, "CDN-Cache-Control");
};