React中的路由懒加载方案
在真实项目中,如果我们事先把所有组件全部导入进来,再基于Route做路由匹配,这样:最后项目打包的时候,所有组件全部打包到一个js中。
这样JS会非常的大:
- 第一次加载页面的时候,从服务器获取这个JS文件就会用很久的时间,导致此阶段页面一直处于白屏的状态,这样很不好
虽然说优化方案中,有建议合并为一个JS文件,这样减少HTTP网络请求的次数,但是这个JS文件不宜过大。
我们最好的处理方案是这样的:
- 我们只把最开始要展示的内容/组件打包到“主JS”中「bundle.js」,其余的组件,打包成独立的JS「或者几个组价合并在一起打包」
- 当页面加载的时候,首先只把“主JS”「bundle.js」请求回来渲染,其余的JS先不加载
- 因为bundle.js中只有最开始要渲染组件的代码,所以体积小,获取和渲染速度快,可以减少白屏等待的时间
- 其余的JS此时并没有加载,也不影响页面第一次渲染
- 当我路由切换的时候,和哪个规则匹配,想要渲染哪个组件,再把这个组件所在的JS文件,动态导入进来进行渲染即可
分割打包JS、按需异步加载JS ====> 路由懒加载
- 事先只把A组件【页面一加载就要渲染的组件】导入进来,也就是打包到bundle.js主JS文件中
- 借助React.lazy函数和ES6中的import实现
- 分割打包:每个组件单独打包为一个JS
- 按需导入/加载:最开始渲染页面不会加载这些单独的JS,只有路由规则匹配成功,需要渲染这个组件的时候,再去加载
一级路由路由文件routes.js:
import A from '../views/A'
import {
lazy } from 'react'
/* import B from '../views/B'
import C from '../views/C' */
import aRoutes from './aRoutes'
// 一级路由的路由表
const routes = [{
redirect: true,
from: '/',
to: '/a',
exact: true
}, {
path: '/a',
name: 'a',
component: A,
meta: {
},
children: aRoutes
}, {
path: '/b',
name: 'b',
component: lazy(() => import('../views/B')),
meta: {
}
}, {
path: '/c',
name: 'c',
component: lazy(() => import('../views/C')),
mata: {
}
}, {
redirect: true,
to: '/a'
}]
export default routes
二级路由路由文件aRoutes.js:
import A1 from "../views/a/A1"
import {
lazy } from "react"
/* import A2 from "../views/a/A2"
import A3 from "../views/a/A3" */
const aRoutes = [{
redirect: true,
from: '/a',
to: '/a/a1',
exact: true
}, {
path: '/a/a1',
name: 'a-a1',
component: lazy(() => import('../views/a/A1')),
meta: {
}
}, {
path: '/a/a2',
name: 'a-a2',
component: lazy(() => import('../views/a/A2')),
meta: {
}
}, {
path: '/a/a3',
name: 'a-a3',
component: lazy(() => import('../views/a/A3')),
meta: {
}
}]
export default aRoutes
原因:默认页面一加载就渲染A组件,然后A组件中二级路由重定向到/a/a1,加载渲染A1组件的js,这个过程是动态加载,异步加载过程中需要一个处理机制—路由懒加载,一定需要Suspense的支持。
Suspense.fallback:在异步加载的组件没有处理完成之前,先展示的Loading效果。
index.js:
import React, {
Suspense } from "react";
...
// 正常匹配规则
config = {
path }
if (exact) config.exact = true
return <Route key={
index} {