如果您未使用 <RouterProvider>
,請改為參閱從元件路由採用框架。
React Router Vite 外掛程式為 React Router 新增了框架功能。本指南將協助您在應用程式中採用此外掛程式。如果您遇到任何問題,請透過 Twitter 或 Discord 尋求協助。
Vite 外掛程式新增了
初始設定需要最多的工作。但是,一旦完成,您就可以逐步採用新功能。
若要使用 Vite 外掛程式,您的專案需要
React Router Vite 外掛程式會渲染自己的 RouterProvider
,因此您無法在其內渲染現有的 RouterProvider
。相反地,您需要格式化所有路由定義以符合路由模組 API。
此步驟將花費最長的時間,但是無論是否採用 React Router Vite 外掛程式,執行此步驟都有幾個好處
👉 將您的路由定義移至路由模組中
將路由定義的每個部分匯出為個別的具名匯出,遵循路由模組 API。
export async function clientLoader() {
return {
title: "About",
};
}
export default function About() {
let data = useLoaderData();
return <div>{data.title}</div>;
}
// clientAction, ErrorBoundary, etc.
👉 建立轉換函式
建立一個輔助函式,將路由模組定義轉換為資料路由器預期的格式
function convert(m: any) {
let {
clientLoader,
clientAction,
default: Component,
...rest
} = m;
return {
...rest,
loader: clientLoader,
action: clientAction,
Component,
};
}
👉 延遲載入並轉換您的路由模組
不要直接匯入路由模組,而是延遲載入並將其轉換為資料路由器預期的格式。
您的路由定義現在不僅符合路由模組 API,而且還能獲得程式碼分割路由的好處。
let router = createBrowserRouter([
// ... other routes
{
path: "about",
- loader: aboutLoader,
- Component: About,
+ lazy: () => import("./routes/about").then(convert),
},
// ... other routes
]);
針對應用程式中的每個路由重複此程序。
一旦您的所有路由定義都轉換為路由模組,您就可以採用 React Router Vite 外掛程式。
👉 安裝 React Router Vite 外掛程式
npm install -D @react-router/dev
👉 安裝執行階段轉接器
我們假設您使用 Node 作為您的執行階段。
npm install @react-router/node
👉 將 React 外掛程式換成 React Router
-import react from '@vitejs/plugin-react'
+import { reactRouter } from "@react-router/dev/vite";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [
- react()
+ reactRouter()
],
});
👉 建立 react-router.config.ts
檔案
將以下內容新增至專案的根目錄。在此設定中,您可以告訴 React Router 關於您的專案,例如在哪裡找到應用程式目錄,以及暫時不使用 SSR (伺服器端渲染)。
touch react-router.config.ts
import type { Config } from "@react-router/dev/config";
export default {
appDirectory: "src",
ssr: false,
} satisfies Config;
在典型的 Vite 應用程式中,index.html
檔案是捆綁的進入點。React Router Vite 外掛程式將進入點移至 root.tsx
檔案,以便您可以使用 React 渲染應用程式的外殼,而不是靜態 HTML,並且最終在需要時升級到伺服器渲染。
👉 將現有的 index.html
移至 root.tsx
例如,如果目前的 index.html
看起來像這樣
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>My App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
您會將該標記移至 src/root.tsx
並刪除 index.html
touch src/root.tsx
import {
Links,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from "react-router";
export function Layout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<head>
<meta charSet="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>My App</title>
<Meta />
<Links />
</head>
<body>
{children}
<ScrollRestoration />
<Scripts />
</body>
</html>
);
}
export default function Root() {
return <Outlet />;
}
👉 將 RouterProvider
上方的所有內容移至 root.tsx
任何全域樣式、內容提供者等都應移至 root.tsx
,以便它們可以在所有路由之間共用。
例如,如果您的 App.tsx
看起來像這樣
import "./index.css";
export default function App() {
return (
<OtherProviders>
<AppLayout>
<RouterProvider router={router} />
</AppLayout>
</OtherProviders>
);
}
您會將 RouterProvider
上方的所有內容移至 root.tsx
。
+import "./index.css";
// ... other imports and Layout
export default function Root() {
return (
+ <OtherProviders>
+ <AppLayout>
<Outlet />
+ </AppLayout>
+ </OtherProviders>
);
}
在典型的 Vite 應用程式中,index.html
檔案指向 src/main.tsx
作為用戶端進入點。React Router 改為使用名為 src/entry.client.tsx
的檔案。
如果 entry.client.tsx
不存在,React Router Vite 外掛程式將使用預設的隱藏檔案。
👉 將 src/entry.client.tsx
作為您的進入點
如果目前的 src/main.tsx
看起來像這樣
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router";
import App from "./App";
const router = createBrowserRouter([
// ... route definitions
]);
ReactDOM.createRoot(
document.getElementById("root")!
).render(
<React.StrictMode>
<RouterProvider router={router} />;
</React.StrictMode>
);
您會將其重新命名為 entry.client.tsx
並將其變更為這樣
import React from "react";
import ReactDOM from "react-dom/client";
import { HydratedRouter } from "react-router/dom";
ReactDOM.hydrateRoot(
document,
<React.StrictMode>
<HydratedRouter />
</React.StrictMode>
);
hydrateRoot
而不是 createRoot
<HydratedRouter>
而不是您的 <App/>
元件<RouterProvider />
。我們將在下一步遷移我們的路由定義。React Router Vite 外掛程式使用 routes.ts
檔案來設定您的路由。格式將與您的資料路由器的定義非常相似。
👉 將定義移至 routes.ts
檔案
touch src/routes.ts src/catchall.tsx
將您的路由定義移至 routes.ts
。請注意,結構描述並不完全相符,因此您會收到型別錯誤;我們將在下一步修正此問題。
+import type { RouteConfig } from "@react-router/dev/routes";
-const router = createBrowserRouter([
+export default [
{
path: "/",
lazy: () => import("./routes/layout").then(convert),
children: [
{
index: true,
lazy: () => import("./routes/home").then(convert),
},
{
path: "about",
lazy: () => import("./routes/about").then(convert),
},
{
path: "todos",
lazy: () => import("./routes/todos").then(convert),
children: [
{
path: ":id",
lazy: () =>
import("./routes/todo").then(convert),
},
],
},
],
},
-]);
+] satisfies RouteConfig;
👉 將 lazy
載入器取代為 file
載入器
export default [
{
path: "/",
- lazy: () => import("./routes/layout").then(convert),
+ file: "./routes/layout.tsx",
children: [
{
index: true,
- lazy: () => import("./routes/home").then(convert),
+ file: "./routes/home.tsx",
},
{
path: "about",
- lazy: () => import("./routes/about").then(convert),
+ file: "./routes/about.tsx",
},
{
path: "todos",
- lazy: () => import("./routes/todos").then(convert),
+ file: "./routes/todos.tsx",
children: [
{
path: ":id",
- lazy: () => import("./routes/todo").then(convert),
+ file: "./routes/todo.tsx",
},
],
},
],
},
] satisfies RouteConfig;
檢視我們關於設定路由的指南,以深入瞭解 routes.ts
檔案和輔助函式,以進一步簡化路由定義。
此時,您應該已完全遷移到 React Router Vite 外掛程式。繼續更新您的 dev
指令碼並執行應用程式,以確保一切正常運作。
👉 新增 dev
指令碼並執行應用程式
"scripts": {
"dev": "react-router dev"
}
現在請確保您可以在此時啟動您的應用程式,然後再繼續
npm run dev
您可能會想要將 .react-router/
新增至您的 .gitignore
檔案,以避免追蹤儲存庫中不必要的檔案。
.react-router/
您可以查看型別安全,以瞭解如何完整設定和使用自動產生的型別安全,以用於參數、載入器資料等。
如果您想要啟用伺服器渲染和靜態預先渲染,您可以使用捆綁器外掛程式中的 ssr
和 prerender
選項來執行此操作。對於 SSR,您還需要將伺服器組建部署到伺服器。請參閱部署以取得更多資訊。
import type { Config } from "@react-router/dev/config";
export default {
ssr: true,
async prerender() {
return ["/", "/about", "/contact"];
},
} satisfies Config;