内容简介:利用
利用 懒加载(Lazy Loading)
优化页面性能不是什么新概念,不过React 16.6可以使用 React.lazy
与 Suspense
让原生React实现Lazy Loading大大的简化。
本篇文章也会拓展多种类似解决方案,见 拓展
部分
主要关键词说明
动态导入(Dynamic Import)
动态导入
目前只是TC39的一个提案,不是JS(ES)标准的一部分。该功能可以动态化加载我们分割的组件/页面/文件,具体提案见下方链接: TC39 proposal-dynamic-import提案
目前要使用 动态导入
,需要使用到babel插件:
babel-plugin-syntax-dynamic-import
React.lazy
lazy函数
提供了一种非常简便的方法动态导入组件,实现按需加载与代码分割
React.lazy使用方式非常简单,示例:
// lazy 接受一个函数作为参数 const MyComponent = React.lazy(() => import('path/MyComponent')); // 展示时才加载(可以自定义一些条件) const App = () => ( <div> <MyComponent /> </div> ) 复制代码
Suspense
Suspense
组件用于包装lazy组件,在lazy组件还没有完全加载时,将fallback内容呈现给用户。
用动态加载,编译时会将文件分割,从加载文件到呈现会有时间延迟,此时可以使用 Suspense
展示一个loading。
使用示例
import React, { Suspense } from 'react'; const MyComponent = React.lazy(() => import('path/MyComponent')); const Loading = ( <h3>loading...</h3> ); const App = () => ( <div> <Suspense fallback={Loading}> <MyComponent /> </Suspense> </div> ) 复制代码
ErrorBoundary
ErrorBoundary(错误边界)
,可以使用ErrorBoundary包装Suspense,当Suspense出错时,统一处理错误。当然 ErrorBoundary
不止可用于Suspense,可以包装任意组件,然后统一处理错误。
实际场景中,可以自己先写一些通用错误页/组件继承自 ErrorBoundary
,然后包装要处理的组件。
也可以在组件的 componentDidCatch
生命周期中单独处理错误。
应用
性能优化说明
针对React加载的优化,可以分为两类:
- 页面加载优化
- 组件加载优化
很明显,React.lazy + Suspense可以很方便的应用于组件加载优化场景。
示例场景
CSR(客户端渲染)应用
多页面的中某个耗时组件的加载
路由层
import React from 'react'; import { BrowserRouter as Router, Route } from 'react-router-dom'; import Header from './header'; import Index from '../pages'; import Welcome from '../pages/welcome'; export default () => ( <Router> <div> <Header /> <Route exact path="/" component={Index}/> <Route path="/welcome" component={Welcome}/> </div> </Router> ); 复制代码
某个存在耗时组件的页面
// welcome.js import React, { Suspense } from 'react'; // 使用Suspense + React.lazy动态加载的耗时组件 const Content = React.lazy(() => import('../components/content')); export default () => ( <div> <h1>Welcome</h1> <Suspense fallback={<div>loading...</div>}> <Content/> </Suspense> </div> ); 复制代码
说明
假设用webpack编译上面代码产出bundle.js。当进入首页时,加载的bundle.js不会包含Welcome Content部分的代码,切换页面到Welcome时会走网络加载需要的文件。
利用这种方法拆分多个组件时,可以显著的提升首屏时间。
完整示例项目
说明:该项目主要用于React一些新功能及有意思的用法示例,会持续更新,后面会涉及到 hooks
及最新源码相关,有兴趣的可以star。
拓展
针对SSR(服务端渲染)应用导入性能优化
可以使用 Next.js ,Next.js已支持直接使用dynamic import,并且可以指明什么时候动态导入(服务端/客户端),Next.js对首屏做了很多优化,首屏时,服务端会寻找到最简依赖渲染,具体可以点击前面链接查看文档。示例:
// Next.js 动态导入 const MyComponent = dynamic(import('../components/MyComponent'), { ssr: false, loading: () => false, }); 复制代码
针对组件的动态加载
针对图片的lazy loading
针对动态请求
- react-request :对于CSR应用,在不用hooks的情况下,也可以不在componentDidMount中处理请求,让请求更加的优雅。
-
react-async
:利用
Render Props + React hooks + Context API
统一处理请求,支持SSR使用
封装 react-request
示例(统一请求处理)
import React from 'react'; import PropTypes from 'prop-types'; import { Fetch } from 'react-request'; // import ReactLoading from 'react-loading'; import config from '../../config'; const CustomFetch = (props) => { const { url, children } = props; return ( <Fetch {...props} url={config.serverUrl + url} transformData={data => data.data} > {({ fetching, failed, data }) => { if (fetching) { // 正在请求:可以展示loading动画 // return <ReactLoading type="cylon" color="#2db53f" height="10%" width="10%" />; } if (failed) { // 当前组件请求失败 // return <h1 className="home">请求失败...</h1>; } if (data) { // 请求成功 return children(data); } return null; }} </Fetch> ); }; CustomFetch.propTypes = { url: PropTypes.string.isRequired, }; export default CustomFetch; 复制代码
在组件中使用CustomFetch
buildLinks = () => ( <div className="links"> <CustomFetch url="/getLinks" > {data => data.map((item, index) => ( <a className="item" href={item.url} key={`link-${index}`}> <img src={item.icon} className="icon" alt={item.name} /> <p>{item.name}</p> </a> ))} </CustomFetch> </div> ); 复制代码
以上所述就是小编给大家介绍的《利用React 16.6新特性优化应用性能》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Redis 命令、特性介绍与性能调优
- Redis基础、高级特性与性能调优
- Mozilla 将主攻 WebAssembly 的性能和特性
- Kotlin 1.3.30 发布,改进性能和引入新特性
- Composer 2.0 发布带来的性能优化、新特性和升级指南
- GNOME 3.32 Beta 发布,带来性能改进和新特性
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。