您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
React请求机制优化思路
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
React请求机制优化思路
jd_4ebb695b2a872
2023-08-14
IP归属:北京
5800浏览
说起数据加载的机制,有一个绕不开的话题就是前端性能,像淘宝、京东、拼多多在内的很多门户的首页其实都会做一些垂直的定制优化,比如让请求在页面最早加载,或者在前一个页面就进行预加载等等。随着react18的发布,请求机制这一块也是被不断谈起,并且在后续其实也给出了明确的方向。 假如我们页面中有三个组件C1、C2、C3依次嵌套,每个组件中有对应的请求F1、F2、F3,通常大多数人会使用useeffect和state变量来实现数据流的获取,这样就意味着必须在组件加载时才能发起请求,所有数据获取都发生在组件的生命周期中,如下图所示,我们可以将这种获取数据的方式称作瀑布流渲染,但是这种方式有一个问题是,在这种方法中,组件之间的数据获取是按顺序进行的,这实际上意味着它们彼此阻塞,如果组件的层级嵌套很深的话,就会导致页面的加载时间特别长。 ![render then fetch.png](https://res.craft.do/user/full/86160629-3ea7-3fc8-9f95-fa5b6cf1ae21/F2428563-0198-4773-89FE-0F6CF26E596E_2/F8q0h3CEYDavyNf6WfHymYmdnwTsiqxNDTpphuetycgz/render%20then%20fetch.png) 为了阻止组件间数据获取的这种顺序阻塞,另一种方法就是在组件加载前可以使用Promise.all获取所有的请求数据,这样在组件加载时就已经获取到所有的数据了。这种方式解决了组件加载顺序阻塞彼此数据流获取的问题,但是也产生了一个新的问题,在请求完成之前页面都会是空白的。 ![先请求再渲染.png](https://res.craft.do/user/full/86160629-3ea7-3fc8-9f95-fa5b6cf1ae21/88F22F2A-9A46-476A-8A0C-7B5CA271E054_2/03ExSunxHrvgKurx0G22vnkeF7xyyrtLOysxJrsDbj0z/88F22F2A-9A46-476A-8A0C-7B5CA271E054_2.png) 基于第二种先请求后渲染的方式,还可以使用Suspense将请求和渲染并行化,Suspense 可以使得组件可以“等待”某些操作结束后,再进行渲染。而这种方式如果要用到实际项目中,还需要考虑C1、C2、C3对应的请求写在哪里,如果写在组件中,那么加载还是慢的。如果拆分出来,就需要考虑文件拆分、code splitting等工程化问题。 ![边请求边渲染.png](https://res.craft.do/user/full/86160629-3ea7-3fc8-9f95-fa5b6cf1ae21/F29931BF-36A2-4964-8EAE-691F57D5FC05_2/nEPEJAsLdYUJq3XfLChajz7ruejfEi6BAD7u5pXAV6Ez/F29931BF-36A2-4964-8EAE-691F57D5FC05_2.png) 在认真的分析了以上三种方式以后,发现各有优劣,同时基于上述方案,我也提供一个请求优化的思路,首先将请求的JS单独拆分出来打一个文件request.js,在html头部引入request.js并使用async属性让脚本并行执行(如下代码所示),这样既可以保证我们的请求在最开始就能发出,也能不阻塞后续React代码打包的js文件的执行,相当请求和渲染的代码在并行执行。 ```javascript // html头部引入request.js <script async src="/js/request.js"></script> ``` 在发送完请求之后,需要将返回的数据注入到React组件中,这部分怎么注入呢?简单的代码示例如下: ```javascript // request.js 中请求部分 evt是发布订阅模式的一个实例 window.InitData = { data: null, on: (msg, fn) => evt.on(msg, e => fn(e)), emit: (msg, data) => evt.emit(msg, data), }; fetch().then(rs => { InitData.data = rs; InitData.emit("init_data", rs); return rs; }); ``` ```javascript // index.js react代码逻辑 ……. useEffect(() => { if (InitData.data !== null) { // 这里已经获取到了请求的返回值 doSomething(); } else { InitData.on("init_data", (data) => { // 利用发布订阅模式获取到数据 doSomething(); }); } }, []); ……. ``` 总体思路就是在html中最先加载单独打包出来的请求文件并加入async属性使脚本并行执行,将返回的数据挂载到window下或者利用发布订阅模式将数据注入到react组件中。这样其实类似于边请求边渲染的模式,利用提前请求来减少加载的时间。后续也是希望能用工程化的方式去解决数据的请求机制。 未来的话在开发时肯定是更倾向于边请求边渲染的这种模式,在React的官网中也有说到未来计划让 `Suspense 处理更`多的场景,包括获取数据等等,在新发布的React18中Suspense也是支持了服务端渲染,包括近期开源的remix也都在优化请求机制能够让应用更快的加载。也欢迎有兴趣的小伙伴一起来讨论和实践。
上一篇:iOS16新特性:灵动岛适配开发与到家业务场景结合的探索实践
下一篇:从0到1构建基于自身业务的前端工具库
jd_4ebb695b2a872
文章数
1
阅读量
145
作者其他文章
01
React请求机制优化思路
说起数据加载的机制,有一个绕不开的话题就是前端性能,像淘宝、京东、拼多多在内的很多门户的首页其实都会做一些垂直的定制优化,比如让请求在页面最早加载,或者在前一个页面就进行预加载等等。随着react18的发布,请求机制这一块也是被不断谈起,并且在后续其实也给出了明确的方向。假如我们页面中有三个组件C1、C2、C3依次嵌套,每个组件中有对应的请求F1、F2、F3,通常大多数人会使用useeffect和
jd_4ebb695b2a872
文章数
1
阅读量
145
作者其他文章
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号