快取回應

快取回應對於保持網站的快速性至關重要,無論是頁面還是中介軟體

預設情況下,建議對所有回應使用 stale-while-revalidate 快取。

例如,我們可以在根 佈局 (src/routes/layout.tsx) 中新增一個 onGet 匯出,如下所示,以在全站套用良好的快取預設值。

src/routes/layout.tsx
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 來設定回應的快取控制標頭。

src/routes/layout.tsx
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,
  });
};

如果您在根目錄設定了預設快取,但想要停用特定頁面的快取,可以使用巢狀佈局覆寫此設定。以下範例覆寫了儀表板頁面的快取。

src/routes/dashboard/layout.tsx
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,
  });
};
 

您可以查看可以傳遞給 request.cacheControl 的選項的完整 API 參考

何時不快取

快取通常是有益的,但並非始終適用於每個頁面。如果您的網站上有顯示給不同人員不同內容的網址,例如僅限登入使用者存取的頁面,或根據使用者位置顯示內容的頁面,則應避免使用快取控制標頭來快取這些頁面。而是應根據每個訪問者在伺服器端呈現這些頁面的內容。

對於流量高且對所有人看起來都相同的頁面,例如首頁,快取非常適合用於提升效能和降低成本。對於專為登入使用者設計且流量可能較少的頁面,建議停用快取。

您可以使用任何您喜歡的邏輯有條件地變更快取行為。

src/routes/layout.tsx
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)可能會刪除您的一些「快取控制」標頭。

在 Vercel 的文件中

如果您在沒有 CDN-Cache-Control 的情況下設定了 Cache-Control,則 Vercel Edge 網路會在將回應發送到瀏覽器之前,從回應中刪除 s-maxage 和 stale-while-revalidate。要確定回應是否從快取提供服務,請檢查回應中的 x-vercel-cache 標頭。

如果您的 CDN(例如 Vercel Edge)自動刪除了某些快取控制標頭,並且您希望在瀏覽器中實作「stale-while-revalidate」或「s-maxage」等快取策略,則可以指定其他 cacheControl。

src/routes/layout.tsx
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");
};

貢獻者

感謝所有幫助改進此文件的貢獻者!

  • steve8708
  • harishkrishnan24
  • maiieul
  • igorbabko
  • mrhoodz
  • mhevery
  • chsanch
  • hamatoyogi
  • Jemsco