Appearance
JS 的渲染与运行
元信息
- 目标:掌握浏览器处理 JS 的方式——解析为 AST、编译为字节码、在渲染主线程上执行;从此能从原理层面解释脚本为何打断 HTML 解析、defer/async 这些"惯例"的由来
- 关键概念:渲染主线程、解析阻塞、执行阻塞、async/defer、CSS 对脚本的间接阻塞
- 关联阶段:cp3
- 常见误区:以为脚本仍应放页面底部(defer 出现后放 head 既早下载又不阻塞);以为 async/defer 对内联脚本也有效(仅对外联脚本有效);以为 CSS 会阻塞 HTML 解析(CSS 只阻塞渲染成像,但会间接阻塞其后的脚本)
在关键渲染路径的流水线里,CSS 只需被解析成 CSSOM,JS 却要在渲染主线程上运行——它能改 DOM、查样式,浏览器对它也就最严格:默认停下 HTML 解析等它。本篇讲 JS 如何被处理与执行、阻塞从何而来、defer/async 如何化解。
网络等待与加载模式
外联脚本都要走网络。解析器等待网络返回是"阻塞式";不等待、先继续解析则是"非阻塞式"——但非阻塞让就绪顺序变得不可预测,需要 async/defer 这类机制来声明依赖关系。
要点:
async与defer仅对外联脚本有效,内联脚本无此属性defer的存在让"脚本放<head>"重新成为最佳实践——既早下载,又不阻塞、不怕元素未就绪。"把脚本塞到页面底部"是defer出现之前的时代应对,不必再效仿
三种写法在下载、执行时机、顺序上的逐项对比,见异步与阻塞。
让脚本不挡路,正是优化关键渲染路径的第一条原则(减少关键资源数量)在脚本一侧的落地——三条原则见关键渲染路径。
参考
- script元素 https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/script
- Chrome V8 让你更懂 JavaScript https://king-hcj.github.io/2020/10/05/google-v8/