页面加载原理
加载资源的形式
- 输入
url
(或跳转页面)加载HTML
https://example.com
- 加载
HTML
中的静态资源
<script type="text/javascript" src="./target.js"></script>
<img src="a.png"/>
2
加载(下载)资源的过程
浏览器根据
DNS
服务器得到域名的IP
地址向该
IP
的服务器发送请求(http
或https
)服务端接受请求,处理之后并返回请求
客户端得到服务端返回的内容
浏览器渲染页面的过程
根据
HTML
结构生成DOM
树结构(DOM 的数据结构是 树(Tree) 类型)根据
CSS
生成CSSOM
(W3C)将
DOM
和CSSOM
整合形成Render
树根据
Render
树开始渲染并展示结果特别地,在下载并执行
script
标签时,因为不确定是否包含修改DOM
的 JS 代码,浏览器默认将 阻塞 当前渲染。
注:对于第 5 点,可在 script
标签上使用 defer
或 async
来解除浏览器在下载 JS 代码的阻塞渲染行为,或者在 body
的结尾处(即等到 DOM 树渲染完成)引入外部 JS 文件。
defer
属性指定浏览器不阻塞渲染并继续下载 JS 代码,但等到 DOM
树建立后才执行下载完成的代码。async
属性指定浏览器不阻塞渲染并继续下载 JS 代码,并在下载完成后立即执行下载完成的 JS 代码。
head
标签中引入的原因
拓展:外部 CSS 在 (下文渲染 DOM
树指的是 DOM
树与 CSSOM
(可能为浏览器默认样式) 结合生成 Render
树)
浏览器是自上而下解析 HTML
文档的,那么在渲染 DOM
树之前,浏览器就已经建立了 CSSOM
树,那么在渲染 DOM
树(即目的是生成 Render
树)时,浏览器将直接根据 CSSOM
树并结合 DOM
树生成 render
树,此举避免DOM
树先应用浏览器默认样式,之后再应用外部样式表的样式这样的多次应用样式的情况发生。
可以对比一下,若在 body
标签的最后引入外部 CSS 文件的话,那么在渲染完 DOM
树(此时是浏览器的默认样式)之后,浏览器又要重新将 DOM
树应用样式。这样可能导致性能问题,并且用户体验太差,可能因样式变化导致的页面跳动等问题。
结论:在 head
标签中引入外部 CSS 文件,是为了保证浏览器在渲染 DOM
树时,可以一次性渲染完成,并生成 Render
树。
body
标签结尾处引入的原因
拓展:外部 JS 在 因为不会阻塞页面的渲染。在下载并执行外部 JS 文件时,此时页面的渲染已经完成。此举让页面更快的完成渲染,减少用户等待时间(渲染未完成时,是白屏)。