Skip to content

浏览器

浏览器相关知识

浏览器渲染一帧都做了什么

浏览器渲染一帧的过程,可以理解为浏览器为了在约16.6毫秒(针对60Hz刷新率的屏幕)内更新并绘制出页面所进行的一系列有序操作,包括以下几个步骤:

1. 接收并处理输入事件

浏览器会最先处理在此帧期间接收到的用户交互事件,例如点击、触摸、滚动或键盘输入。这确保了用户的操作能够得到及时响应。

2. 执行Javascript任务

接下来会执行Javascript代码,这包括事件回调、定时器的回调等。Javascript能修改DOM和CSSOM,从而可能触发后续的渲染流程。需要注意的是,长时间执行的Javascript会阻塞渲染,导致卡顿。

3. 执行requestAnimationFrame回调

这是一个专门为动画设计的高效API。它会在浏览器进行下一轮渲染之前执行注册的回调函数。在此处进行视觉属性的变更(如DOM元素的位置、样式),可以确保动画与浏览器的刷新率同步,从而获得更平滑的效果。

4. 样式计算与布局

  • 样式计算:计算每个DOM元素最终应用的CSS样式。
  • 布局:也称为重排,根据计算出的样式,确定每个DOM元素在视口中的位置和大小。

5. 绘制

也称为重绘。在确认了元素的几何和样式信息后,浏览器会将元素的文本、颜色、图像、边框阴影等转换成像素信息。绘制通常是在多个图层上完成的。

6.合成与显示

  • 合成:页面通常会被分成多个图层。合成线程会将这些图层进行光栅化(转换成位图),并按照正确的层级顺序合并成最终图像。

  • 显示:合成后的最终图像被提交给GPU进程,由GPU绘制到屏幕上。使用CSS的 transform或 opacity属性实现的动画通常只需经过这一步骤,效率最高。

从输入url到页面展示出来的整个过程

  1. 浏览器会检查缓存,如果请求的资源在缓存中并且未过期,就会直接使用缓存中的资源。如果资源未缓存或缓存已过期,浏览器会发起新请求。
  2. 浏览器会解析URL,获取协议、主机、端口和路径。
  3. 浏览器会通过DNS查询获取主机的IP地址。
  4. 浏览器会与目标IP地址和端口建立TCP连接。
  5. TCP连接建立后,浏览器会发送HTTP请求。
  6. 服务器接收到请求并进行处理,然后返回HTTP响应。
  7. 浏览器接收到HTTP响应,并根据情况选择关闭TCP连接或保留重用。
  8. 浏览器检查响应状态码,并根据资源类型决定如何处理。如果资源是HTML文档,浏览器会解析HTML文档,构建DOM树,下载资源,构建CSSOM树,执行js脚本等操作。

详细说明

🔍 1. URL解析与缓存判断

  • 一句话总结:浏览器先解析URL的各个组成部分,然后检查请求的资源是否在本地缓存中。
  • 详细解释:浏览器首先会分析你输入的URL,识别出协议(如HTTP/HTTPS)、域名端口资源路径参数等部分。如果协议或主机名不合法,浏览器可能会将输入内容直接转给搜索引擎。接着,浏览器会检查本地缓存(包括浏览器缓存、系统缓存等),如果存在可用的缓存资源且未失效,则直接使用缓存内容呈现,不再向服务器发起请求。

🌐 2. DNS解析

  • 一句话总结:将人类可读的域名转换为机器可识别的IP地址。
  • 详细解释:如果缓存中没有找到资源,浏览器需要知道服务器在哪。它会发起一个DNS查询。这个过程首先检查浏览器自身的DNS缓存,若无则查询操作系统缓存和hosts文件,再没有则会请求本地DNS服务器。如果本地DNS服务器也没有记录,它会以迭代或递归的方式向根域名服务器顶级域服务器(如.com)以及最终的权威域名服务器发起查询,最终获得域名对应的IP地址。这个过程的结果会被缓存起来以加速后续访问。

🤝 3. 建立TCP连接

  • 一句话总结:浏览器和服务器通过“三次握手”建立一个可靠的传输通道。
  • 详细解释:获取IP地址后,浏览器会通过TCP三次握手与服务器建立连接。首先,浏览器发送一个SYN包(同步序列编号)给服务器;服务器收到后回复一个SYN-ACK包;最后,浏览器再发送一个ACK包进行确认。至此,连接建立,双方可以开始可靠的数据传输。如果使用的是HTTPS协议,在此之后还会进行一个TLS握手过程,用于协商加密密钥,确保通信安全。

📨 4. 发送HTTP请求

  • 一句话总结:浏览器通过已建立的连接,向服务器发送一个格式化的HTTP请求报文。
  • 详细解释:连接建立后,浏览器会构建一个HTTP请求报文并发送给服务器。这个报文主要包括三个部分:请求行(包含请求方法如GET/POST、URL路径、HTTP版本)、请求头(包含主机Host、用户代理User-Agent、可接受的内容类型Accept等信息)以及可选的请求体(如POST请求提交的表单数据)。

⚙️ 5. 服务器处理并返回响应

  • 一句话总结:服务器处理接收到的请求,并将请求的资源或结果封装成HTTP响应报文返回给浏览器。
  • 详细解释:服务器(如Nginx、Apache)接收到请求后,可能会将其转发给后端的应用处理程序(如PHP、Java应用)。应用处理业务逻辑(如查询数据库)后,生成响应内容。服务器再将此内容封装成HTTP响应报文返回给浏览器。响应报文包括状态行(如状态码200 OK、404 Not Found)、响应头(如内容类型Content-Type、缓存控制Cache-Control)和响应体(实际的HTML文档等数据)。

🎨 6. 浏览器解析与渲染页面

  • 一句话总结:浏览器接收到响应后,解析HTML、CSS和JavaScript,最终将页面渲染到屏幕上。
  • 详细解释:这是最复杂的一步。浏览器首先解析HTML文档,构建DOM树。同时解析CSS(包括外部CSS文件和内联样式),构建CSSOM树。接着,将DOM树和CSSOM树合并成渲染树。然后进行布局,计算每个元素在视口中的确切位置和大小。最后进行绘制,将渲染树中的节点转换成屏幕上的实际像素,并可能进行合成以提高性能。在此过程中,如果遇到JavaScript代码,浏览器会加载并执行它。需要注意的是,JavaScript的执行可能会阻塞DOM的解析和渲染,除非使用asyncdefer属性异步加载脚本。

👋 7. 关闭TCP连接

  • 一句话总结:页面加载完成后,TCP连接会在适当时候被关闭。
  • 详细解释:在页面及其所有资源加载完成后,为了释放资源,TCP连接会被关闭。对于HTTP/1.1默认的持久连接,它会在空闲一段时间后,通过TCP四次挥手的过程来优雅地关闭连接。

数据存储(本地存储API)

这类“仓库”是网页通过JavaScript代码主动存进去的,用于保存各种业务数据。它们包括:

存储方式容量生命周期特点与适用场景
Cookie很小(约4KB)可设置过期时间,或浏览器关闭即失效(会话期)数据会自动随每次HTTP请求发送到服务器。主要用于身份验证(如保持登录状态)、记录用户偏好。因为容量小且会增加请求负担,不适合存大量数据。
localStorage较大(通常5-10MB)永久存储,除非手动清除仅存储在客户端,不随请求发送。适合保存长期不变的本地设置,如网站的夜间模式选择、非敏感的用户配置等。
sessionStorage较大(通常5-10MB)会话期存储,关闭当前浏览器标签页即失效数据仅在同一标签页内有效。适合存放临时信息,比如一个多步骤表单在填写过程中暂存的数据,避免页面刷新或意外跳转后丢失。
IndexedDB非常大(近乎无限)永久存储这是一个客户端的大型非关系型数据库,可以存储大量结构化数据,并支持复杂查询和事务。适合用于离线应用、缓存大量用户数据(如邮件、文档草稿)等高级场景。

为了更清晰地理解最常见的几种方式,它们的核心区别可以归纳为下表:

特性CookielocalStoragesessionStorage
生命周期可设过期时间,或会话级永久存储,除非手动删除仅当前标签页有效,关闭即失
存储容量约4KB通常5-10MB通常5-10MB
数据是否自动发送到服务器(随HTTP请求)
数据作用域同源的所有标签页共享同源的所有标签页共享仅限当前标签页
属性名作用简介
Name(名称)Cookie 的唯一标识符,一旦创建便不可更改。
Value(值)存储在 Cookie 中的实际数据。
Domain(域)指定哪些域名可以访问此 Cookie。例如,设置为 .example.com,则所有子域名(如 a.example.com)也可访问。
Path(路径)指定域名下的哪些路径可以访问此 Cookie。只有指定路径及其子路径的请求才会携带该 Cookie。
Expires / Max-Age控制 Cookie 的有效期。Expires 设置一个具体的过期时间(GMT格式),Max-Age 设置多少秒后过期。不设置则默认为会话 Cookie,浏览器关闭后失效。
Secure一个标记属性。若设置,则 Cookie 只允许通过安全的 HTTPS 协议传输,防止在 HTTP 连接中被窃取。
HttpOnly一个标记属性。若设置,将禁止客户端 JavaScript 通过 document.cookie 访问此 Cookie,有助于防范 XSS 攻击窃取 Cookie。
SameSite控制 Cookie 在跨站请求中是否被发送,是防范 CSRF 攻击的重要机制。其值可以是:
- Strict:最严格,完全禁止在跨站请求中发送。
- Lax:宽松模式,例如从外部链接导航到该站点会发送(GET请求)。
- None:无限制,允许跨站发送(必须同时设置 Secure 属性)。
Priority这是一个非标准属性,主要由 Chrome 提案使用。当 Cookie 数量超出浏览器限制时,浏览器会优先清理低优先级(Low)的 Cookie。

资源缓存(HTTP缓存)

主要用于存储从网上下载的静态资源,比如图片、样式表(CSS)、脚本(JS)等。它通过检查服务器返回的响应头指令来工作,分为两种策略:

特性强缓存协商缓存
核心机制浏览器直接使用本地缓存,不发送请求到服务器浏览器发送请求到服务器,由服务器判断是否使用缓存
HTTP状态码200 (from memory/disk cache)304 (Not Modified)
关键HTTP头部Cache-Control (如 max-age), ExpiresLast-Modified / If-Modified-Since, ETag / If-None-Match
通信成本无网络请求有一次请求/响应的往返
优先级优先于协商缓存强缓存失效后触发

💾 理解两种缓存的工作流程

浏览器检查缓存的顺序是:强缓存优先,不命中再协商缓存

  1. 强缓存:浏览器首先检查资源是否在“强缓存”的有效期内。如果是,它根本不会向服务器发送请求,直接从本地缓存加载资源。你在开发者工具的Network面板中会看到状态码为 200 (from disk cache)200 (from memory cache)
  2. 协商缓存:如果强缓存失效(例如,max-age设置的时间过了),浏览器才会携带缓存标识(如上次收到的 ETagLast-Modified 值)向服务器发送请求。服务器通过比对这些标识来判断资源是否更改。如果没变,就返回一个轻量的 304 (Not Modified) 响应,告诉浏览器继续用缓存;如果变了,就返回 200 和新的资源。

⚙️ 关键HTTP头部详解

强缓存相关头部

  • Cache-Control (HTTP/1.1,主流):这是最常用和重要的缓存控制头,它可以通过一些指令来精确控制缓存行为。
    • max-age=3600:资源在3600秒内有效,直接从缓存读取。
    • no-cache不是不缓存,而是要求每次使用缓存前必须向服务器验证(即跳过强缓存,直接进入协商缓存流程)。
    • no-store:真正的不缓存,不允许存储任何客户端缓存和服务器缓存。
    • public / private:指定资源是否可以被代理服务器等中间缓存缓存。
  • Expires (HTTP/1.0,逐渐淘汰):指定一个资源的绝对过期时间。如果同时设置了 Cache-ControlExpiresCache-Control 的优先级更高。

协商缓存相关头部

  • Last-Modified & If-Modified-Since
    • 服务器首次返回资源时,在响应头带上 Last-Modified(资源的最后修改时间)。
    • 当浏览器再次请求该资源时,会在请求头自动带上 If-Modified-Since,其值就是上次收到的 Last-Modified。服务器会比较时间,决定返回304还是200。
  • ETag & If-None-Match(优先级更高)
    • 服务器首次返回资源时,在响应头带上 ETag,这是基于资源内容生成的一个唯一标识符(如哈希值)。
    • 浏览器再次请求时,会在请求头自动带上 If-None-Match,其值就是上次收到的 ETag。服务器比对 ETag,如果一致则返回304。
    • ETagLast-Modified 更精确,因为它能感知到内容的变化,而不仅仅是修改时间(例如,文件在1秒内被多次修改,或者文件内容变了但修改时间没变)。

🎯 实际应用策略

在实际项目中,通常会结合使用两种缓存:

  • 对于静态资源(如JS、CSS、图片):使用强缓存并设置较长的 max-age(如一年)。同时,通过构建工具(如Webpack)为文件名添加哈希戳(如 app.a1b2c3.js),这样当文件内容变化时,文件名也会改变,从而确保用户能获取到最新版本。
  • 对于HTML页面和频繁更新的API:使用协商缓存Cache-Control: no-cache)或较短的强缓存时间,以确保内容的及时更新。

🔍 在浏览器中观察缓存行为

打开浏览器的“开发者工具”(F12),切换到 Network(网络) 面板:

  • 如果看到状态码为 200 (from disk cache)200 (from memory cache),说明命中了强缓存
  • 如果看到状态码为 304 Not Modified,说明命中了协商缓存

URL中#部分

1.基本定义与作用

  • #及其后的内容称为片段标识符​(Fragment Identifier),用于定位页面内的特定位置。
  • 两种定位方式:通过<a name="id">或HTML元素的id属性。

2.HTTP请求与服务器交互

  • 不会发送到服务器:浏览器仅请求#前的部分(如GET /index.html),#后的内容由客户端处理
  • 示例:http://example.com/?color=#fff实际请求为/?color=,#fff被忽略

3.对SEO的影响

  • 默认忽略:搜索引擎(如Google)通常不抓取#后的内容,视为同一页面。
  • 例外规则​:若使用#!(如Twitter的#!/username),Google会将其转换为?escaped_fragment=参数抓取动态内容。
  • ​单页应用(SPA)风险​:纯哈希路由可能导致内容无法被索引,建议结合History API或预渲染技术优化。

4.浏览器行为与前端应用

  • ​无重载​:修改#仅触发页面滚动或前端路由切换,不重新加载页面。
  • ​历史记录​:改变#会新增浏览器历史条目(IE6/7除外),支持后退操作。
  • ​事件监听​:可通过onhashchange事件响应哈希变化。

5.最佳实践建议

  • 避免在关键参数中使用#(需传递时编码为%23)
  • 对SPA优先使用History API,或配置服务器支持_escaped_fragment_