使用 React Router 构建单页应用有两种方式
当将 React Router 用作框架时,您可以通过在 react-router.config.ts
文件中设置 ssr:false
来启用“SPA 模式”。这将禁用运行时服务器渲染,并在构建时生成一个 index.html
,您可以将其作为 SPA 提供和水合。
典型的单页应用发送一个几乎空白的 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 的入口点提供。这将仅渲染根路由,使其能够在运行时为应用程序中的任何路径进行水合。
为了提供比空的 <div>
更好的加载 UI,您可以向根路由添加一个 HydrateFallback
组件,以在构建时将加载 UI 渲染到 index.html
中。这样,在 SPA 加载/水合时,它将立即显示给用户。
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
属性提供。
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
来管理路由数据和 mutation。
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 错误,则可能是您需要配置主机。