有兩種方式可以使用 React Router 發布 single page app
當使用 React Router 作為框架時,您可以透過在您的 react-router.config.ts
檔案中設定 ssr:false
來啟用「SPA 模式」。這將停用執行階段伺服器渲染,並在建置時產生一個 index.html
,您可以將其作為 SPA 提供和 hydration。
典型的 Single Page app 會傳送幾乎空白的 index.html
模板,其中幾乎只有一個空的 <div id="root"></div>
。 相反地,react-router build
(在 SPA 模式下) 會在建置時將您的根路由預先渲染到 index.html
檔案中。 這表示您可以
<div>
loader
為您的應用程式外殼載入資料HydrateFallback
)請務必注意,設定 ssr:false
只會停用執行階段伺服器渲染。 React Router 仍然會在建置時伺服器渲染您的根路由,以產生 index.html
檔案。 這就是為什麼您的專案仍然需要依賴 @react-router/node
,並且您的路由需要是 SSR 安全的。 這表示您不能在初始渲染期間呼叫 window
或其他僅限瀏覽器的 API,即使伺服器渲染已停用也是如此。
伺服器渲染預設為啟用。 在 react-router.config.ts
中將 ssr
標記設定為 false
以停用它。
import { type Config } from "@react-router/dev/config";
export default {
ssr: false,
} satisfies Config;
將此設定為 false 後,將不再產生伺服器建置。
ssr:false
只會停用執行階段伺服器渲染。 React Router 仍然會在建置時伺服器渲染您的根路由,以產生 index.html
檔案。 這就是為什麼您的專案仍然需要依賴 @react-router/node
,並且您的路由需要是 SSR 安全的。 這表示您不能在初始渲染期間呼叫 window
或其他僅限瀏覽器的 API,即使伺服器渲染已停用也是如此。
HydrateFallback
和選用的 loader
SPA 模式將在建置時產生一個 index.html
檔案,您可以將其作為 SPA 的進入點提供。 這將只渲染根路由,使其能夠在執行階段為應用程式中的任何路徑進行 hydration。
為了提供比空的 <div>
更好的載入 UI,您可以將 HydrateFallback
元件新增至您的根路由,以便在建置時將您的載入 UI 渲染到 index.html
中。 這樣一來,在 SPA 載入/hydration 時,它會立即向使用者顯示。
import LoadingScreen from "./components/loading-screen";
export function Layout() {
return <html>{/*...*/}</html>;
}
export function HydrateFallback() {
return <LoadingScreen />;
}
export default function App() {
return <Outlet />;
}
由於根路由是在建置時進行伺服器渲染,因此您可以選擇在根路由中使用 loader
。 此 loader
將在建置時呼叫,並且資料將透過選用的 HydrateFallback
loaderData
prop 提供。
import { Route } from "./+types/root";
export async function loader() {
return {
version: await getVersion(),
};
}
export function HydrateFallback({
loaderData,
}: Route.ComponentProps) {
return (
<div>
<h1>Loading version {loaderData.version}...</h1>
<AwesomeSpinner />
</div>
);
}
當使用 SPA 模式時,除非您預先渲染這些頁面,否則您無法在應用程式中的任何其他路由中包含 loader
。
在停用伺服器渲染的情況下,您仍然可以使用 clientLoader
和 clientAction
來管理路由資料和變更。
import { Route } from "./+types/some-route";
export async function clientLoader({
params,
}: Route.ClientLoaderArgs) {
let data = await fetch(`/some/api/stuff/${params.id}`);
return data;
}
export async function clientAction({
request,
}: Route.ClientActionArgs) {
let formData = await request.formData();
return await processPayment(formData);
}
執行 react-router build
後,將 build/client
目錄部署到您偏好的任何靜態主機。
部署任何 SPA 的常見做法是,您需要設定您的主機以將所有 URL 導向客戶端建置的 index.html
。 某些主機預設會執行此操作,但其他主機則不會。 例如,主機可能支援 _redirects
檔案來執行此操作
/* /index.html 200
如果您在應用程式的有效路由上收到 404 錯誤,則可能是您需要設定您的主機。