likes
comments
collection
share

React Router v6 路由懒加载的2种方式

作者站长头像
站长
· 阅读数 3

介绍

React Router v6 的路由懒加载有2种实现方式,1是使用react-router自带的 route.lazy,2是使用React自带的 React.lazy

下面介绍这两种实现方式

注:本文内容针对配置式路由,非约定式路由

0. 相同代码的部分

当前我的依赖包版本 package.json:

{
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.14.0"
  },
  "devDependencies": {
    "@types/node": "^18.15.11",
    "@types/react": "^18.0.28",
    "@types/react-dom": "^18.0.11",
    "@vitejs/plugin-react": "^3.1.0",
    "typescript": "^4.9.3",
    "vite": "^4.2.0"
  },
}

入口文件 src/App.tsx:

import './App.less'
import React from 'react'
import { RouterProvider } from 'react-router-dom'
import { router } from '@/routes'

function App() {
  return <RouterProvider router={router} />
}

export default App

1. React.lazy

依赖 React.lazy + React.Suspense

src/routes/index.tsx:

import React from 'react'
import { createHashRouter, Navigate, RouteObject } from 'react-router-dom'
import Loading from '@/components/Loading'
import BasicLayout from '@/layouts/BasicLayout'
import Page404 from '@/pages/common/404'
import PageLogin from '@/pages/login'

const Page_goodsMng = React.lazy(() => import('@/pages/goods/goodsMng'))

const route404 = {
  path: '*',
  element: <Page404 />,
}

const routes: RouteObject[] = [
  {
    path: '/login',
    element: <PageLogin />
  },
  {
    element: <BasicLayout />,
    children: [
      //// 懒加载代码
      // 商品管理
      {
        path: '/web/company/goods/goodsmgr',
        element: (
          <React.Suspense fallback={<Loading />}>
            <Page_goodsMng />
          </React.Suspense>
        ),
      },
      route404,
    ],
  },
  route404,
]

export default routes

export const router = createHashRouter(routes as any)

2. react-router 自带的 route.lazy

src/routes/index.tsx:

import React from 'react'
import { createHashRouter, Navigate, RouteObject } from 'react-router-dom'
import Loading from '@/components/Loading'
import BasicLayout from '@/layouts/BasicLayout'
import Page404 from '@/pages/common/404'
import PageLogin from '@/pages/login'

const routes: RouteObject[] = [
  {
    path: '/login',
    element: <PageLogin />
  },
  {
    element: <BasicLayout />,
    children: [
      //// 懒加载代码
      // 商品管理
      {
        path: '/web/company/goods/goodsmgr',
        // use react-router route.lazy
        lazy: async () => ({
          Component: (await import('@/pages/goods/goodsMng')).default,
        }),
      },
      route404,
    ],
  },
  route404,
]

export default routes

export const router = createHashRouter(routes as any)

3. 两种方式的区别

React.lazy的方式可以配置加载时的fallback,route.lazy则不支持,也就是说当懒加载的路由内容很大时,route.lazy的方式很有可能有一段时间的白屏。

除了fallback,目前我的体验上还没发现其他的区别,如果还有其他的区别可以评论区讨论一下奥

所以对比来看的话,route.lazy好像没有什么优势

那么我就有疑问了,我觉得fallback这个属于比较基础的功能,react-router既然加入的route.lazy的用法,为什么不加 fallback 呢

4. React Router 为什么不自带fallback功能,要怎么处理?

我找到了一个react-router的issues,问了相同的问题,react-router的作者之一进行了回答,1是印证了react-router确实没有自带fallback的功能,2是回答了作者是如何考虑,以及如果想增加fallback的效果要怎么处理

issues: github.com/remix-run/r…

作者认为:

React Router v6 路由懒加载的2种方式

简单说...这好像就是作者喜好的问题?

React Router 官网的效果是,跳转路由过程中(懒加载过程),当前页面淡出、顶部增加进度条的方式,而非fallback的loading方式

4.1 useNavigation

如果使用route.lazy的方式,可以使用这个 useNavigation 这个hooks,来判断路由是否是loading的状态

经过测试,页面跳转时,navigation为loading

React Router v6 路由懒加载的2种方式