前言
以前在看一些开源项目的源码时,比如cornerstone(一种为医学影像服务的web框架),折服于其优秀的设计模式,灵活的工具扩展,丰富的数据结构,在当时阅读和学习这些源码时,都是出于公司业务考虑,只是看懂了个大概,而如今随着编码技能的提高和经验的积累,我发现,源码的背后其实是在阐述一种设计理念,自顶而下,设计思想抽象逐渐落地,落实到每一行代码,同时我也有了进一步的体会,软件架构在某种程度上是为了服务它的设计理念,它的技术平衡点。
闲来无事,看了一些react的源码,聊聊react的设计理念。
React理念
官网告诉我们:“我们认为,React 是用 JavaScript 构建快速响应的大型 Web 应用程序的首选方式。它在 Facebook 和 Instagram 上表现优秀。”
它的特征是“快速响应”,“大型web应用”,那么它是如何处理快速响应的呢,首先得知道快速响应的性能瓶颈在哪?有这两类场景会影响这“快速响应”:
那么react是如何解决的呢?
快速响应的第一个难题解决--将同步的更新渲染转换为可中断的异步更新
我们知道主流浏览器的刷新频率是60Hz,也就是每16.6ms浏览器刷新一次,而卡顿则是在这期间发生的,比如js脚本执行时间过长,页面卡帧,甚至掉帧,则在浏览器刷新的时候就会有卡顿的现象了。
怎么办呢?找浏览器要时间,在它每一帧渲染的时候,留一些时间给js线程,React利用这时间抓紧更新组件,从源码中看到,预留的时间是5ms。
而上面英文的意思就是Scheduler控制器每隔5ms,观察有没有其他work要占用渲染主线程,没有的话我就继续更新组件渲染,有的话我就先暂停,也就是说将复杂的长任务,分拆到每一帧的渲染中,js执行时间在5ms左右,之后执行html的布局和css渲染。
而这个机制在哪呢,就在Scheduler
的时间切片(后续会说)。
// 通过使用ReactDOM.unstable_createRoot开启Concurrent Mode
// ReactDOM.render(<App/>, rootEl);
ReactDOM.unstable_createRoot(rootEl).render(<App/>);
快速响应的第二个难题解决--前端解决不了
网络延迟前端是无法解决的,所以只能是最大限度的减少用户对网络延迟的体验感知。
而react给出的答案是什么呢,它通过用户体验团队发现:
所以,react尝试了在Concurrent 模式在内部使用不同的“优先级”,对应于人类感知研究中的交互类别。设计了Suspense功能以及配套的hook --- useDeferredValue
总结
react为实现“构建快速响应的大型web应用”目的在渲染和网络请求上做了很多努力,并在架构设计方面也是言行合一,比如fiber架构的设计,diff算法的优化等等,下篇我们再一起探讨React的新老架构,以及为此所做的努力。
靠才华整容,我是认真的。