浏览器加载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 才真正显示页面
相关推荐
爱分享的鱼鱼1 小时前
Vue生命周期钩子详解与实战应用
前端·vue.js
晴殇i1 小时前
CSS Grid 与 Flexbox:现代前端布局的双子星
前端·css
曹卫平dudu2 小时前
一起学习TailWind Css
前端·css
sosojie2 小时前
and+design的table前端本地分页处理
前端·vue.js
炫饭第一名2 小时前
前端玩转 AI 应用开发|SSE 协议与JS中的流式处理🌊
前端·人工智能·程序员
前端老宋Running2 小时前
一种名为“Webpack 配置工程师”的已故职业—— Vite 与“零配置”的快乐
前端·vite·前端工程化
用户6600676685392 小时前
从“养猫”看懂JS面向对象:原型链与Class本质拆解
前端·javascript·面试
parade岁月2 小时前
我的第一个 TDesign PR:修复 Empty 组件的 v-if 警告
前端
云鹤_2 小时前
【Amis源码阅读】低代码如何实现交互(下)
前端·低代码·架构