前言
页面初次显示内容时机和 DOMContentLoaded 之间是否存在关系。本文是概念介绍外加自测,如有错误恳请指正。
DOMContentLoaded
1. DCL 触发时,只有 DOM 加载并解析完成了
当纯 HTML 被完全加载以及解析时,DOMContentLoaded 事件会被触发,而不必等待样式表,图片或者子框架完成加载。
2. 同步 JS 的下载和解析均会阻塞 DOM 解析
JavaScript 的同步模式 (这里指同步的 JS 代码) 会导致 DOM 解析暂停。(JS 下载 和 解析 都会阻塞 DOM 解析。)
如果你想在用户请求页面时,首先尽可能先解析 DOM,此时你可以使用JavaScript 异步模式(这里指异步 JS,如 ajax 的回调),并且优化样式表的加载。(所以,尽可能让 JS 异步加载。解析没办法,肯定会阻塞 DOM 解析。CSS 部分见下段。)
3. CSS 的加载会减缓 HTML 加载,进而推迟 DOM 解析
If loaded as usual, stylesheets slow down DOM parsing as they're loaded in parallel, "stealing" traffic from the main HTML document.(CSS 推迟了 DOM 解析。因为它们是并行 loaded,CSS 的加载占用了部分 traffic,导致 html 加载也变得缓慢了,所以推迟了 DOM 解析。)
4. document.readyState 和 DCL
readyState == interactive 的时机和 DCL 的触发时机基本一致
5. 测试 DCL、document.readyState、页面内容首次呈现时间
google.com
打开 Chrome,新建标签页。打开 Network 面板,网速选 slow 3G。刷新。
可以看到,DOMContentLoaded 很快触发,测试时为 253ms。页面已经显示了除背景图片的其他内容。
之后 waterfall 一直变化,地址栏左侧也一直是“叉号”,表示页面是加载状态。这时点到 console 面板,document.readyState 输出"interactive"。
51s 后,Load 被触发。地址栏左侧变成可刷新状态。document.readyState 输出"complete"。
结论: DCL 触发时,readyState 值变为"interactive",页面显示部分内容,页面是加载状态;window.load 触发时,readyState 值变为"complete",页面是完成状态
baidu.com
DCL 前,页面就有东西显示。搜索框也可以输入文字,点击链接可以跳转到其他页面。document.readyState 输出 "loading"。
DCL 后,document.readyState 输出 "interactive"。
Load 后,document.readyState 输出 "complete"。
从上述操作观察,页面首次显示内容时机在 DCL 触发前。也许应该用 FP FCP FMP 来确定页面最初渲染的时间。
CSS 被视为阻塞渲染的资源,这意味着浏览器将不会渲染任何已处理的内容,直至 CSSOM 构建完毕。—— 阻塞渲染的 CSS
First Paint —— 页面最初显示内容的时机
performance - First Contentful Paint —— Google Developer lighthouse 文档
亲测:FP 可能出现在任意位置(DCL 前,DCL 后,Load 前,甚至 Load 后)。
Window load event
The load event is fired when the whole page has loaded, including all dependent resources such as stylesheets and images. This is in contrast to DOMContentLoaded, which is fired as soon as the page DOM has been loaded, without waiting for resources to finish loading.
load 事件在页面全部加载完成时触发,包括所有依赖的样式、图片资源。