前端应该知道的浏览器知识

浏览器整体架构:多进程多线程

现代浏览器(以Chrome为代表)采用分层、多进程的架构,主要目的是安全、稳定和性能。一个典型的浏览器可以被抽象为下图所示的三层结构:

  • 第一层:用户界面 :我们看到的地址栏、书签栏、按钮等。它运行在独立的 浏览器进程 中,响应用户的全局操作。
  • 第二层:浏览器内核 :浏览器的"大脑",负责调度和管理。网络线程 处理请求,UI后端线程 绘制基础控件,而最核心的渲染引擎 (如Blink)和JS引擎 (如V8)则运行在独立的渲染进程中。
  • 第三层:数据持久层:负责Cookie、本地存储、缓存等数据的读写。

主要进程及其职责包括:

进程 职责
浏览器进程 负责界面显示(地址栏、书签)、用户交互、子进程管理等。
GPU进程 负责独立的图形绘制(3D CSS、WebGL)。
网络进程 负责所有网络资源加载。
渲染进程(核心) 每个标签页通常对应一个独立的渲染进程,负责解析HTML/CSS、执行JavaScript、进行布局和绘制(排版、渲染)。我们说的"主线程"就在这里。
插件进程 每个插件独立进程,防止崩溃影响浏览器。

所以,浏览器整体是多进程的。而在一个渲染进程内部,又包含多个线程协同工作

🧵 渲染进程内的线程分工

一个典型的渲染进程包含以下关键线程:

  1. GUI渲染线程 :负责解析HTML/CSS、构建DOM树、CSSOM树、布局和绘制等。注意:GUI渲染线程与JS引擎线程是互斥的
  2. JavaScript引擎线程(这就是我们常说的"主线程"或"UI线程") :负责执行JavaScript代码(如V8引擎)。我们常说的"JavaScript是单线程的",指的就是这个线程。
  3. 定时器触发线程 :管理setTimeoutsetInterval的计时,计时完毕将回调加入任务队列。
  4. 异步HTTP请求线程 :处理XMLHttpRequestfetch等网络请求,完成后将回调加入任务队列。
  5. 事件触发线程:管理事件循环,当事件(如点击)触发时,将对应的回调函数加入任务队列。
  6. 合成线程:将页面分层信息发送给GPU进程。

核心:"主线程"是什么?

我们通常所说的 "主线程" ,狭义上指 "JavaScript引擎线程" ,广义上指的是承担了JavaScript执行、页面渲染(GUI)、事件处理等核心工作的这个单一线程执行模型

因为GUI渲染线程JS引擎线程是互斥的,它们不能同时执行,所以可以理解为一个"工作主线程"在不同时段切换着做这两件事。其工作流程可以总结为下图:

为什么这样设计? 主要是为了保证DOM操作结果的一致性。如果JS线程和渲染线程同时工作,JS可能在渲染中途修改DOM,导致渲染出错。互斥执行简化了并发控制,但带来了性能挑战。

🧵 微观机制:渲染进程与事件循环

作为前端开发者,我们必须深入理解渲染进程的内部,因为我们的代码就在这里执行。下图描绘了渲染进程中,从接收网络数据到最终屏幕像素的关键工作流:

结合上图,我们来理解几个最关键的概念:

  1. 渲染流水线

    这是浏览器将代码变成像素的过程。你需要理解几个关键步骤:

    • 解析与构建树 :HTML解析为DOM树 ,CSS解析为CSSOM树
    • 布局:计算每个DOM元素在视口中的精确位置和大小(又称"回流")。
    • 绘制 :将元素的文本、颜色、边框等视觉信息填充到多个图层上(又称"重绘")。
    • 合成 :这是现代浏览器保持流畅的关键。合成线程 将各个图层分块,交由GPU进程 进行光栅化(变成位图),最后像叠盘子一样合成为最终画面。这个过程完全在独立的线程进行,不阻塞主线程
  2. 事件循环:JavaScript的并发模型

    是 JavaScript 实现异步编程的核心机制,其作用是协调同步任务异步任务的执行顺序,让单线程的 JS 能够高效处理非阻塞操作(如网络请求、定时器、DOM 事件)。

    • 宏任务队列 :包含 setTimeoutsetIntervalI/O、UI渲染、MessageChannel 等回调。

    • 微任务队列 :包含 Promise.thenMutationObserverqueueMicrotask 等回调。
      运行规则 :每执行一个 宏任务后,会清空整个微任务队列,然后检查是否需要渲染,接着再取下一个宏任务。

    核心规则一个宏任务 → 所有微任务 → (可能渲染)→ 下一个宏任务

💡 对前端开发的深刻启示

  1. 性能瓶颈在主线程 :所有同步JS、DOM操作、样式计算、布局都发生在同一个主线程上。这就是为什么长时间的同步JS会"卡死"页面------它阻塞了渲染和事件处理。

  2. 理解渲染时机 :浏览器会智能地合并多次DOM操作,但直接读取某些布局属性(如 offsetTopgetComputedStyle)会强制触发同步布局,导致性能骤降。

  3. 善用异步与分层

    • requestAnimationFrame 执行动画,让它与渲染周期对齐。
    • 将耗时计算移入 Web Worker(运行在独立线程,无法访问DOM)。
    • 利用CSS transformopacity 属性进行动画,它们可以由合成线程单独处理,完全避开主线程和重绘,效率最高。
  4. React调度器的用武之地 :React正是深刻理解了上述机制,才用 MessageChannel 将渲染工作拆分为5ms左右的可中断任务单元。每个单元执行后,通过事件循环将控制权交还浏览器,从而避免长任务阻塞,实现流畅的并发更新。

相关推荐
踩着两条虫15 分钟前
可视化 vs 终端 vs 云端:VTJ.PRO、Claude Code、Codex 三强横评
前端·vue.js·人工智能·低代码·架构
kyriewen17 分钟前
Godot 全面封杀 Vibe Coding,作为每天用 AI 写代码的人,我反而觉得这是件好事
前端·ai编程·claude
前进的搬砖er29 分钟前
4.three.js的几何体、纹理、光源、材质、uv属性 讲义
前端
前端毕业班42 分钟前
uni-app 小程序支持 teleport 了
前端·javascript·vue.js
东风破_1 小时前
LLM 为什么记不住你?无状态、messages 和上下文管理
javascript·人工智能
梨子同志1 小时前
qiankun
前端
梨子同志1 小时前
Nginx
前端
梨子同志1 小时前
NestJS
前端
梨子同志2 小时前
Next.js
前端
谭光志2 小时前
工具塞满上下文窗口怎么办?深度拆解 AI Agent Tool Search 按需加载实现原理
前端·后端·ai编程