③ ReactSSR 实现路由

整理文件结构

最后的文件结构会变为下面的结构,有一些文件需要我们去继续完善

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
src/
├── app koa服务器相关文件
│ ├── errorHandle.ts
│ └── index.ts
├── components 组件文件夹
│ ├── header
│ │ ├── header.tsx (新增)
│ │ └── index.tsx (新增)
│ ├── hello
│ │ ├── hello.tsx
│ │ └── index.tsx
│ ├── index.tsx 组件的入口
│ ├── login
│ │ ├── index.tsx
│ │ └── login.tsx
│ ├── router.tsx 客户端路由 (新增)
│ └── routes.tsx 路由子项,可以和服务端渲染公用 (新增)
├── config
│ └── default.config.ts
├── router
│ ├── index.tsx koa的路由配置
│ └── router.tsx 服务端路由 (新增)
├── server.ts koa服务器入口文件
└── util
└── errorTypes.ts

客户端添加路由

添加一个简单的<Header/>组件,使用<Link/>组件添加路由跳转

1
2
3
4
5
6
7
8
9
10
11
12
13
import React from "react";
import {
Link
} from "react-router-dom";

const Header:React.FC = () =>{
return <div>
<Link to="/">hello</Link>
<Link to="/login">login</Link>
</div>
}

export default Header;

添加 src/routes.ts 提取路由公用部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import React from "react";
import {
Switch,
Route,
} from "react-router-dom";


import Hello from "./hello";
import Login from "./login";

const Routes = () => {
return (
<Switch>
<Route path="/hello">
<Hello />
</Route>
<Route path="/login">
<Login />
</Route>
<Route path="/">
<Hello />
</Route>
</Switch>
)
}
export default Routes;

添加 src/router.ts 客户端路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React from "react";
import Koa from 'koa';
import {
BrowserRouter,
} from "react-router-dom";

import Routes from './routes'

const Router:React.FC<unknown> = () =>{
return (
<BrowserRouter>
<Routes />
</BrowserRouter>
)
}

export default Router;

src/index.ts 最终导出App

1
2
3
4
5
6
7
8
9
10
import ReactDom from 'react-dom';
import React from 'react';
import Router from './router';

const App = () => {

return <Router />
}

ReactDom.hydrate(<App/>, document.getElementById('root'));

服务端路由

添加 router/touter.ts

因为服务端并不能感知到路由的变化,所以需要手动传递路由

当客户端渲染了一个 <Redirect> 浏览器历史改变并显示了新的屏幕,在服务端不能改变App的状态,所以使用context拿到渲染的结果,如果可以拿到context.url,就可以知道重定向的结果。可以让我们在服务中发起重定向.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React from "react";
import Koa from 'koa';
import {
StaticRouter,
} from "react-router-dom";

import Routes from '../components/routes'

const context={};

const Router:React.FC<unknown> = ({ctx}) =>{
return (
<StaticRouter location={ctx.url} context={context}>
<Routes />
</StaticRouter>
)
}

export default Router;

router/index.tsx

需要添加root元素,并匹配所有路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import Router from '@koa/router';
import ReactDOMServer from 'react-dom/server';
import React from 'react';
import App from './router';
const router = new Router();

router.get("/(.*)",async (ctx,next)=>{
console.log(ctx);
ctx.body=`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id='root'>${ReactDOMServer.renderToString(<App {...{ctx}}/>)}</div>
<script src='/index.js'></script>
</body>
</html>
`
})

export default router;
打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2015-2025 SunZhiqi

此时无声胜有声!

支付宝
微信