生產環(huán)境下日志輸出禁用
接入babel-plugin-transform-remove-console
npm install babel-plugin-transform-remove-console --save-dev
配置.babelrc
// 生產環(huán)境下配置去掉console輸出
{
??...
??"plugins": [
????...
??],
??"env": {"production": {
??????"plugins": [["transform-remove-console", {"exclude": ["error"]}]]
??}
??}
}
采用setNativeProps
在RN中,如果需要頻繁刷新view,建議使用setNativeProps,避免使用setState導致的頻繁render。
類似頂部tab的透明度漸變,就適用這種情況
官方原文建議
在(不得不)頻繁刷新而又遇到了性能瓶頸的時候。 直接操作組件并不是應該經常使用的工具。一般來說只是用來創(chuàng)建連續(xù)的動畫,同時避免渲染組件結構和同步太多視圖變化所帶來的大量開銷。setNativeProps 是一個“簡單粗暴”的方法,它直接在底層(DOM、UIView等)而不是React組件中記錄state,這樣會使代碼邏輯難以理清。所以在使用這個方法之前,請盡量先嘗試用setState 和shouldComponentUpdate方法來解決問題。
使用PureComponent或shouldComponentUpdate
PureComponent
當組件更新時,如果組件的 props 和 state 都沒發(fā)生改變, render 方法就不會觸發(fā),省去 Virtual DOM 的生成和比對過程,達到提升性能的目的。
具體原理是 在shouldComponentUpdate回調中,對oldState和newState 及 oldProps和newProps進行淺比較,如不同,才return true,進而回調render。
重寫shouldComponentUpdate
代碼塊
shouldComponentUpdate() {
?????return this.state.update;
}
控制在需要的時候才去刷新,根據需求或者業(yè)務去控制。
Android硬件加速
通過啟用View的renderToHardwareTextureAndroid屬性 為true,可以開啟View的硬件加速。(決定這個視圖是否要把它自己(以及所有的子視圖)渲染到一個 GPU 上的硬件紋理中。)
在 Android 上,這對于只修改不透明度、旋轉、位移、或縮放的動畫和交互十分有用:在這些情況下,視圖不必每次都重新繪制,顯示列表也不需要重新執(zhí)行。紋理可以被重用于不同的參數。負面作用是這會大量消耗顯存,所以當交互/動畫結束后應該把此屬性設置回 false。
shouldRasterizeIOS在iOS上有個shouldRasterizeIOS屬性,可以設置該view在被渲染到屏幕之前,先繪制到一個位圖上,這個我理解和Android中的雙緩沖區(qū)比較想像。
這個屬性對于不會修改組件和子視圖尺寸的動畫和交互十分有用。舉例來說,當我們移動一個靜態(tài)視圖的位置的時候,預渲染允許渲染器重用一個緩存了靜態(tài)視圖的位圖,并快速合成。
長列表加載
使用用復用性更強的FlatList或SectionList
FlatList或SectionList優(yōu)化:
Item采用PureComponent或重寫shouldComponentUpdate
getItemLayout如果行高是固定的,可以使用getItemLayout,避免動態(tài)測量內容尺寸的開銷。
首屏進入時間優(yōu)化
減少bundle包大小
圖片壓縮;
圖片上傳到圖片服務器,再引用;
mrn團隊的拆包策略(目前有bug)
懶加載
JS在執(zhí)行import時有時很需要時間,首屏不需要展示的組件可以懶加載
代碼塊
import React, { Component } from 'react';
import { TouchableOpacity, View, Text } from 'react-native';
// 先把這個組件賦值為null
let VeryExpensive = null;
export default class Optimized extends Component {
??state = { needsExpensive: false };
??didPress = () => {
????if (VeryExpensive == null) {
????// 真正需要這個組件的時候才加載
??????VeryExpensive = require('./VeryExpensive').default;
????}
????this.setState(() => ({
??????needsExpensive: true,
????}));
??};
??render() {
????return (
??????<View style={{ marginTop: 20 }}>
????????<TouchableOpacity onPress={this.didPress}>
??????????<Text>Load</Text>
????????</TouchableOpacity>
??????// 根據需要判斷是否渲染該組件
????????{this.state.needsExpensive ? <VeryExpensive /> : null}
??????</View>
????);
??}
}