React性能优化(完整版)
- 我的博客
- http://wangxince.site/my-demo-markdown/
React 性能优化
1.减少 render 次数
shouldComponentUpdate PureComponent
shouldComponentUpdate(nextProps,nextState) {return !this.props.xxx === nextProps.xxx
}
// PureComponent 自动浅对比
React.Memo
// 1.当props变化的时候才会重新渲染 浅层对比
function Component(props) {}
const MyComponent = React.memo(Component);
// 2.自定义比较对比Props 如果相等返回true 否则返回false
function MyComponent(props) {}
export default React.memo(MyComponent, (prevProps, nextProps) => boolean);
2.减少函数的重新执行导致的渲染: useCallback
<button onClick={props.onClick}>改标题</button>
// 组件的每次渲染都会重新创建一个新的函数 因此函数的引用地址发生了变化
// 函数会重新开始执行 倒是子组件重新渲染
// 解决办法就是在函数没有改变的时候,重新渲染的时候保持两个函数的引用一致
const memoizedCallback = useCallback(()=>{}, [])
<Child onClick={memoizedCallback} name="xxx" />
3.缓存计算量比较大的函数结果: useMemo
- 如果没有提供依赖项数组,useMemo 在每次渲染时都会计算新的值
- 计算量如果很小的计算函数,也可以选择不使用 useMemo,因为这点优化并不会作为性能瓶颈的要点,反而可能使用错误还会引起一些性能问题
const base = useMemo(fn, []);
4.其他优化
1.在 render 渲染函数中不要进行复杂的副作用(数组排序 等等)
2.减少不必要的嵌套
3.虚拟列表
- https://usehooks-ts.com/react-hook/use-intersection-observer
4.惰性渲染 && 惰性函数
- 惰性加载表示函数执行的分支只会在函数第一次调用的时候执行。在第一次调用的过程中。
- 该函数被覆盖为另一个按照合适的方式执行的函数。这样任何对原函数的调用就不用再经过执行的分支了
#var timeStamp = null;function getTimeStamp() {if (timeStamp) {return timeStamp}// 直接为外界的变量赋值timeStamp = new Date().getTime()return timeStamp;}console.log(getTimeStamp());console.log(getTimeStamp());console.log(getTimeStamp());console.log(getTimeStamp());
# 自执行函数 避免污染全局变量var getTimeStamp = (function () {var timeStamp = null;return function () {if (timeStamp) {return timeStamp;}timeStamp = new Date().getTime()return timeStamp;}})()
# 第一次只是在给函数重新定义 第二次执行时候才生效var getTimeStamp = function () {var timeStamp = new Date().getTime()getTimeStamp = function () {return timeStamp}return getTimeStamp()}
# element ui 源码 处理 dom 事件
export const on = (function() {if (!isServer && document.addEventListener) {return function(element, event, handler) {if (element && event && handler) {element.addEventListener(event, handler, false);}};} else {return function(element, event, handler) {if (element && event && handler) {element.attachEvent('on' + event, handler);}};}
})();
#function test(num) {switch (num) {case 1:test = () => 1break;case 2:test = () => 2break;case 3:test = () => 3break;default:test = () => nullbreak;}return test()}console.log(test(null)); // null
5.减少使用箭头函数 => 实例方法
- 使用箭头函数的情况下,每次组件的重新渲染都创建新的事件处理程序,这会导致子组件重新渲染
// 1.class
<ComplexComponent onClick={evt => onClick(evt.id)} otherProps={values} />;
class MyComponent extends Component {render() {<ComplexComponent onClick={this.handleClick} otherProps={values} />;}handleClick = () => {};
}
// 2.hooks 使用useCallback包裹
const handleClick = useCallback(() => {}, []);
return <ComplexComponent onClick={handleClick} otherProps={values} />;
// 3.当状态很多时候
function useRefProps<T>(props: T) {const ref = useRef < T > props;// 每次渲染更新propsuseEffect(() => {ref.current = props;});
}function MyComp(props) {const propsRef = useRefProps(props);// 现在handleClick是始终不变的const handleClick = useCallback(() => {const { foo, bar, baz, bazz, bazzzz } = propsRef.current;}, []);
}
// 4.class需要bind的时候
// 不要这样 <input type="button" value="Click" onClick={this.handleButtonClick.bind(this)} />
<input type="button" value="Click" onClick={this.handleButtonClick} />;constructor() {this.state = {name: "Mayank"}this.handleButtonClick = this.handleButtonClick.bind(this)}
6.使用 Immutable.js
7.简化 state 和 props
- 不是所有数据都需要放在 state 里面
- 如果需要组件响应它的变动, 或者需要渲染到视图中的数据才应该放到 state 中
- 这样可以避免不必要的数据变动导致组件重新渲染
8.颗粒化组件
- vue 不需要 shouldComponentUpdate 会自动优化
- 但是如果太过耦合 只要要任意一个属性值变动就会重新渲染整个组件
- 应该将数据隔离抽取到单一职责的组件
- 越细粒度的组件,可以收获更高的性能优化效果
8.懒加载异步组件
- lazy Suspense
- 减少主包体积 减少网络带宽
if (this.props.name == 'Mayank') {ComponentToLazyLoad = lazy(() => import('./mayankComponent'));
} else if (this.props.name == 'Anshul') {ComponentToLazyLoad = lazy(() => import('./anshulComponent'));
}
<div><h1>This is the Base User: {this.state.name}</h1><Suspense fallback={<div>Loading...</div>}><ComponentToLazyLoad /></Suspense>
</div>;
8.用 Fragment 代替自己最外层写的元素
9.复杂变动的组件+Key
- 并不是只有 map 渲染的时候才能写 key
- element 等组件库会将一些 API 利用 computed 缓存(computed 只有当 props 和 data 中的变量变化的时候才会重新缓存)
- vue 的 diff 算法有时候自动计算会直接缓存
- (比如你写了两个 El-Button 这时候 diff 算法将他们当成一个,而组件库内部的 computed 没有重新计算)
- 此时就可能产生值变化 但是表单的 API 未变化的 bug
- 这时候就需要给其加不同的 key
10.避免使用内联样式
- <b style={{“backgroundColor”: “blue”}}>Welcome to Sample Page
11.防流节抖
12.CDN
13.gzip 压缩
http{gzip on; #开启gzip功能gzip_types *; #压缩源文件类型,根据具体的访问资源类型设定gzip_comp_level 6; #gzip压缩级别gzip_min_length 1024; #进行压缩响应页面的最小长度,content-lengthgzip_buffers 4 16K; #缓存空间大小gzip_http_version 1.1; #指定压缩响应所需要的最低HTTP请求版本gzip_vary on; #往头信息中添加压缩标识gzip_disable "MSIE [1-6]\."; #对IE6以下的版本都不进行压缩gzip_proxied off; #nginx作为反向代理压缩服务端返回数据的条件
}
14.webpack 拆包
css 抽离
plugins: [new MiniCssExtractPlugin({// 对输出的css文件进行重命名filename: 'css/built.css'}),// 压缩cssnew OptimizeCssAssetsWebpackPlugin()
]#{test: /\.css$/,use: [ 'file-loader']['file-loader?name=[name].bundle[hash].css']},
js 抽离
output: {filename: 'js/[name].js',path: path.resolve(__dirname, 'dist'),},
代码切割
1. 多入口 自动打包多个文件entry: {'jquery': './src/index.js','angular': './src/2.js'},
2. 异部的chunkrequire.ensure([],function(_require){_require('./xxx')})import('./2.css').then(() => {...})
}
#
3.
optimization: {splitChunks: {chunks: 'all'}
}
#
externals: {jquery: 'jQuery'
}
引入cdn
dll
#
硬链接一个 包,再手动scrit引入这个包 之后webpack就不用编译了
#
yarn add add-asset-html-webpack-plugin
webpack --config webpack.config.dll.js && webpack
# 文件路径webpack.config.jswebpack.config.dll.jsdistindex.htmlsrcpublicdlljquerymanifest.json
# webpack.config.js
const path = require('path')
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
module.export = {...externals: {jquery: 'jQuery'},plugins:[new HtmlWebpackPlugin({template: './index.html',filename: 'index.html',minify: { removeComments: true }}),// 告诉webpack哪些库不参与打包,同时使用时的名称也得变~new webpack.DllReferencePlugin({manifest: resolve(__dirname, 'dll/manifest.json')}),// 将某个文件打包输出去,并在html中自动引入该资源new AddAssetHtmlPlugin({filepath: path.resolve(__dirname, 'dll/jquery.js'),publicPath: '../dll',outputPath: 'vendor',}),]
}
# webpack.config.dll.js
const path = require('path');
const webpack = require('webpack')
module.exports = {entry: {jquery: ['jquery'],},output: {filename: '[name].js',path: path.resolve(__dirname, 'dll'),library: '[name]_[hash]'},plugins: [// 打包生成一个 manifest.json --> 提供和jquery映射new webpack.DllPlugin({// 映射库的暴露的内容名称 和 library 相同name: '[name]_[hash]',path: path.join(__dirname, 'dll/manifest.json'),})],mode: 'production'
};
externals: {jquery: 'jQuery'
},
new webpack.ProvidePlugin({$: path.resolve(path.join(__dirname, 'dll/jquery.js'))
}),
其他 cli 集成
chainWebpack: function(config, { webpack }) {config.merge({optimization: {splitChunks: {chunks: 'all',minSize: 30000,minChunks: 3,automaticNameDelimiter: '.',cacheGroups: {vendor: {name: 'vendors',test({ resource }: any) {return /[\\/]node_modules[\\/]/.test(resource);},priority: 10,},},},},});},
React性能优化(完整版)相关推荐
- react性能优化方案_React灵敏且性能卓越的Spray + Akka解决方案,以“在Java和Node.js中发挥并发性和性能”...
react性能优化方案 在我以前的文章中,我研究了一个虚拟的交易引擎,并将基于Java的阻止解决方案与基于Node.js的非阻止解决方案进行了比较. 在文章的结尾,我写道: 我怀疑随着Node.js的 ...
- [react] 你知道的react性能优化有哪些方法?
[react] 你知道的react性能优化有哪些方法? shouldComponentUpdate PureComponent :Class Component React.Memo :Functio ...
- React性能优化记录(不定期更新)
React性能优化记录(不定期更新) 1. 使用PureComponent代替Component 在新建组件的时候需要继承Component会用到以下代码 import React,{Componen ...
- React性能优化SCU | PureComponent | memo
文章目录 React性能优化SCU React更新机制 render函数被调用 PureComponent 高阶组件memo React性能优化SCU React更新机制 我们在前面文章已经讲解过Re ...
- Airbnb 爱彼迎房源详情页中的 React 性能优化
Airbnb 爱彼迎工程师和数据科学家将定期和大家分享移动开发.系统架构.数据科学及人工智能等领域的技术探索和经验心得. 正文从这开始-- 在一些容易被忽视但又非常重要的场景,可能会有许多严重影响性能 ...
- react 组件遍历】_从 Context 源码实现谈 React 性能优化
(给前端大全加星标,提升前端技能) 转自:魔术师卡颂 学完这篇文章,你会收获: 了解Context的实现原理 源码层面掌握React组件的render时机,从而写出高性能的React组件 源码层面了解 ...
- React性能优化总结
文章同步于Github Pines-Cheng/blog 初学者对React可能满怀期待,觉得React可能完爆其它一切框架,甚至不切实际地认为React可能连原生的渲染都能完爆--对框架的狂热确实会 ...
- react性能优化之memo的作用和memo的坑
前言 在react中,组件渲染的是最常有的事情.但是,有部分的渲染是不必要的,是可以避免的. 在react的一般规则中,只有父组件的某一个状态改变,父组件下面所有的子组件不论是否使用了该状态,都会进行 ...
- React 性能优化完全指南,将自己这几年的心血总结成这篇!
作者: MoonBall 原文地址: https://juejin.cn/post/6935584878071119885 本文分为三部分,首先介绍 React 的工作流,让读者对 React 组件更 ...
最新文章
- 依赖包 全局_composer 更新指定的依赖包
- 阿里mysql连接数据库服务器配置_配置链接mysql数据库
- 简单搞定linux逻辑卷
- 【问链财经-区块链基础知识系列】 第十八课 区块链应用于贷款结算
- Tomcat虚拟目录
- AVL树双旋转+图解
- 211计算机建设,“211工程”重点学科信息资源建设综述
- [转载] python字符串分割
- 陆振波的svm的matlab代码的解释,陆振波SVM的MATLAB代码解释
- 驱动级鼠标模拟实现_双飞燕血手幽灵V8M Max电竞鼠标兼具功能和性价比
- ARMv6 ARMv7 架构 整体介绍
- python爬虫的知识
- ORACLE安全加固篇
- 如何快速搭建在家里(外网)也能访问的云办公云桌面系统
- 物联网设备安全保护,需要这三道防线
- 1070: 小汽车的位置 Python
- 南方s730手簿说明书_s730手薄
- 「作于2018初」我的撸码人生
- ASIO 和 Websocket++ 独立编译
- Github上有趣的100个python项目
热门文章
- php mysql c语言教学网站
- 2023 MacBook Pro 与2021 Macbook Pro有哪些差别
- 简直绝了:周星驰与赵本山的对话
- python线性插值函数_Numpy一维线性插值函数的用法
- Matlab:disp函数、imshow函数的使用方法
- 使用全屏沉浸模式(Using Immersive Full-Screen Mode)
- BraTS数据集处理详解(附代码详解)
- 国家级大数据网络加速实验室落户迅雷
- 锐炬显卡可以linux吗,大势所趋!Intel锐炬显卡让你抛弃独显
- [量化-030]金融哲学-道德经解读-001-道德经的版本问题