文章开始之前希望大家支持一下我独立开发的微信小程序“头脑旋风”,或微信扫描我的头像进入,谢谢支持~
文章目录
1.React Native 中如何优化应用的性能?
- 优化渲染和更新逻辑
- 避免不必要的渲染:
- 使用
React.memo
或PureComponent
来避免组件不必要的重新渲染。 - 合理使用
shouldComponentUpdate
或React.useCallback
优化函数组件的性能。
- 使用
- FlatList 优化:
- 使用
keyExtractor
提供唯一键值。 - 通过设置
initialNumToRender
、maxToRenderPerBatch
和windowSize
控制渲染的批次和范围。 - 使用
getItemLayout
提供固定高度以提高滚动性能。
- 使用
- 减少匿名函数和内联对象:
- 避免在
render
方法中直接定义函数和对象,将它们提取为组件外的常量或使用useMemo
、useCallback
缓存。
- 避免在
- 避免不必要的渲染:
- 优化 JavaScript 性能
- 避免复杂计算:
- 将繁重的计算逻辑放到后台线程,使用库如
react-native-worker
或Web Worker
。
- 将繁重的计算逻辑放到后台线程,使用库如
- 减少
re-renders
:- 利用
Context
或Redux
管理全局状态,但避免不必要的深度嵌套,结合useSelector
或useContext
的浅比较。
- 利用
- 避免复杂计算:
- 图片优化
- 图片格式:
- 使用压缩后的图片(如
JPEG
、WebP
),避免加载超高分辨率图片。
- 使用压缩后的图片(如
- 缓存:
- 使用库如
react-native-fast-image
实现图片缓存和加载优化。
- 使用库如
- 按需加载:
- 通过惰性加载只加载当前屏幕需要的图片。
- 图片格式:
- 网络请求优化
- 压缩和缓存:
- 启用
GZIP
压缩和HTTP
缓存。 - 使用本地数据库(如
Realm
或SQLite
)缓存频繁请求的数据。
- 启用
- 压缩和缓存:
- 减少启动时间
- 代码拆分:
- 使用按需加载的方式分拆代码,减少主包体积(如
react-native-screens
的懒加载功能)。
- 使用按需加载的方式分拆代码,减少主包体积(如
- 启用
Hermes
引擎:Hermes
是Facebook
为React Native
应用设计的JavaScript
引擎,可减少应用启动时间并优化内存使用。
- 禁用
Dev Tools
:- 确保在生产环境中关闭
debug
、yellow box
和其他开发工具。
- 确保在生产环境中关闭
- 代码拆分:
- 动画优化
- 使用原生驱动动画:
- 使用
Animated
中的useNativeDriver: true
,将动画计算移至原生线程。
- 使用
- 选择性能友好的动画库:
- 如
react-native-reanimated
或lottie-react-native
,能更高效地处理复杂动画。
- 如
- 使用原生驱动动画:
- 内存管理
- 避免内存泄漏:
- 在组件卸载时清理定时器、订阅和事件监听器。
- 在异步操作中添加
isMounted
检查。
- 管理大列表:
- 对长列表使用
FlatList
或SectionList
,避免使用ScrollView
加载所有数据。
- 对长列表使用
- 避免内存泄漏:
- 监控和调试
- 使用性能分析工具:
React DevTools
:分析组件渲染问题。Flipper
:用于检查网络请求、日志和性能。Android Studio
和Xcode Profiler
:分析原生性能瓶颈。
- 使用性能分析工具:
2.如何减少重新渲染?
在 React
或 React Native
中,减少组件的重新渲染是优化性能的关键。以下是一些减少不必要重新渲染的方法:
- 使用
React.memo
React.memo
可以防止函数组件在相同的props
下重新渲染。
如果const MyComponent = React.memo(({ prop1 }) => { console.log("Rendering"); return <Text>{prop1}</Text>; });
prop1
未改变,组件不会重新渲染。 - 避免匿名函数和内联对象
- 匿名函数或内联对象在每次渲染时都会生成新的引用,可能触发子组件的重新渲染。
- 问题示例
const Parent = () => { return <Child onClick={() => console.log("Clicked")} />; };
- 解决方案
const handleClick = useCallback(() => { console.log("Clicked"); }, []); const Parent = () => { return <Child onClick={handleClick} />; };
useCallback
确保函数引用在依赖不变时保持稳定。 - 使用
useMemo
缓存计算值
复杂的计算结果可以通过useMemo
缓存,避免每次渲染都重新计算。const Parent = ({ items }) => { const processedItems = useMemo(() => { return items.map(item => item * 2); }, [items]); return <Child items={processedItems} />; };
- 合理使用
shouldComponentUpdate
或React.PureComponent
对于类组件,可以通过shouldComponentUpdate
或React.PureComponent
控制是否需要重新渲染。class MyComponent extends React.PureComponent { render() { console.log("Rendering"); return <Text>{this.props.value}</Text>; } }
- 使用
key
提高列表性能
在列表渲染中,确保key
唯一且稳定,避免React
重新创建DOM
节点。<FlatList data={data} renderItem={({ item }) => <Item key={item.id} {...item} />} keyExtractor={(item) => item.id.toString()} />
- 避免不必要的
useEffect
执行
useEffect
中的逻辑如果没有依赖变化,可以跳过执行。- 问题示例
useEffect(() => { console.log("Effect executed"); });
- 解决方案
useEffect(() => { console.log("Effect executed"); }, []); // 添加依赖项数组
- 分离状态
将状态切分到更小的组件或Context
,避免一个状态变化影响整个组件树。- 问题示例
const Parent = () => { const [count, setCount] = useState(0); return ( <> <ChildA count={count} /> <ChildB /> </> ); };
- 解决方案
使用状态上下文分离:
const CountContext = React.createContext(); const Parent = () => { const [count, setCount] = useState(0); return ( <CountContext.Provider value={count}> <ChildA /> <ChildB /> </CountContext.Provider> ); };
- 使用状态管理工具
如果组件需要共享全局状态,可使用Redux
或Zustand
等状态管理工具,避免通过props
层层传递。 - 避免过大的组件树
将组件拆分为更小的功能性组件,减小单个组件的渲染范围。 - 检测和优化性能
使用工具分析性能瓶颈:React DevTools
:检查组件渲染的频率。Profiler API
:分析组件渲染时间。
import { Profiler } from "react"; const Parent = () => ( <Profiler id="Parent" onRender={(id, phase, actualTime) => { console.log({ id, phase, actualTime }); }}> <Child /> </Profiler> );
3.如何使用 memo 和 useCallback?
在 React
中,React.memo
和 useCallback
是优化组件性能的常用工具。它们可以帮助减少不必要的重新渲染,从而提高应用的效率。
React.memo
的用法
React.memo
是一个高阶组件,用于优化函数组件。它会对组件的props
进行浅比较,如果props
没有变化,就跳过重新渲染。- 基本用法
import React from "react"; const MyComponent = React.memo(({ value }) => { console.log("Rendered!"); return <div>{value}</div>; }); const Parent = () => { const [count, setCount] = React.useState(0); return ( <> <MyComponent value="Hello" /> <button onClick={() => setCount(count + 1)}>Increment</button> </> ); };
- 输出
即使Parent
组件重新渲染,MyComponent
也不会重新渲染,因为它的props
没有变化。 - 与自定义比较函数结合
React.memo
默认使用浅比较,但你可以通过传递自定义比较函数来处理复杂props
。
const MyComponent = React.memo( ({ value }) => { console.log("Rendered!"); return <div>{value.text}</div>; }, (prevProps, nextProps) => { // 自定义比较:如果 `value.text` 没变,不重新渲染 return prevProps.value.text === nextProps.value.text; } );
useCallback
的用法
useCallback
是一个React Hook
,用于缓存函数的引用。它会在依赖未改变时返回相同的函数实例。- 为什么需要
useCallback
在React
中,每次渲染都会重新创建函数实例。通过useCallback
可以避免不必要的函数重新创建,从而减少传递给子组件的props
变化。 - 基本用法
import React, { useState, useCallback } from "react"; const Child = React.memo(({ onClick }) => { console.log("Child Rendered!"); return <button onClick={onClick}>Click Me</button>; }); const Parent = () => { const [count, setCount] = useState(0); // 如果不使用 useCallback,每次渲染都会生成新的函数实例 const handleClick = useCallback(() => { console.log("Button clicked"); }, []); // 依赖为空,函数实例只会创建一次 return ( <> <p>Count: {count}</p> <Child onClick={handleClick} /> <button onClick={() => setCount(count + 1)}>Increment</button> </> ); };
- 输出
每次Parent
重新渲染时,由于useCallback
,Child
组件不会重新渲染,因为onClick
函数引用没有变化。
- 为什么需要
- 与
useCallback
和React.memo
配合
useCallback
常与React.memo
一起使用,确保传递给子组件的回调函数引用不变。const Child = React.memo(({ onClick }) => { console.log("Child Rendered!"); return <button onClick={onClick}>Click Me</button>; }); const Parent = () => { const [count, setCount] = useState(0); const handleClick = useCallback(() => { console.log("Button clicked"); }, []); return ( <> <Child onClick={handleClick} /> <button onClick={() => setCount(count + 1)}>Increment</button> </> ); };
useCallback
的依赖管理
确保正确传递依赖项,否则可能导致回调函数的行为异常:const Parent = () => { const [count, setCount] = useState(0); // 如果依赖项未设置,当 count 变化时,函数不会更新 const handleClick = useCallback(() => { console.log(count); }, [count]); // 添加 count 作为依赖 return <button onClick={handleClick}>Log Count</button>; };
- 注意事项
- 性能权衡:
- 不要过度使用
React.memo
和useCallback
,它们也有开销,适用于有明显性能问题的场景。
- 不要过度使用
- 浅比较限制:
React.memo
只进行浅比较,传递复杂对象时可能需要自定义比较函数。
- 依赖列表维护:
- 在
useCallback
和useMemo
中正确设置依赖,避免错误或不必要的更新。
- 在
- 性能权衡:
4.为什么需要优化 React Native 的启动时间?如何进行优化?
优化 React Native
应用的启动时间是提升用户体验的关键因素,尤其在移动设备上,用户对应用响应速度非常敏感。以下是优化启动时间的原因及具体方法。
- 为什么需要优化启动时间?
- 用户体验:
- 如果应用加载时间过长,用户可能会流失或感到沮丧。数据显示,超过
3 秒
的启动时间会显著增加用户放弃应用的概率。
- 如果应用加载时间过长,用户可能会流失或感到沮丧。数据显示,超过
- 竞争优势:
- 快速启动的应用更容易吸引用户,尤其在同类应用中,性能是一个显著的优势。
- 系统资源限制:
- 启动时间长会占用更多设备资源,影响低端设备或运行多任务时的性能。
- 提升品牌形象:
- 快速启动让用户感到应用更专业、可靠,从而提升品牌的整体形象。
- 用户体验:
- 如何优化
React Native
的启动时间?-
启用
Hermes
引擎
Hermes
是Facebook
为React Native
开发的JavaScript
引擎,能显著减少应用启动时间,尤其是Android
。- 操作步骤
- 在
React Native
项目中启用Hermes
npx react-native init MyApp
- 修改
android/app/build.gradle
文件:
project.ext.react = [ enableHermes: true // 启用 Hermes ]
- 重新构建应用:
cd android && ./gradlew clean && cd .. npx react-native run-android
- 在
- 优势
- 更快的
JavaScript
初始化时间。 - 更低的内存使用。
- 更快的
- 操作步骤
-
减少
JavaScript
包大小- 代码分割:
- 将
JavaScript
拆分为多个小文件,并按需加载功能。 - 使用动态
import()
方法按需加载模块。
- 将
- 移除未使用的代码:
- 使用工具如
babel-plugin-import
按需引入模块。
- 使用工具如
- 压缩和混淆代码:
- 使用
Metro Bundler
自带的压缩功能减少JavaScript
包大小。 - 启用生产模式:
npx react-native run-android --variant=release
- 使用
- 代码分割:
-
延迟加载资源
- 对不需要立即显示的组件和功能进行懒加载。
const LazyComponent = React.lazy(() => import('./LazyComponent')); const App = () => ( <React.Suspense fallback={<Text>Loading...</Text>}> <LazyComponent /> </React.Suspense> );
- 使用低分辨率占位符,加载后再替换为高分辨率图片。
-
优化原生模块加载
- 移除未使用的原生模块:
- 确保只链接实际需要的原生模块,减少原生代码加载时间。
- 使用
react-native-clean-project
清理项目中的多余依赖。
- 合并原生模块初始化:
- 如果多个模块需要初始化,尽量将初始化过程合并到一个方法中。5. 减少主线程阻塞
- 移除未使用的原生模块:
-
减少主线程阻塞
- 优化渲染性能:
- 避免在启动时进行复杂计算,将其推迟到后台线程处理。
- 使用
InteractionManager.runAfterInteractions
延迟非关键任务:
InteractionManager.runAfterInteractions(() => { // 非关键任务 });
- 优化启动动画:
- 在应用启动时提供即时的启动屏幕或动画,减少用户感知的等待时间。
- 优化渲染性能:
-
使用原生启动屏幕
React Native
应用在启动时,可能需要加载JavaScript
和原生模块。通过添加启动屏幕,可以在后台加载资源时向用户展示品牌形象。操作步骤
- 使用库如
react-native-splash-screen
。 - 在启动时加载资源,完成后隐藏启动屏幕。
- 使用库如
-
减少依赖项
移除不必要的依赖,尤其是会增加启动时间的庞大库。例如:- 替换
moment.js
(大体积)为dayjs
。 - 避免直接使用未优化的第三方库,如未按需加载的组件库。
- 替换
-
监控启动性能
使用性能监控工具检测启动时间的瓶颈: -
React Native Performance Monitor
:在开发环境中启用性能监控。 -
Flipper
:检查网络请求、内存占用、组件加载时间。 -
Android Studio Profiler / Xcode Instruments
:分析原生层面的性能问题。
-
5.什么是 React Native
的 bridge
,它会影响性能吗?
-
什么是
React Native
的Bridge
?
在React Native
中,Bridge
是一个关键概念,用于连接JavaScript
代码(运行在JavaScript
引擎中,如Hermes
或JSC
)和原生代码(运行在Android
和iOS
平台上)。- React Native 的核心架构如下:
JavaScript 线程
:运行 React 和应用逻辑(UI 渲染逻辑、状态管理等)。Bridge
:一个通信层,用于在 JavaScript 线程和原生线程之间传递数据。原生线程
:负责原生视图的渲染、动画、手势处理等。
- React Native 的核心架构如下:
-
Bridge
的作用:- 它通过异步消息传递,让
JavaScript
代码调用原生模块(如摄像头、地理定位)。 - 同样,原生模块也可以通过
Bridge
把数据传回JavaScript
。
- 它通过异步消息传递,让
-
通信过程:
JavaScript
调用原生模块(通过Bridge
)。- 数据打包为
JSON
格式。 - 通过异步消息队列传递到原生线程。
- 原生模块处理请求,并将结果通过
Bridge
发送回JavaScript
。
-
Bridge
对性能的影响
由于React Native
的Bridge
是异步的消息通道,其性能可能受到以下因素的影响:-
- 通信延迟
- 每次跨越
JavaScript
和原生层的通信,都会有一定的延迟。 - 如果通信频率高(例如频繁更新
UI
、滚动动画),Bridge
的性能瓶颈会导致卡顿。
-
- 数据序列化开销
- 传递数据时需要将
JavaScript
对象序列化为JSON
格式,原生端需要将其反序列化。 - 如果传递的数据量很大(如大图片、复杂数据结构),序列化和反序列化的开销会明显增加。
-
- 高频调用问题
- 高频事件(如动画帧、手势处理)如果依赖
Bridge
,可能因为消息队列拥堵而导致掉帧。 - 示例:如果滚动事件需要通过
JavaScript
处理,Bridge
可能成为性能瓶颈。
-
- 多线程并发问题
React Native
中,JavaScript
和原生线程独立运行。虽然这是为了避免阻塞,但如果线程之间的消息同步不及时,可能出现性能问题。
-
-
如何优化 Bridge 性能?
-
- 减少通信频率
- 将高频事件的逻辑尽量放在原生代码中处理,减少依赖
JavaScript
。 - 优化滚动事件:使用原生实现滚动逻辑(如
FlatList
或SectionList
)。
-
- 减少传输数据量
- 传递必要的数据,避免大数据对象直接通过
Bridge
。 - 对数据进行压缩或拆分处理。
-
- 使用批量处理
- 如果需要传递多个事件或数据,可以合并成一个消息,通过一次
Bridge
调用完成。 - 示例:将多次状态更新合并为一个批量更新。
-
- 优化动画
- 使用
React Native
的原生动画驱动(如Animated
和LayoutAnimation
),而不是依赖JavaScript
驱动的动画。
-
- 使用
JSI
(JavaScript Interface
)
React Native
的新架构(Fabric
和Turbo Modules
)通过JSI
替代了传统的Bridge
。JSI
提供了更高效的同步通信机制,避免了数据序列化和异步队列的开销。
特点:
- 支持直接调用原生代码,无需
JSON
序列化。 - 提升通信效率,尤其适合高频任务。
- 要启用
JSI
,需要确保你的React Native
版本支持Fabric
和Turbo Modules
。
- 使用
-
- 性能监控
- 使用工具(如
Flipper
)监控Bridge
的消息队列,分析通信延迟和数据传输量。 - 找到频繁调用或大数据传输的关键点并优化。
-
-
总结
- Bridge 的优缺点:
优点
:异步机制让JavaScript
和原生线程解耦,降低线程阻塞风险。缺点
:通信延迟、数据序列化等开销可能影响性能,尤其是在高频通信场景下。
- 优化方向:
- 避免高频事件依赖
Bridge
。 - 使用批量传输减少通信次数。
- 尽早迁移到支持
JSI
的新架构,进一步提升通信效率。
- 避免高频事件依赖
- Bridge 的优缺点:
6.如何减少 JavaScript 和原生模块之间的通信开销?
减少 JavaScript
和原生模块之间的通信开销是优化 React Native
应用性能的关键。以下是一些有效的策略和实践方法:
-
- 减少通信频率
- 合并调用
问题
:频繁的单次通信会增加Bridge
的开销。解决方案
:将多次调用合并为一次批量调用。例如,合并状态更新或事件发送。
// 示例:批量发送数据 const sendData = (dataList) => { NativeModules.MyNativeModule.sendBatchData(dataList); };
- 本地化高频任务
问题
:高频任务(如滚动、动画)如果通过Bridge
处理,可能导致卡顿。解决方案
:将高频任务逻辑尽量放在原生代码中。
例如,使用原生实现动画和手势处理:- React Native 提供了
Animated
和LayoutAnimation
等可以利用原生线程处理动画的工具。 - 使用原生组件(如
FlatList
)处理滚动,而不是自定义滚动逻辑。
-
- 减少数据传输量
-
传递必要的数据
问题
:传递大数据对象或冗余数据会增加序列化和反序列化的时间。解决方案
:只传递关键数据,避免整个对象通过 Bridge。
// 示例:仅传递必要字段 const sendUserData = (user) => { NativeModules.MyNativeModule.sendUserData({ id: user.id, name: user.name, }); };
-
数据压缩
问题
:数据量过大可能导致性能瓶颈。解决方案
:在JavaScript
层对数据进行压缩,再通过Bridge
传递。
例如,将 JSON 数据压缩成字符串:
import { gzip } from 'pako'; const compressedData = gzip(JSON.stringify(data)); NativeModules.MyNativeModule.sendData(compressedData);
-
- 减少序列化和反序列化开销
- 使用轻量级数据结构
- 避免使用嵌套过深的对象或数组,尽量使用扁平化的结构。
- 示例:用简单的数组替代复杂的对象树。
- 迁移到
JSI
(JavaScript Interface
)问题
:传统 Bridge 依赖 JSON 序列化和反序列化。解决方案
:在支持新架构(Fabric 和 Turbo Modules)的 React Native 中使用 JSI。
- 特点:
- 直接调用原生代码,无需 JSON 序列化。
- 提高数据传输效率,减少性能损耗。
-
- 优化高频事件处理
- 减少事件监听器的绑定
问题
:过多的事件监听器可能增加通信负担。解决方案
:优化事件监听逻辑,绑定必要的事件。
// 示例:限制监听范围 useEffect(() => { const subscription = DeviceEventEmitter.addListener('eventName', handleEvent); return () => subscription.remove(); }, []); ```
- 延迟非关键任务
- 将非关键任务延迟到后台线程处理,避免占用主线程时间。
import { InteractionManager } from 'react-native'; InteractionManager.runAfterInteractions(() => { // 执行非关键任务 });
-
- 使用原生模块的能力
- 原生端缓存
问题
:重复传输同样的数据会浪费带宽。解决方案
:将需要频繁访问的数据缓存到原生端,避免重复通信。
- 事件触发机制
- 使用原生端的事件触发机制(如
DeviceEventEmitter
),通过事件监听代替主动通信。
//原生模块发送事件 DeviceEventEmitter.emit('customEvent', { key: 'value' }); // JavaScript 中监听 DeviceEventEmitter.addListener('customEvent', (data) => { console.log(data); });
- 使用原生端的事件触发机制(如
-
- 性能监控和调优
- 监控
Bridge
开销- 使用工具如
Flipper
和React Native Debugger
监控Bridge
的通信频率和数据量。
- 使用工具如
- 识别瓶颈
- 找出频繁调用的模块,分析哪些调用是可以合并或优化的。
7.如何实现代码分割和动态加载?
在 React Native
中,代码分割和动态加载是优化性能、减少初始加载时间的关键技术。以下是实现代码分割和动态加载的详细指南:
-
- 什么是代码分割和动态加载?
代码分割
将应用程序的代码分为多个小的独立块(chunks),以便按需加载所需的部分,而不是在启动时加载整个代码库。动态加载
动态加载允许应用在运行时按需加载某些模块或组件,而不是在初始加载时加载所有代码。
-
- 为什么要实现代码分割和动态加载?
减少初始加载时间
:只加载启动时所需的代码,提高应用启动速度。按需加载
:延迟加载不常用的模块,提高运行时性能。内存优化
:避免一次性加载大块代码,减少内存占用。
-
- 在 React Native 中实现代码分割和动态加载
-
使用
React.lazy
实现组件的动态加载
示例:懒加载组件import React, { Suspense } from 'react'; // 动态加载组件 const LazyComponent = React.lazy(() => import('./LazyComponent')); const App = () => ( <Suspense fallback={<Text>Loading...</Text>}> <LazyComponent /> </Suspense> ); export default App;
注意
:React.lazy
需要配合Suspense
使用,fallback
属性用于在组件加载时显示占位内容。- 在 React Native 中,
Suspense
的支持有限,尤其是某些场景下的服务端渲染。
-
按需加载模块
动态加载函数或模块,可以避免一次性加载所有代码。
示例:动态加载模块
const loadModule = async () => { const module = await import('./SomeModule'); module.default(); // 使用动态加载的模块 }; const App = () => ( <Button title="Load Module" onPress={loadModule} /> ); export default App;
-
使用 React Navigation 的延迟加载屏幕
如果使用 React Navigation,可以延迟加载屏幕组件,避免加载所有屏幕的代码。
示例:延迟加载屏幕
import React, { Suspense } from 'react'; import { createStackNavigator } from '@react-navigation/stack'; const Stack = createStackNavigator(); const LazyScreen = React.lazy(() => import('./LazyScreen')); const App = () => ( <Stack.Navigator> <Stack.Screen name="LazyScreen" component={() => ( <Suspense fallback={<Text>Loading Screen...</Text>}> <LazyScreen /> </Suspense> )} /> </Stack.Navigator> ); export default App;
-
使用 Metro Bundler 的分包功能
Metro 是 React Native 默认的打包工具,支持代码分包功能。
实现分包
配置分包
:创建一个自定义的 metro.config.js 文件。
const path = require('path'); module.exports = { resolver: { // 指定额外的包作为单独的依赖分包 extraNodeModules: { someDependency: path.resolve(__dirname, 'node_modules/some-dependency'), }, }, transformer: { // 启用分包功能 getTransformOptions: async () => ({ transform: { experimentalImportSupport: true, inlineRequires: false, }, }), }, };
创建分包入口
:将某些模块配置为单独的分包。
-
使用动态加载的图片和资源
在 React Native 中,大型图片资源也可以延迟加载。
示例:动态加载图片
const LazyImage = ({ uri }) => { const [loaded, setLoaded] = React.useState(false); return ( <View> {!loaded && <ActivityIndicator />} <Image source={{ uri }} onLoad={() => setLoaded(true)} style={{ width: 100, height: 100 }} /> </View> ); };
-
避免加载无关依赖
通过 Babel 插件(如babel-plugin-import
)按需加载库的模块,减少无关代码的加载。
示例:按需加载 Ant Design Mobile
npm install babel-plugin-import --save-dev
配置
.babelrc
:{ "plugins": [ ["import", { "libraryName": "antd-mobile", "libraryDirectory": "es", "style": true }] ] }
然后只加载需要的模块:
import { Button } from 'antd-mobile'; // 只加载 Button 组件
-
- 注意事项
- 适配性能监控工具
- 使用工具如
Flipper
监控代码加载情况,确保延迟加载部分按预期执行。
- 使用工具如
- 处理动态加载的错误
- 为动态加载添加错误边界,防止加载失败导致崩溃。
class ErrorBoundary extends React.Component { state = { hasError: false }; static getDerivedStateFromError(error) { return { hasError: true }; } render() { if (this.state.hasError) { return <Text>Something went wrong!</Text>; } return this.props.children; } } const App = () => ( <ErrorBoundary> <Suspense fallback={<Text>Loading...</Text>}> <LazyComponent /> </Suspense> </ErrorBoundary> );
- 测试用户体验
- 确保延迟加载的占位符(如
fallback
)能提供良好的用户体验。