# React 优化 - 路由懒加载
使用步骤
- 使用 lazy 方法导入路由组件
- 使用内置的 Suspense 组件渲染路由组件
代码实现
router/index.js
例如下面的代码
import { createBrowserRouter } from 'react-router-dom' | |
import { lazy, Suspense } from 'react' | |
import Login from '@/pages/Login' | |
import Layout from '@/pages/Layout' | |
import AuthRoute from '@/components/Auth' | |
// 使用 lazy 方法导入路由组件 | |
const Publish = lazy(() => import('@/pages/Publish')) | |
const Article = lazy(() => import('@/pages/Article')) | |
const Home = lazy(() => import('@/pages/Article')) | |
const router = createBrowserRouter([ | |
{ | |
path: '/', | |
element: ( | |
<AuthRoute> | |
<Layout /> | |
</AuthRoute> | |
), | |
children: [ | |
{ | |
index: true, | |
element: ( | |
<Suspense fallback={'加载中'}> | |
<Home /> | |
</Suspense> | |
) | |
}, | |
{ | |
path: 'article', | |
element: ( | |
// 使用内置的 Suspense 组件渲染路由组件 | |
//fallback 就相对于 loading,组件未加载完成时显示的内容 | |
<Suspense fallback={'加载中'}> | |
<Article /> | |
</Suspense> | |
) | |
}, | |
{ | |
path: 'publish', | |
element: ( | |
<Suspense fallback={'加载中'}> | |
<Publish /> | |
</Suspense> | |
) | |
}, | |
], | |
}, | |
{ | |
path: '/login', | |
element: <Login />, | |
}, | |
]) | |
export default router |
查看效果
我们可以在打包之后,通过切换路由,监控 network 面板资源的请求情况,验证是否分隔成功
# React 优化 - 打包体积分析
业务背景
通过分析打包体积,才能知道项目中的哪部分内容体积过大,方便知道哪些包如何来优化
使用步骤
- 安装分析打包体积的包:
npm i source-map-explorer - 在 package.json 中的 scripts 标签中,添加分析打包体积的命令
- 对项目打包:
npm run build(如果已经打过包,可省略这一步) - 运行分析命令:
npm run analyze - 通过浏览器打开的页面,分析图表中的包体积
核心代码:
"scripts": { | |
"analyze": "source-map-explorer 'build/static/js/*.js'", | |
} |
# React 优化 - 配置 CDN
分析说明:通过 craco 来修改 webpack 配置,从而实现 CDN 优化
核心代码
craco.config.js
// 添加自定义对于 webpack 的配置 | |
const path = require('path') | |
const { whenProd, getPlugin, pluginByName } = require('@craco/craco') | |
module.exports = { | |
//webpack 配置 | |
webpack: { | |
// 配置别名 | |
alias: { | |
// 约定:使用 @ 表示 src 文件所在路径 | |
'@': path.resolve(__dirname, 'src') | |
}, | |
// 配置 webpack | |
// 配置 CDN | |
configure: (webpackConfig) => { | |
let cdn = { | |
js:[] | |
} | |
whenProd(() => { | |
//key: 不参与打包的包 (由 dependencies 依赖项中的 key 决定) | |
//value: cdn 文件中 挂载于全局的变量名称 为了替换之前在开发环境下 | |
webpackConfig.externals = { | |
react: 'React', | |
'react-dom': 'ReactDOM' | |
} | |
// 配置现成的 cdn 资源地址 | |
// 实际开发的时候 用公司自己花钱买的 cdn 服务器 | |
cdn = { | |
js: [ | |
'https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.production.min.js', | |
'https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.production.min.js', | |
] | |
} | |
}) | |
// 通过 htmlWebpackPlugin 插件 在 public/index.html 注入 cdn 资源 url | |
const { isFound, match } = getPlugin( | |
webpackConfig, | |
pluginByName('HtmlWebpackPlugin') | |
) | |
if (isFound) { | |
// 找到了 HtmlWebpackPlugin 的插件 | |
// match.userOptions.files = cdn | |
match.options.files = cdn | |
} | |
return webpackConfig | |
} | |
} | |
} |
public/index.html
<body> | |
<div id="root"></div> | |
<!-- 加载第三发包的 CDN 链接 --> | |
<% htmlWebpackPlugin.options.files.js.forEach(cdnURL => { %> | |
<script src="<%= cdnURL %>"></script> | |
<% }) %> | |
</body> |