浏览器主线程为何如此昂贵
The Browser's Main Thread Is Expensive
提到前端优化,大家常想到减少网络请求或压缩包体积,却很少关注主线程。在交互密集的场景下,无论网络多快,一旦主线程被阻塞,屏幕就会卡顿。文章指出,代码本身可能并不慢,问题在于它占用了主线程。浏览器的主线程负责 JavaScript 执行、渲染和事件处理,所有工作都在单线程队列中串行执行。如果任务超过 16.6 毫秒的帧预算,就会导致掉帧。解决之道在于智能分配时间:通过拆分长任务、批处理、优先级排序和延迟执行,让主线程在任务间隙处理用户输入和渲染,从而恢复流畅体验。
代码本身并不慢,问题只是它恰好是占用主线程的那段代码。
HN 评论区
80- nerdralph
我基本同意这篇文章的观点,但想澄清以下几点:
> 为了让屏幕看起来流畅,帧率必须匹配显示器的刷新率。在最常见的 60Hz 显示器上,这意味着每秒 60 帧,即每帧约 16.6 毫秒。
其实并不一定要完全匹配显示器的刷新率。对于 144Hz 的显示器,72FPS 对绝大多数人来说已经足够流畅,甚至 48FPS 对大多数人来说也够用了。我同意更高的帧率更好,但收益是递减的。
- martinald
好文章,真希望更多人知道这些内容。
不过问题在于,这篇文章过于聚焦于交互性。实际上,90% 以上的慢网站并非因为交互性慢,而是因为它们打包了巨大的 React/Next.js 代码包,且需要执行极其繁重的 hydration(水合)工作。
太多网站的代码包超过 10MB,需要下载、解析并水合。
我甚至见过(很多)网站内部堆叠了多个 SPA(单页应用)。
如果你的网络速度慢和/或 CPU 性能差,页面在几十秒内基本无法使用,无论你在代码包水合后做多少 yield(让出)操作都解决不了这个问题。
- gwbas1c
顺便一提:这不仅仅是浏览器的问题。所有平台(Windows、Mac、iOS、Android)通常都采用单线程 UI。
- jkhdigital
这篇文章最后得出了以下结论:
> 开发中的很多工作都是权衡取舍,你必须根据具体情况做出选择,这最终取决于开发者的经验和判断。
这是一篇很棒的文章,但我认为它将调度问题框架化为“经验和判断”的问题有点落后了。将工作分配给稀缺资源的问题,是计算机科学中最古老、研究最透彻的问题之一。在试图重新发明轮子之前,先去查阅一下相关教科书会更合理。
- larodi
顶级好文,点赞!之前应用过其中一些技术,它们确实非常重要。问题是,在学习或教授 JS 时,通常没时间深入讲解这些话题,而它们的重要性其实比表面看起来大得多。
协作式多任务处理的核心就是时不时让出控制权(交还给运行器),以便它能处理绘图。此外,在 60fps 下,有很多计算可以每 N 帧执行一次,人眼察觉不到,动画依然流畅。
当涉及 WebGPU 时,情况会变得更有意思,不过 CSS 动画器确实很快。
注:我最近的一些作品(新式数字传单网站)-> bsf.hmsu.org // nouveauxhivers.dub4powder.xyz