預先渲染
在本頁面上

預先渲染

預先渲染允許您藉由在建置時而非執行時渲染頁面,來加速靜態內容的頁面載入速度。預先渲染透過 react-router.config.ts 中的 prerender 設定啟用,並且可以根據 ssr 設定值以兩種方式使用

  • 與執行階段 SSR 伺服器搭配使用,`ssr:true` (預設值)
  • 部署到靜態檔案伺服器,`ssr:false`

使用 ssr:true 預先渲染

設定

prerender 選項新增至您的設定,共有三種簽名

import type { Config } from "@react-router/dev/config";

export default {
  // Can be omitted - defaults to true
  ssr: true,

  // all static paths (no dynamic segments like "/post/:slug")
  prerender: true,

  // specific paths
  prerender: ["/", "/blog", "/blog/popular-post"],

  // async function for dependencies like a CMS
  async prerender({ getStaticPaths }) {
    let posts = await fakeGetPostsFromCMS();
    return [
      "/",
      "/blog",
      ...posts.map((post) => post.href),
    ];
  },
} satisfies Config;

資料載入與預先渲染

預先渲染沒有額外的應用程式 API。正在預先渲染的路徑使用與伺服器渲染相同的路由 loader 函數

export async function loader({ request, params }) {
  let post = await getPost(params.slug);
  return post;
}

export function Post({ loaderData }) {
  return <div>{loaderData.title}</div>;
}

建置會建立一個 new Request() 並像伺服器一樣在您的應用程式中執行,而不是請求傳送到已部署伺服器上的路由。

當伺服器渲染時,對尚未預先渲染的路徑的請求將照常進行伺服器渲染。

靜態檔案輸出

渲染結果將寫出到您的 `build/client` 目錄。您會注意到每個路徑有兩個檔案

  • [url].html 用於初始文件請求的 HTML 檔案
  • [url].data 用於用戶端導航瀏覽器請求的檔案

您的建置輸出將指示哪些檔案已預先渲染

> react-router build
vite v5.2.11 building for production...
...
vite v5.2.11 building SSR bundle for production...
...
Prerender: Generated build/client/index.html
Prerender: Generated build/client/blog.data
Prerender: Generated build/client/blog/index.html
Prerender: Generated build/client/blog/my-first-post.data
Prerender: Generated build/client/blog/my-first-post/index.html
...

在開發期間,預先渲染不會將渲染結果儲存到 public 目錄,這僅在 `react-router build` 時發生。

使用 ssr:false 預先渲染

上述範例假設您正在部署執行階段伺服器,但正在預先渲染一些靜態頁面,以便更快地提供它們並避免點擊伺服器。

若要停用執行階段 SSR 並設定從靜態檔案伺服器提供預先渲染,您可以設定 ssr:false 設定旗標

import type { Config } from "@react-router/dev/config";

export default {
  ssr: false, // disable runtime server rendering
  prerender: true, // pre-render all static routes
} satisfies Config;

如果您在未指定 prerender 設定的情況下指定 ssr:false,React Router 將其稱為 SPA 模式。在 SPA 模式中,我們渲染一個能夠為您應用程式的 *任何* 路徑進行 hydration 的單一 HTML 檔案。它可以做到這一點,因為它只將 root 路由渲染到 HTML 檔案中,然後在 hydration 期間根據瀏覽器 URL 確定要載入哪些子路由。這表示您可以在 root 路由上使用 `loader`,但不能在任何其他路由上使用,因為我們在瀏覽器中 hydration 之前不知道要載入哪些路由。

如果您想要使用 ssr:false 預先渲染路徑,那些相符的路徑 *可以* 具有 loader,因為我們將預先渲染這些路徑的所有相符路由,而不僅僅是 root。當設定 `ssr:false` 時,您無法在任何路由中包含 `actions` 或 `headers` 函數,因為將沒有執行階段伺服器來執行它們。

使用 SPA 後備方案預先渲染

如果您想要 ssr:false 但不想預先渲染 *所有* 路由 - 這也沒問題!您可能有一些路徑需要預先渲染的效能/SEO 優勢,但其他頁面使用 SPA 即可。

您也可以使用設定選項的組合來做到這一點 - 只需將您的 prerender 設定限制為您想要預先渲染的路徑,React Router 也會輸出一個 "SPA 後備" HTML 檔案,可用於提供 hydration 任何其他路徑 (使用與 SPA 模式相同的方法)。

這將寫入到以下路徑之一

  • build/client/index.html - 如果 / 路徑未預先渲染
  • build/client/__spa-fallback.html - 如果 / 路徑已預先渲染
import type { Config } from "@react-router/dev/config";

export default {
  ssr: false,

  // SPA fallback will be written to build/client/index.html
  prerender: ["/about-us"],

  // SPA fallback will be written to build/client/__spa-fallback.html
  prerender: ["/", "/about-us"],
} satisfies Config;

您可以設定您的部署伺服器,以便為任何原本會 404 的路徑提供此檔案。某些主機預設會執行此操作,但其他主機則不會。例如,主機可能支援 _redirects 檔案來執行此操作

# If you did not pre-render the `/` route
/*    /index.html   200

# If you pre-rendered the `/` route
/*    /__spa-fallback.html   200

如果您在應用程式的有效路由上收到 404 錯誤,則可能是您需要設定您的主機。

這是另一個關於如何使用 sirv-cli 工具執行此操作的範例

# If you did not pre-render the `/` route
sirv-cli build/client --single index.html

# If you pre-rendered the `/` route
sirv-cli build/client --single __spa-fallback.html

無效的匯出

當使用 ssr:false 進行預先渲染時,如果您有無效的匯出,React Router 將在建置時產生錯誤,以幫助防止一些容易被忽略的錯誤。

  • 所有路由都禁止使用 headers/action 函數,因為將沒有執行階段伺服器來執行它們
  • 當在沒有 prerender 設定 (SPA 模式) 的情況下使用 ssr:false 時,僅允許在 root 路由上使用 loader
  • 當在有 prerender 設定的情況下使用 ssr:false 時,允許在 prerender 路徑比對的任何路由上使用 loader
    • 如果您在具有子路由的預先渲染路由上使用 loader,您需要確保父 loaderData 可以在執行時正確地確定,方法是
      • 預先渲染所有子路由,以便可以在建置時針對每個子路由路徑呼叫父 loader 並渲染到 .data 檔案中,或者
      • 在父項上使用 clientLoader,可以在執行時針對非預先渲染的子路徑呼叫它
文件與範例 CC 4.0