技术知识文章集合TECHNICAL ARCHIVE · 457 DOCUMENTS

显示模式

登录
ARCHIVE DOCUMENTBR

从输入 URL 开始建立前端知识体系

所属馆藏
Browser
文件格式
Markdown
原始路径
Browser/13-从输入URL开始建立前端知识体系
本文目录15 个章节
  1. 一、先建立全局地图
  2. 二、前置内容:浏览器主要进程
  3. 三、第一部分:输入网址并解析 URL
  4. 四、浏览器缓存
  5. 五、DNS:域名解析
  6. 六、第二部分:网络协议和 TCP 连接
  7. 七、第三部分:HTTP 请求和版本演进
  8. 八、HTTPS 和 TLS
  9. 九、第四部分:服务器处理请求
  10. 十、第五部分:浏览器渲染页面
  11. 十一、第六部分:连接关闭和 TCP 四次挥手
  12. 十二、如何用工具验证这条链路?
  13. 十三、把“固定数字”改成“验证口径”
  14. 总结
  15. 参考资料

从输入 URL 开始建立前端知识体系

Category(分类): Browser Status: 已更新

本文保留原文从浏览器进程、URL、缓存、DNS、TCP/IP、HTTP、HTTPS、服务器处理、渲染和连接关闭建立知识体系的写法。网络协议和浏览器实现持续演进,文中的“典型流程”应理解为模型:缓存命中、连接复用、Service Worker、HTTP/2、HTTP/3、代理和 BFCache 都可能让真实路径变短或改变。

一、先建立全局地图

从用户输入 URL 到页面可见,可以先记住这条主线:

浏览器进程接收导航
  -> 解析 URL、检查缓存和 HSTS
  -> DNS 得到地址
  -> 复用或建立连接(TCP/TLS 或 QUIC/TLS)
  -> 发送 HTTP 请求
  -> CDN/代理/Web Server/应用处理
  -> 返回响应或重定向
  -> 浏览器提交文档给渲染进程
  -> DOM/CSSOM/样式/布局/绘制/栅格化/合成
  -> 用户交互、资源加载和事件循环继续运行

这条链路涉及多个知识领域:

  • 操作系统:进程、线程、虚拟内存、套接字;
  • 浏览器:Browser、Network、Renderer、GPU/Viz 和 IPC;
  • 网络:DNS、IP、TCP、TLS、HTTP/1.1、HTTP/2、HTTP/3;
  • Web 平台:URL、缓存、Service Worker、DOM、CSSOM、事件循环;
  • 性能:关键渲染路径、LCP、INP、CLS、缓存和资源优先级。

二、前置内容:浏览器主要进程

以 Chromium 的概念模型为例,浏览器可能包含:

  • Browser 进程:窗口、标签页、历史记录、权限和进程协调;
  • Renderer 进程:页面 HTML/CSS/JavaScript、DOM、布局和绘制准备;
  • Network Service:网络协议和资源请求;
  • GPU/Viz 相关进程:图形设备、合成和显示;
  • Utility、Storage、音视频、扩展等进程:按功能动态创建。

浏览器主要进程示意

早期资料常写“每个 Tab 对应一个渲染进程”。这只是便于理解的粗略模型。现代浏览器会根据站点隔离、同源关系、页面策略、扩展和资源压力决定进程归属,一个页面也可能与多个进程协作。Firefox、Safari 和 Chromium 的划分也不完全相同。

多进程的优点是隔离崩溃和权限边界、利用多核并行工作、便于回收页面资源;代价是进程、线程、IPC、共享内存和图形表面会增加资源消耗。

三、第一部分:输入网址并解析 URL

如果地址栏输入的内容符合 URL 形式,浏览器会解析它;如果只是普通文本,浏览器可能交给默认搜索引擎。URL 常见结构如下:

URL 各组成部分示意

https://example.com:443/docs/index.html?lang=zh-CN#install
\___/   \_________/ \___/ \_____________/ \________/ \______/
协议       主机       端口       路径          查询参数      片段

用户名、密码、端口、查询参数和片段并不是每个 URL 都有。片段通常只在客户端定位文档内位置,不会发送给服务器。URL 中的国际化域名会经过规范化和编码,路径、查询参数的编码也会影响最终请求目标。

1. 解析前的浏览器行为

浏览器可能先处理:

  • 历史记录、书签和地址栏自动补全;
  • 当前页面的 beforeunload(如果页面注册了且浏览器允许),但不应依赖它保存可靠数据;
  • BFCache、预渲染和页面恢复;
  • 浏览器缓存、Service Worker 和预加载资源。

beforeunload 可能影响 BFCache,也不是移动端页面关闭的可靠通知。需要保存数据时应在状态变化时保存,页面隐藏时可做最后一次轻量上报。

2. HSTS:把 HTTP 升级为 HTTPS

HSTS 由服务端响应头声明:

Strict-Transport-Security: max-age=31536000; includeSubDomains

浏览器记住后,用户输入 http://example.com 时可以在发出明文 HTTP 请求前改成 https://example.com。HSTS 仍需 DNS 和 HTTPS 连接,且不能替代证书验证。首次访问前是否受保护,取决于预加载列表或其他已有策略。

四、浏览器缓存

缓存不是只有一个“浏览器缓存开关”,而是由 HTTP 缓存、内存/磁盘存储、Service Worker、CDN 和代理等共同影响。具体读取顺序由请求上下文和浏览器实现决定。

浏览器强缓存与协商缓存示意浏览器缓存命中示例Cache-Control 缓存示例

1. 强缓存

Cache-Control: public, max-age=3600
Expires: Wed, 22 Nov 2026 08:41:00 GMT
  • Cache-Control: max-age=3600 表示响应在一小时内通常可以直接复用;
  • no-cache 表示复用前需要重新验证,不是禁止存储;
  • no-store 表示不要存储响应;
  • private 表示响应不应被共享缓存用于其他用户;
  • immutable 可用于版本固定、内容指纹化的静态资源,但应谨慎使用;
  • Expires 是绝对时间,现代项目应优先使用 Cache-Control

请求头和响应头可以携带不同方向的缓存指令。不要把所有字段放进“请求头表”或“响应头表”后就认为它们含义相同。

2. 协商缓存

强缓存不能直接使用,或响应要求重新验证时,浏览器会携带缓存验证器:

GET /app.js HTTP/1.1
If-None-Match: "app-v42"
If-Modified-Since: Wed, 22 Nov 2023 08:41:00 GMT

资源没有变化时,服务器可以返回:

HTTP/1.1 304 Not Modified
ETag: "app-v42"

304 没有新的响应体,浏览器继续使用已有缓存。资源变化时,服务器返回新的 200 响应和新的验证器。

3. 用 Last-Modified 实现一个安全的 Node.js 示例

下面的示例只用于说明 HTTP 验证器。生产环境还应处理路径穿越、并发、文件不存在、时区格式、缓存控制和错误响应:

import http from 'node:http'
import fs from 'node:fs'
import path from 'node:path'

const filePath = path.resolve('public/index.js')

http.createServer((request, response) => {
  if (request.url !== '/index.js') {
    response.writeHead(404)
    response.end('Not Found')
    return
  }

  const stat = fs.statSync(filePath)
  const lastModified = stat.mtime.toUTCString()
  const requestTime = request.headers['if-modified-since']

  if (requestTime === lastModified) {
    response.writeHead(304, { 'Last-Modified': lastModified })
    response.end()
    return
  }

  response.writeHead(200, {
    'Content-Type': 'text/javascript; charset=utf-8',
    'Cache-Control': 'no-cache',
    'Last-Modified': lastModified
  })
  fs.createReadStream(filePath).pipe(response)
}).listen(8888)

Last-Modified 协商缓存示意Last-Modified 请求验证示意协商缓存响应示意

Last-Modified 的精度通常是秒,快速连续修改或分布式文件系统可能让它不够精确,所以常与 ETag 一起使用。

4. 用 ETag 实现验证

import crypto from 'node:crypto'

function createEtag(buffer) {
  const digest = crypto.createHash('sha256').update(buffer).digest('base64url')
  return `"${digest}"`
}

const body = fs.readFileSync(filePath)
const etag = createEtag(body)

if (request.headers['if-none-match'] === etag) {
  response.writeHead(304, { ETag: etag })
  response.end()
} else {
  response.writeHead(200, {
    'Content-Type': 'text/javascript; charset=utf-8',
    'Cache-Control': 'no-cache',
    ETag: etag
  })
  response.end(body)
}

ETag 缓存示意ETag 请求验证示意缓存命中与失效示意

ETag 不要求必须是文件 MD5,也可以是版本号、哈希或其他稳定标识。多台服务器应尽量生成一致的 ETag,否则同一资源在不同节点间可能反复验证。

5. Service Worker、内存缓存和磁盘缓存

Service Worker 运行在独立的 Worker 全局环境中,可以拦截符合范围的 fetch 事件,并用 Cache Storage 实现离线或自定义缓存策略。它需要安全上下文(HTTPS,开发环境的 localhost 通常例外):

self.addEventListener('fetch', event => {
  if (new URL(event.request.url).pathname === '/app-shell.html') {
    event.respondWith(
      caches.match(event.request).then(cached => {
        return cached || fetch(event.request)
      })
    )
  }
})

Memory Cache 读取快但生命周期短,Disk Cache 容量和持续性通常更好。它们是浏览器内部实现,不应依赖某个资源一定在哪一层。Cache Storage、HTTP Cache 和预加载缓存也有不同的匹配规则。

HTTP/2 Server Push 曾经被资料称为 Push Cache,但该机制已经被现代浏览器逐步弃用,Chrome 已移除支持。现在通常使用 preload、103 Early Hints、缓存、CDN 和合理的资源优先级替代,不要把 Push Cache 当作当前浏览器必然存在的缓存层。

五、DNS:域名解析

在连接 Web 服务器前,浏览器需要通过操作系统或配置的 DNS 解析器取得 A/AAAA 等记录。常见缓存位置包括浏览器、操作系统、路由器和递归解析器。

DNS 请求示意

1. 递归查询

通常客户端向递归 DNS 服务器发起一次查询,由递归服务器负责访问根、顶级域和权威服务器,并把最终结果返回给客户端:

DNS 递归查询示意

2. 迭代查询

迭代查询时,被询问的 DNS 服务器返回下一步的委派信息,查询方继续访问下一台服务器:

DNS 迭代查询示意

现实网络中常见的是“客户端到递归解析器”与“递归解析器向权威服务器迭代”组合。DNS 查询通常使用 UDP,但大响应、截断和安全 DNS 还可能使用 TCP、DoT 或 DoH。

3. DNS 负载均衡和预解析

同一域名返回多个地址,可以结合地域、权重、健康状态和 CDN 节点分散请求:

DNS 负载均衡和解析示意

DNS 负载均衡受到 TTL、缓存、连接复用和健康检查的影响,不能代替所有应用层故障转移。

对确定会使用的跨域资源,可以声明预解析:

<link rel="dns-prefetch" href="//cdn.example.com">
<link rel="preconnect" href="https://cdn.example.com" crossorigin>

dns-prefetch 只提示解析域名,preconnect 还可能建立连接和 TLS。二者会消耗连接和设备资源,应只对关键第三方域名使用,不要为所有域名添加。

DNS 预解析示意

六、第二部分:网络协议和 TCP 连接

1. 网络协议分层

网络协议分层示意

TCP/IP 不是只有 TCP 和 IP 两个协议,而是一组协议集合:DNS、HTTP、TLS、TCP、UDP、IP、ARP 等在不同层次协作。

TCP/IP 协议关系示意

2. TCP 三次握手

HTTP/1.1 和 HTTP/2 通常使用 TCP 连接。HTTP/3 则使用 QUIC/UDP,不经过 TCP 三次握手。

典型 TCP 握手:

  1. 客户端发送 SYN 和初始序列号 x
  2. 服务端发送 SYN + ACK,确认 x + 1,并发送自己的初始序列号 y
  3. 客户端发送 ACK,确认 y + 1

TCP 三次握手示意

三次握手让双方确认发送和接收能力,并同步序列号。两次握手不能让服务端确认客户端能收到服务端的确认,延迟到达的旧 SYN 也可能让服务端错误保留连接状态。

TCP 连接还会协商窗口、最大报文段、时间戳、拥塞控制等参数。浏览器和系统可能复用已有连接、使用 TCP Fast Open 或通过代理建立连接,不能把每次请求都当作从零开始。

3. 半连接队列与 SYN 洪泛

服务端收到 SYN 后可能处于 SYN-RECEIVED,连接信息会进入半连接队列;完成握手后才进入已建立连接队列。大量伪造源地址的 SYN 可能耗尽队列,形成 SYN Flood。常见防护包括 SYN cookies、网关清洗、连接限速和系统参数调优。

排查时可以使用系统工具观察连接状态,例如 Linux:

ss -ant state syn-recv

不要仅凭一次状态数量就断定攻击,还要结合流量来源、时间趋势和服务端日志。

七、第三部分:HTTP 请求和版本演进

1. HTTP/0.9、1.0 和 1.1

历史上 HTTP/0.9 只有简单的 GET 和 HTML 响应;HTTP/1.0 引入状态码、请求头、响应头、内容类型和缓存等能力;HTTP/1.1 增加持久连接、分块传输、Host、范围请求和更完整的缓存协商。

HTTP/1.1 的连接可以复用,但同一连接上的请求和响应存在顺序限制,浏览器可能通过多个连接缓解队头阻塞。

2. HTTP/2

HTTP/2 使用二进制帧、流、多路复用、HPACK 头部压缩和优先级等机制。一个连接可以承载多个并发流,流内仍然保持顺序。HTTP/2 Server Push 已被现代浏览器弃用,资源预加载和 CDN 策略更常见。

3. HTTP/3

HTTP/3 使用 QUIC 在 UDP 之上传输,并使用 TLS 1.3。它为不同流提供独立的传输处理,减少 TCP 层队头阻塞影响,但实际性能仍取决于网络、丢包、服务端和客户端:

HTTP/3 与 QUIC 示意

HTTP/3 不是“无论环境都最快”,也不是把可靠性完全交给 UDP;可靠传输、拥塞控制和加密由 QUIC 实现。

4. HTTP 请求报文

GET /docs/index.html?lang=zh-CN HTTP/1.1
Host: www.example.com
Accept: text/html
Accept-Encoding: gzip, br
Connection: keep-alive

HTTP 请求报文示意

请求通常包含请求行、请求头和可选请求体。HostAccept、缓存验证器、Cookie、认证和客户端提示等字段会影响服务端处理。

5. HTTP 响应报文

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
Content-Encoding: br

<!doctype html>

HTTP 响应报文示意

HTTP 是无状态协议,但 Cookie、Authorization、URL 参数和服务端会话可以在应用层保存状态。HTTP/1.1 默认通常使用持久连接,HTTP/2 和 HTTP/3 还会复用多路流。

6. 各协议如何配合

DNS、TCP/IP 和 HTTP 的关系示意

可以这样记:

  • DNS 将主机名解析为地址;
  • HTTP 定义请求和响应的应用语义;
  • TLS 提供认证、机密性和完整性保护;
  • TCP 或 QUIC 负责可靠传输、拥塞控制和连接;
  • IP 负责在网络间寻址和转发。

八、HTTPS 和 TLS

HTTPS 是 HTTP 通过 TLS 传输。现代部署应优先使用 TLS 1.2/1.3,TLS 1.3 的握手和密码套件与旧版 TLS 1.2 不同,不能把一套固定的“客户端四步、服务端三步”流程套给所有版本。

HTTPS/TLS 握手示意

典型 TLS 1.3 握手会包含:

  1. 客户端发送 ClientHello,携带支持的版本、密码套件、随机数和密钥交换参数;
  2. 服务端选择参数,返回 ServerHello、证书链和签名等信息;
  3. 客户端验证证书的域名、有效期、信任链和用途;
  4. 双方通过密钥交换导出会话密钥;
  5. 后续 HTTP 数据使用对称加密并带完整性保护。

TLS 证书主要用于认证服务端身份和签名密钥交换,不是用来直接加密所有业务数据。TLS 1.3 通常需要一次网络往返完成首次握手,会话恢复可能更快;0-RTT 请求有重放风险,服务端要限制适用操作。

九、第四部分:服务器处理请求

服务器链路可能是:

客户端 -> CDN/WAF -> 反向代理 -> Web Server -> 应用服务 -> 缓存/数据库/其他服务

服务器处理请求示意

静态资源可以由 CDN 或 Web Server 直接返回;动态请求可能交给 Node.js、Java、Go、PHP、Python 等应用服务,再访问数据库或缓存。服务端可以使用线程池、事件循环、进程模型和异步 I/O 组合处理并发,不应把 epoll 当成所有服务器的唯一实现。

反向代理常用于 TLS 终止、路由、压缩、缓存、限流和负载均衡。部署时要正确传递 Host、协议、真实客户端地址、请求 ID,并处理超时、重试和幂等性。

服务器最终返回状态码、响应头和响应体。重定向时:

  • 301308 适合永久迁移;
  • 302303 通常表示临时处理;
  • 307308 保留原请求方法和请求体;
  • 避免重定向链和循环。

十、第五部分:浏览器渲染页面

1. DOM 树

浏览器把 HTML 字节按编码解码、分词并建立节点关系,形成 DOM:

HTML 字节到 DOM 树示意

<!doctype html>
<html lang="zh-CN">
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="style.css">
    <title>Critical Path</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <img src="awesome-photo.jpg" alt="示例图片">
  </body>
</html>

2. CSSOM 和样式计算

body { font-size: 16px; }
p { font-weight: 700; }
span { color: red; }
img { max-width: 100%; height: auto; }

浏览器会解析 CSS 规则,根据层叠、继承、媒体条件和元素状态计算最终样式,形成供布局使用的样式数据:

CSSOM 解析示意CSSOM 与样式规则示意

3. 布局树、绘制和合成

现代实现可能使用布局树、绘制块、图层树和合成表面,而不一定使用旧 WebKit 资料中的 RenderObject/RenderLayer 名称。概念上可以分为:

  1. 样式重计算;
  2. Layout,计算几何位置;
  3. Paint,生成绘制记录;
  4. Raster,将绘制记录栅格化为位图;
  5. Composite,按图层、裁剪、透明度和变换合成。

布局树示意

页面滚动、3D 变换、视频、部分 iframe、滤镜和动画可能促使浏览器使用独立合成资源:

.card {
  transition: transform 200ms ease, opacity 200ms ease;
}

.card.is-moving {
  transform: translateY(-8px);
  opacity: 0.9;
}

不要把 transform: translateZ(0) 当成必须使用的 GPU 开关。will-change 也只是提示:

.card.is-preparing {
  will-change: transform, opacity;
}

大量合成层会占用纹理内存、栅格化带宽和合成时间,应通过 DevTools Performance、Layers 和 Paint flashing 验证。

创建图层的示意DevTools Layers 面板示意

4. 回流与重绘

  • 回流/Layout:元素尺寸、位置、内容或布局关系变化后重新计算几何信息;
  • 重绘/Paint:颜色、背景、阴影等视觉内容变化后重新生成绘制记录;
  • 合成/Composite:组合已经准备好的图层或表面。

“回流必然导致重绘、重绘不一定导致回流”是有用的入门模型,但实际浏览器可能使用缓存和局部更新。下面这些读取可能迫使浏览器提交之前的样式写入并计算布局:

const rect = element.getBoundingClientRect()
const width = element.offsetWidth
const style = getComputedStyle(element)

优化方式:

  • 将 DOM 和 class 修改批量执行;
  • 将布局读取与样式写入分组;
  • 缓存需要重复读取的值;
  • 使用 DocumentFragment 或一次性更新;
  • 动画优先考虑 transformopacity
  • 对大规模计算使用 Worker 或分片任务;
  • 不要把现代 CSS calc() 误认为必须禁用的“CSS 表达式”。

十一、第六部分:连接关闭和 TCP 四次挥手

HTTP/1.1 的持久连接、HTTP/2 的多路复用和 HTTP/3 的 QUIC 都可能让连接继续存在。连接何时关闭由协议、服务器、客户端、空闲超时和网络状态决定。

TCP 主动关闭时通常包括:

  1. 一方发送 FIN,表示不再发送数据;
  2. 对方返回 ACK,但仍可以继续发送自己的数据;
  3. 对方发送自己的 FIN
  4. 第一方确认并进入 TIME_WAIT 等状态。

TCP 四次挥手示意

实际 ACK 和 FIN 可能合并,因此“四次挥手”是典型交互模型,不是每次都严格四个独立报文。TIME_WAIT 用来处理延迟报文和最后确认重传,具体时长由 TCP 实现和网络参数决定。

十二、如何用工具验证这条链路?

浏览器 DevTools

  • Network:观察 DNS、连接复用、TLS、请求、响应、重定向、缓存和资源优先级;
  • Performance:观察脚本、样式、布局、绘制、栅格化、合成和长任务;
  • Application:检查 HTTP 缓存、Service Worker、Cache Storage 和存储;
  • Rendering/Layers:检查绘制闪烁和合成图层;
  • Search Console:检查搜索引擎实际抓取和渲染结果。

Performance API

const navigation = performance.getEntriesByType('navigation')[0]

if (navigation) {
  console.table({
    dns: navigation.domainLookupEnd - navigation.domainLookupStart,
    tcp: navigation.connectEnd - navigation.connectStart,
    ttfb: navigation.responseStart - navigation.startTime,
    domContentLoaded: navigation.domContentLoadedEventEnd,
    load: navigation.loadEventEnd
  })
}

不要把一次开发机结果当成所有用户体验。真实监控应按页面、发布版本、设备、网络、地域和导航类型统计 P75/P95,并结合 LCP、INP、CLS、资源时序和错误数据分析。

HTTP 全链路知识图示HTTP 知识体系总览浏览器连接并发示意

十三、把“固定数字”改成“验证口径”

原文中有一些典型但过时的固定说法,建议这样理解:

旧说法更准确的现在说法
每个 Tab 必然一个进程进程归属由浏览器根据站点隔离和资源策略决定
DNS 一定使用 UDP常用查询可能使用 UDP,也可能使用 TCP、DoT、DoH
HTTP/1.1 同域名最多 6 个请求这是旧浏览器经验;HTTP/2/3 使用多路复用,实际由协议和实现决定
HTTPS 固定 3 次 TCP + 4 次 TLS 握手TLS 版本、恢复、代理和 HTTP/3 会改变往返次数
HTTP/3 一定最快QUIC 有优势,但需结合网络、丢包、服务端和客户端验证
所有资源都按固定缓存层顺序读取Service Worker、HTTP Cache、CDN 和预加载受请求上下文与实现影响
translateZ(0) 一定开启 GPU现代浏览器会自行决定合成路径,可能增加内存成本
页面一定要等 load 才显示浏览器可以流式解析和渐进式渲染,load 不是用户体验完成时间

总结

  1. 浏览器导航是 Browser、Network、Renderer、GPU/Viz 等多个进程和线程协作的结果;
  2. URL 的片段通常不发送到服务器,缓存和 HSTS 可能让网络步骤提前结束或被跳过;
  3. DNS 负责解析地址,但递归、迭代、缓存和安全 DNS 的部署方式很多;
  4. TCP、TLS、HTTP/2、HTTP/3 分别解决不同层的问题,不能把旧 HTTP/1.1 经验套到所有连接;
  5. 服务器可能经过 CDN、WAF、反向代理、Web Server、应用和数据库;
  6. 浏览器流式解析 HTML,经过 DOM、CSSOM、样式、布局、绘制、栅格化和合成;
  7. TCP 四次挥手是典型关闭流程,HTTP 持久连接和 QUIC 会改变连接生命周期;
  8. 学习浏览器原理的关键不是背诵固定数字,而是掌握每个阶段的职责、依赖和验证工具。

参考资料

457 DOCUMENTS · 10 COLLECTIONS
ARCHIVE SEARCH457 篇文章

SEARCH GUIDE

输入关键词开始搜索

支持搜索文章标题、所属分类和原始文档路径。

按分类浏览

10 COLLECTIONS