React SSR - 02 路由支持、Redux 支持、防止 XSS 攻击

本文介绍了一个React服务端渲染(SSR)项目的实现过程,包括客户端和服务端的路由与Redux支持,以及如何解决服务端渲染中遇到的数据获取问题。

路由支持

实现思路

在 React SSR 项目中需要实现两端路由:

  • 客户端路由用于支持用户通过点击链接的形式跳转页面。

  • 服务器端路由用于支持用户直接从浏览器地址栏中访问页面。

客户端和服务器端共用一套路由规则,所以路由规则代码属于同构代码。

新增一个页面

新增一个 List 页面用于测试路由切换:

// src\share\pages\List.js
import React from 'react'

function List() {
   
   
  return <div>List works</div>
}

export default List

安装路由依赖

react-router-dom # react 路由模块
react-router-config # react 路由规则配置模块(通过数组对象的方式集中配置路由规则)

编写路由规则

react-router-config 用于辅助 React 路由,可以通过数组对象格式配置路由规则。

使用它提供的 renderRoutes 方法可以将数组对象格式的路由规则转换成<Switch><Route>组件去渲染。

// src\share\routes.js
import Home from './pages/Home'
import List from './pages/List'

const routes = [
  {
   
   
    path: '/',
    component: Home,
    exact: true // 精确匹配
  },
  {
   
   
    path: '/list',
    component: List,
    exact: true // 精确匹配
  }
]

export default routes


// renderRoutes(routes) 会被转换成:
/*
<Switch>
  <Route path="/" exact>
    <Home />
  </Route>
  <Route path="/list" exact>
    <List />
  </Route>
</Switch>
*/

实现服务器端路由

1 Express 路由接收任何请求

Express 路由接收所有 GET 请求,将请求信息传递给服务端渲染方法。

服务器端 React 路由通过请求路径匹配要进行渲染的组件。

// src/server/index.js
import app from './http'
import renderer from './renderer'

app.get('*', (req, res) => {
   
   
  res.send(renderer(req))
})

2 服务器端路由配置

使用静态路由组件 <StaticRouter> 代替 <BrowserRouter>

<StaticRouter> 用于服务器端渲染,它没有路由跳转功能,将客户端请求的地址传递给 location 属性,<StaticRouter> 渲染 location 匹配的组件。

// src\server\renderer.js
import React from 'react'
import {
   
    renderToString } from 'react-dom/server'
import {
   
    StaticRouter } from 'react-router-dom'
import {
   
    renderRoutes } from 'react-router-config'
import routes from '../share/routes'

export default req => {
   
   
  const content = renderToString(
    <StaticRouter location={
   
   req.path}>
    	{
   
   renderRoutes(routes)}
    </StaticRouter>
  )
  return `
    <html>
      <head>
        <title>React SSR</title>
      </head>
      <body>
        <div id="root">${
     
     content}</div>
        <script src="/bundle.js"></script>
      </body>
    </html>
  `
}

关闭客户端二次渲染

现在由于客户端二次渲染(hydrate),访问 http://localhost:3000/list会被重新渲染为 / 路由内容。

有两个方式可以关闭客户端二次渲染

  1. 取消加载二次渲染脚本
    • 删掉 <script src="/bundle.js"></script>
  2. 浏览器禁止运行 JavaScript 脚本
    • Chrome 为例,在设置中搜索 JavaScript,进入网站设置 - JavaScript

实现客户端路由

客户端路由实现的方式和客户端渲染一样。

// src\client\index.js
import React from 'react'
import ReactDOM from 'react-dom'
import {
   
    BrowserRouter } from 'react-router-dom'
import {
   
    renderRoutes } from 'react-router-config'
import routes from '../share/routes'

ReactDOM.hydrate(
  <BrowserRouter>
    {
   
   renderRoutes(routes)}
  </BrowserRouter>,
  document.getElementById('root')
)

添加一个链接测试客户端路由跳转是否成功:

// src\share\pages\Home.js
import React from 'react'
import {
   
    Link } from 'react-router-dom'

function Home() {
   
   
  return (
    <div
      onClick={
   
   () => {
   
   
        console.log('click')
      }}
    >
      Home works
      <Link to="/list"
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值