从输入URL到页面加载全过程

从输入URL到页面加载的全过程是一道经典面试题,也是一道痕宏大的面试题。它可以用简单几句话就把大概流程说完,但是每一个流程都能够展开成一本书。所以想要把这个过程理解透,需要下很大的功夫。

这里我们用先把大致流程列出来,然后按照每一个步骤中能够涉及到的知识点来慢慢展开。

「翻译」互联网是如何运作的?这篇文章中也提到了在浏览器输入URL地址后会发生什么,文章列出了浏览器会做的事情,主要内容围绕浏览器和服务器之间的通信展开,没有细化浏览器接内部机制,这里我们先把步骤列出来,再来细化知识点。

序号 内容 知识点
1 从浏览器接收url到开启网络请求线程 浏览器机制,进程与线程之间的关系
2 开启网络线程到发出一个完整的http请求 DNS查询,TCP/IP请求,协议栈
3 从服务器接收到请求到对应后台接收到请求 负载均衡,安全拦截,后台内部处理
4 后台和前台的http交互 http协议,http报文,cookie
5 http缓存
6 浏览器接收到http数据包后的解析流程 html解析,css解析,布局,绘制,复合图层的合成,
GPU绘制,外链资源的处理
7 CSS的可视化格式模型 元素的渲染规则
8 JS引擎解析过程
9

从浏览器接收URL到开启网络请求进程

多进程的浏览器

详见:「Learning」浏览器多进程与JS运行机制

  • 浏览器是多进程的,有一个主进程,每个tab页有一个独立的进程
  • 进程包括
    • Browser主进程(只有一个)
    • 第三方插件进程(仅当使用时创建)
    • GPU进程(最多一个,用于3D绘制)
    • 浏览器渲染进程(默认每个tab一个)

多线程的浏览器内核

详见:前端复习之事件系统

浏览器渲染进程是浏览器内核,页面渲染、JS执行、时间循环都在这个进程中进行。它是多线程的,包括:

  • GUI渲染进程 (负责渲染界面,与JS线程互斥)
  • JS引擎线程(负责处理JS脚本)
  • 事件触发线程(用来控制时间循环)
  • 定时触发器线程(setTimeoutsetInterval所在线程)
  • 异步http请求线程

解析URL

输入URL后,会进行解析。URL一般包括:

  • protocol 协议头,如http, ftp等
  • host 主机域名或IP地址
  • port 端口号
  • path 目录路径
  • query 查询参数
  • fragment#后的hash值,一般用来定位到某个位置

开启网络线程到发出一个完整的HTTP请求

DNS查询得到IP

详见:「翻译」互联网是如何运作的?

DNS全称是Domain Name Service,域名服务。它是一个记录互联网中各计算机名称和与之对应的IP地址的分布式数据库。每个DNS服务器都是数据库的一部分,如果没有查找到域名,就会逐级向上重定向请求,直到找到域名,再连接到服务器。

浏览器会先与服务器建立连接,再发送HTTP请求。

TCP/IP请求

三次握手

浏览器和服务器连接的方式是三次握手。

  • 第一次握手:建立连接。客户端发送连接请求报文段
  • 第二次握手:服务器接收到报文段,对报文段进行确认,并发送自己的请求信息
  • 第三次握手:客户端收到服务器的报文段,向服务器返回报文

简单理解就是:

  • 第一次:客户端给服务器发送消息“我想和你聊会天”
  • 第二次:服务端收到消息,把自己的状态改为聊天状态,并告诉服务器“我听见了,你能听见我吗?”
  • 第三次:客户端收到服务器的消息,回复服务器“我能听见你”

三次握手确保双方发送的信息对方都能收到。

image-20180909145147755

四次挥手

断开连接时,需要经历四次挥手。

  • 第一次挥手:客户端给服务端发送报文,告诉服务端要结束连接了,此时客户端进入等待结束状态,表示客户端没有数据要发给服务端了
  • 第二次挥手:服务器收到客户端的报文,给客户端回复报文,表示同意关闭请求
  • 第三次挥手:服务器向客户端发送报文,请求关闭连接
  • 第四次挥手:客户端收到服务器的报文,回复给服务器一个OK的消息,进入倒计时关闭状态,服务器收到OK消息后就关闭连接;此时客户端没有收到回复,表示服务器正常关闭了,于是客户端也关闭连接

简单来说,就是:

  • 第一次:客户端说“我要挂电话了”
  • 第二次:服务端收到消息,告诉客户端“我同意”
  • 第三次:服务端说“那我挂了哦”,就开始举着电话准备挂
  • 第四次:客户端说”好,你挂吧“,就开始等着服务端挂电话;服务端听到后就挂了电话;客户端等了一会儿发现没有声音,确定服务端挂了,自己也挂了

image-20180909145655904

网络模型和协议栈

详见:网络体系结构模型:4层?5层?还是7层?

HTTP即超文本传输协议,是应用层协议,它位于协议栈的顶层。当数据包从一个电脑传递到另一个电脑时,数据包会从发送信息的电脑协议栈的顶层开始逐级向下,直到网络接口层将数据从文本信息转化成电子信号,接收信息的电脑则从协议栈的底部开始,数据会逐级向上传递,最终到达应用层。

在协议栈中,TCP和IP依次位于应用层的下面,因此HTTP请求在传递过程中也会逐级通过TCP层和IP层,

从服务器接收到请求到对应后台接收到请求

负载均衡

详见:简单了解负载均衡

HTTP交互

前后端交互时,HTTP报文作为信息的载体。

HTTP报文结构

报文一般包括: 通用头部,请求/响应头部,请求/响应体

通用头部

组成部分:

  • Request URL:请求的web服务器地址
  • Request Method:请求方法(GET,POST,OPTIONS,PUT,HEAD,DELET,CONNECT,TRACE)
  • Status Code:请求返回的状态码
  • Remote Address:请求的远程服务器地址
请求方法
  • HTTP 1.0定义了三种请求方法:GET, POST, HEAD
  • HTTP 1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE, CONNECT
状态码

image-20180909163314773

  • 1xx:请求已接受,继续处理
  • 2xx:请求被成功接收
    • 200: 请求被成功完成,所请求的资源发送回客户端
  • 3xx:重定向,要完成请求必须进行更进一步的操作
    • 304:自从上次请求后,请求的网页未修改过,请客户端使用本地缓存
  • 4xx:客户端错误
    • 401:请求未经授权
    • 403:禁止访问
    • 404:资源未找到
  • 5xx:服务器端错误
    • 500:服务器内部错误
    • 503:服务不可用
请求/响应头部
常用请求头
  • Accept: 接受类型,表示浏览器支持的MIME类型
  • Accept-Encoding: 浏览器支持的压缩类型
  • Content-ype:实体内容的类型
  • Cache-Control:指定请求和响应遵循的缓存机制
  • If-Modified-Since:对应服务端的Last-Modified,用来查看文件是否变动
  • Expires:缓存控制,这个时间内不会请求,直接使用缓存
  • Max-age:代表资源在本地缓存多少秒
  • Cookie:有cookie并且同域访问会自动带上
  • Connection:浏览器与服务器通信时对于长连接如何处理
  • Host:请求的服务器URL
  • Origin:最初的请求从哪里发起(源)
  • Referer:该页面的来源URL
  • User-Agent:用户客户端的一些必要信息
常见响应头
  • Access-Control-Allow-Headers:服务器允许请求的Headers
  • Access-Control-Allow-Methods:服务器允许的请求方法
  • Access-Control-Allow-Origin:服务器允许的请求Origin头部
  • Content-Type:服务器返回的实体内容的类型
  • Date:数据从服务器发送的事件
  • Cache-Control:告诉浏览器或其他客户,什么环境可以安全地缓存文档
  • Last-Modified:请求资源的最后修改时间
  • Expires:应该在什么时候认为文档已经过期,从而不再缓存它
  • Max-age:客户端的本地资源应该缓存多少秒
  • Set-Cookie:设置页面cookie
  • Keep-Alive:如果客户端有keep-alive,服务端也会有相应
  • Server:服务器的一些相关信息
请求头和响应头匹配

一般来说,请求头和响应头应该匹配分析。

  • 请求头的Accept和响应头的Content-Type匹配
  • 跨域请求时,请求头的Origin和响应头的Access-Control-Allow-Origin要匹配
  • 使用缓存时,请求头的If-Modified-Since,If-None-Match分别和响应头的Last-Modified,ETag对应
请求/响应实体

HTTP请求中,除了头部,还有消息实体。消息头和实体之间会有一个分隔符。

请求头体示例:

image-20180909203522641

详见:BOM之cookie

优化cookie

在一个页面下,如果有许多依赖的静态资源,这些资源的HTTP请求都会携带cookie,而这些静态资源并不需要cookie验证,就会造成验证的资源浪费。针对这种场景,可以多域名拆分:

  • 将静态资源分组,放到不同的子域名下
  • 子域名请求时,不会带上父级域名的cookie,避免浪费资源

长连接和短连接

TCP/IP层面

  • 长连接:一个TCP/IP连接上可以连续发送多个数据包,如果连接期间没有数据包发送,需要双发发送检测包来维持连接
  • 短连接:通信双方有数据交互时,就建立一个TCP连接,数据发送完成后断开连接

HTTP层面

  • HTTP 1.0:默认使用短连接,浏览器每进行一次HTTP操作,就建立一次连接,任务结束就断开
  • HTTP 1.1开始:默认使用长连接,长连接中会有Connection: keep-alive。长连接情况下,一个网页打开完成后,客户端和服务端之间用于传输HTTP的TCP连接不会关闭。如果客户端再次访问这个服务器页面,会继续使用这一条已经建立的连接

HTTP 2.0

HTTP 2.0是HTTP的下一代规范,它为提升加载速度提供了空间。HTTP 2.0和HTTP 1.x相比,无论在资源加载速度还是CPU占用上都有了很大的提升。

HTTP版本

HTTP协议目前已有3个版本:

  • HTTP 1.0
  • HTTP 1.1
  • HTTP 2.0

版本之间的区别

HTTP 1.0 VS HTTP 1.1

HTTP 1.0和HTTP 1.1之间最主要的区别是:HTTP 1.0默认是短连接,HTTP 1.1默认是长连接

  • HTTP 1.0(每次请求资源都要建立连接,每次连接都要三次握手,四次挥手)

    image-20180909213345886

  • HTTP 1.1(建立一次连接,多次请求均由这个连接完成)

    image-20180909213438093

除此之外,还有以下改动:

  • HTTP 1.1增加Host字段

  • HTTP 1.1引入Chunked transfer-coding,实现断点续传

  • HTTP 1.1.管线化(pipelining)理论,可以同时发出多个HTTP请求(但实际操作中还是会多开TCP,而不是HTTP pipelining,下图是管线化和非管线化的区别)

    image-20180909213912272

HTTP 2.0

无论HTTP 1.0还是1.1都会出现阻塞的情况,因为无论是一次发送一个请求,还是同时发送多个请求,返回的数据都需要按照响应顺序一一接收。这个阻塞的情况叫做线头阻塞(Head of line blocking)

  1. HTTP 2.0解决了线头阻塞的问题,它实现多路复用,即一个TCP/IP连接可以请求多个资源。

image-20180909221328265

  1. HTTP采用新的二进制分帧层(应用层与传输层中间),不再以文本格式传输,定义了如何封装http消息,并在客户端和服务器之间传输。

    image-20180909221436617

    传输的每个帧都关联到一个“流”,双休的帧序列可以通过一个HTTP2的连接在服务端和客户端之间不断的交换数据。

  2. 使用HPACK对头部进行压缩

  3. 服务器推送,服务端可以退客户端的一个请求发出多个响应,主动通知客户端

  4. 请求优先级(如果流被赋予优先级,就会基于优先级来处理)

HTTPS

https就是安全版的HTTP。

区别

请求前建立SSL连接,确保接下来的通信都是加密的,无法被轻易截取分析。

HTTPS的运行机制见:用信鸽解释HTTPS

解析页面流程

浏览器渲染的大体步骤:

  1. 解析HTML,构建DOM树
  2. 解析CSS,生成CSS规则树
  3. 合并DOM树和CSS规则,生成render树
  4. 布局render树(Layout/reflow),负责各元素尺寸、位置的计算
  5. 绘制render树(paint),绘制页面像素信息
  6. 浏览器会将各层的信息发送给GPU,GPU会将各层合成(composite),显示在屏幕上

详见:HTML解析过程全解

参考:

从输入URL到页面加载的过程?由一道题完善自己的前端知识体系!

关于 HTTP2 和 HTTPS,这些你必须要知道