浏览器加载html、css、js的顺序

最近在回顾基本知识,就顺便记录下浏览器从加载 HTML → CSS → JS 到页面渲染的过程,简单说下。


为什么要了解浏览器加载流程?

前端性能优化、SEO、首屏渲染速度、闪烁问题、Hydration mismatch 这些常见问题,本质上都与浏览器加载顺序有关,特别是排查的时候会心态爆炸。

例如实际上用 nuxtjs3 写项目的时候,首页加载老是会出现 Hydration completed but contains mismatches.,diu查了好久,把页面渲染顺序都进行调式,最后发现不是页面问题,而是在 nuxt.config.ts 多配置了首页缓存的,导致每次两端渲染不同:

ts 复制代码
    nitro.prerender.routes: ['/']

    routeRules: {
        "/": { prerender: true },
    },

虽说不是加载流程问题,但是好歹还是能排查一些问题的,掌握的话查起来还是很快的。


浏览器加载网页的完整过程

下面是简化但准确的流程:

复制代码
HTML 下载 → 解析 HTML → 下载/解析 CSS → 构建渲染树 → Layout → Paint

JavaScript 则会在关键步骤中插入"阻塞点",它会影响解析顺序与渲染顺序。


一、浏览器加载 HTML(构建 DOM)

浏览器首先从服务器下载 HTML 文件,然后:

  • 上到下 解析
  • 一边读一边构建 DOM 树

在解析 HTML 的过程中,如果遇到外部资源,就会触发对应行为:

  • 浏览器会并行下载 CSS
  • 不会阻塞 HTML 解析
  • CSS 解析未完成前无法渲染页面(渲染阻塞)

遇到 <script>(无 async/defr)

  • 阻塞 HTML 解析
  • 下载 JS
  • 执行 JS
  • 继续解析 HTML

也就是 普通 script 会暂停 DOM 的构建


二、CSS 加载与解析(构建 CSSOM)

CSS 文件下载后需要被解析成 CSSOM(CSS 对象模型)。

CSS 是渲染阻塞的

CSSOM 未构建完成 → 浏览器无法进行首次渲染

但 CSS 不会阻塞 HTML 的解析,只会阻塞渲染阶段。


三、DOM + CSSOM → Render Tree(渲染树)

当 DOM 和 CSSOM 都准备好后,浏览器把它们合成 Render Tree:

  • DOM 决定页面结构
  • CSS 决定页面样式

两者合成渲染树后,才可以进行 Layout & Paint。


四、Layout(布局计算)

浏览器计算每个节点的:

  • 大小
  • 位置
  • 盒模型

五、Paint(绘制)

将渲染树绘制到屏幕像素上。

此时用户才看到页面。


六、JavaScript 对加载顺序的影响

JavaScript 的三种加载方式:

1. 普通 <script>(最慢)

复制代码
阻塞 HTML 解析 → 下载 JS → 执行 JS → 继续解析 HTML

2. <script defer>(推荐)

复制代码
并行下载 JS
HTML 完成后按顺序执行
不阻塞解析
在 DOMContentLoaded 之前执行

3. <script async>(最快,但不稳定)

复制代码
并行下载
下载完立即执行(可能打断 HTML 解析)
执行顺序无法保证

浏览器加载流程(Mermaid 完整时序图)

sequenceDiagram participant B as Browser participant H as HTML Parser participant C as CSS Parser participant J as JS Engine B->>H: 下载并解析 HTML H->>C: 遇到 <link> 开始下载 CSS(不阻塞 HTML) C->>C: 解析 CSS(阻塞渲染) H->>J: 遇到普通 <script> 下载并执行(阻塞 HTML) H->>H: DOM Tree 构建完毕 C->>C: CSSOM 构建完毕 H->>B: DOM + CSSOM → Render Tree B->>B: Layout(布局计算) B->>B: Paint(绘制) B->>User: 页面显示


最终总结(记住这 7 句话就够了)

  1. HTML 自上而下解析,构建 DOM
  2. CSS 加载不阻塞 HTML,但阻塞渲染
  3. 普通 script 会阻塞 HTML 解析
  4. async 脱离顺序执行
  5. defer 按顺序、在 HTML 完成后执行
  6. DOM + CSSOM 才能进行渲染
  7. Layout → Paint 才真正显示页面
相关推荐
QT 小鲜肉4 分钟前
【Linux命令大全】001.文件管理之mtoolstest命令(实操篇)
linux·运维·前端·笔记·microsoft
holeer6 分钟前
React UI组件封装实战——以经典项目「个人博客」与「仿手机QQ」为例
前端·javascript·react.js·ui·前端框架·软件工程
chilavert31813 分钟前
技术演进中的开发沉思-277 AJax :Calendar
前端·javascript·microsoft·ajax
debug 小菜鸟14 分钟前
搭建web 环境的那些事
前端
鹏多多16 分钟前
Flutter下拉刷新上拉加载侧拉刷新插件:easy_refresh全面使用指南
android·前端·ios
Mike_jia29 分钟前
OpenDeRisk:AI 原生风险智能系统 ——7*24H 应用系统AI数字运维助手(AI-SRE)
前端
朱穆朗38 分钟前
electron升级到33.0.x版本后,devtools字体的修改方法
前端·javascript·electron
IT_陈寒1 小时前
Java 21新特性实战:5个必学的性能优化技巧让你的应用提速40%
前端·人工智能·后端
HarrySunCn1 小时前
大夏龙雀DX-CT511N-B实战之路-第1步
前端·单片机·物联网·iot
未来之窗软件服务1 小时前
幽冥大陆(七十七)C# 调用 中文huayan-medium.onnx —东方仙盟练气期
前端·ui·c#·仙盟创梦ide·东方仙盟