本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
大家好,我是羊肉串。从输入url到页面展示,中间发生了什么这道经典面试题,相信作为一个前端,应该经常被问到。里面沿伸的知识点很多,从浏览器到性能优化。本文将整理这个过程.
总结步骤
- 用户输入内容或者url并回车
- 浏览器先查找本地是否存在该请求的未过期缓存
- 进行dns解析,得到对应的ip地址
- 建立tcp连接(也就是所谓的三次握手)
- 发送http请求
- 服务器接收http请求,处理数据,将响应返回浏览器
- 断开tcp连接(也就是四次挥手)
- 渲染页面
前置知识点
进程和线程
- 一个进程就是一个程序的运行实例,拥有独立的内存空间。
- 线程是依附于进程,通常在进程中使用多线程并行处理提高运算效率
- 进程中的任意一个线程出错,都会导致线程崩溃
- 一个进程中的数据可以在多个线程中间共享
- 多个进程之间相互隔离,其中一个进程挂掉,不会影响其他进程
浏览器进程
目前浏览器包括:一个浏览器主进程,一个GPU进程,一个网络进程,多个渲染进程和多个插件进程组成
- 浏览器主进程:负责界面显示,用户交互,子进程管理
- 渲染进程:负责将html js css 变成用户能够感知的网页。
- 网络进程:负责浏览器和服务器进行数据传递。获取网络数据
- GPU进程:用于图形和视频的渲染
- 插件进程:管理浏览器插件,通过插件进程,将各种插件包裹起来,某个插件崩溃,不会导致浏览器奔溃
dns域名系统
dns即是域名系统,在浏览器输入一个url地址时,浏览器要向这个url地址的主机名对应的服务器发送请求,dns的作用就是将主机名转换成ip地址
- 分布式 每台dns服务器只负责部分映射
- 有层次 dns有三种类型服务器
- 根dns服务器:管理顶级域dns服务器,通过询问根dns服务器,可以知道对应的顶级域dns服务器的ip地址是多少,从而继续向顶级域dns服务器发送问询请求
- 顶级域dns服务器:返回权威域dns服务器ip地址
- 权威域dns服务器:返回最终映射ip地址
类型服务器区分:
示例: 比如一个域名地址m.n.com 实际地址应该是m.n.com.
其中类型服务器的区分是根据.来进行区分的。
即根dns服务器是根据com查询顶级域dns服务器
顶级域dns服务器根据n查询权威域dns服务器
权威域dns服务器根据m查询最终映射的ip地址
查询步骤:
主机m.n.com 想要获取主机a.b.com的ip地址
主机m.n.com向它的本地dns服务器发送一个dns查询报文,其中包含a.b.com主机名
本地dns服务器将该报文转发给根dns服务器
根dns服务器注意到com前缀,便向本地dns服务器返回com对应的顶级域dns服务器的ip地址列表
本地dns服务器则向其中一台顶级域dns服务器发送查询报文
该顶级域dns服务器注意到b.com前缀,便向本地dns服务器返回权威dns服务器的ip地址
本地dns服务器又向其中一台权威服务器发送查询报文
该权威服务器返回了a.b.com的ip地址
本地dns服务器将a.b.com跟ip地址映射返回给主机m.m.com
TCP协议
TCP(传输控制协议)是一种面向连接的,可靠的,基于字节流的传输层通信协议
- 建立连接(三次握手)(待完善)
- 传输数据
- 断开连接(四次挥手)(待完善)
渲染过程
- 构建dom树:输入一个html文件,通过html解析器解析,最终输出一个树状结构的DOM
- 样式计算:根据css样式表,计算dom树所有的节点样式
- 布局:计算dom元素的坐标位置,并将信息保存在布局树中
- 分层:由于页面可能存在复杂的效果,比如3D转换,z-index等,浏览器会为特定的节点生成图层,生成一颗图层树
- 拥有层叠上下文的元素会被单独提升为一层,比如z-index,opacity,等
- 需要裁减的元素,也会单独提升一层
- 绘制:为每个图层生成绘制列表,将其提交给合成线程
- 分块:合成线程将图层分成图块
- 光栅化:利用光栅化线程将图块转换成位图
- 合成:将无图绘制在屏幕上
缓存相关
- 强缓存,使用cache-control和expires两个请求头控制
- expires是http1.0提出的一个资源过期时间,是一个绝对时间,由服务器返回
- cache-control http1.1提出来的
- max-age 相对时间
- no-cache 响应协商缓存
- no-store 所有内容都不取缓存
- 协商缓存
- 当资源没有命中强缓存时,就会判断是否命中协商缓存,命中返回304
- last-modified 表示资源的最后修改时间,会在请求头上加上if-modified-since给服务端,服务端判断当前日期后,数据是否有更新,没有返回304,有更新返回200和数据,并更新last-mdified
- etag/if-none-match 资源变化会引起etag变化,请求时会将上一次的etag发送给服务端,判断数据是否发生变化
- 强缓存优先于协商缓存,如果强缓存生效,直接使用强缓存,强缓存不生效,则判断是否命中协商缓存
总结答案
- 1.用户输入内容,浏览器根据内容判断输入的是内容还是网址,如果是内容,会将内容和搜索引擎拼接成新的url地址。
- 2.浏览器进程构建请求信息,将url请求发送给网络进程;
- 3.网络进程获取到url地址,先去本地缓存中查找是否有缓存文件,如果有未过期的文件,拦截请求,直接返回200,否则进入网络请求过程
- 4.请求dns返回域名对应的ip地址和端口号,本地dns服务器先去判断是否有缓存当前域名信息,如果没有发送请求获取对应的ip地址和端口号。如果没有端口号,http默认80端口,https默认443
- 5.由于同一个域名最多只能同时存在6个tcp链接,如果超过,则需要等待
- 6.建立tcp连接(三次握手)
- 7.目标服务器解析请求头和请求体,判断是否需要重定向
- 若需要,返回code码301或者302,并在请求头的location字段中附上重定向地址,浏览器根据code码和location进行重定向操作
- 若不需要,则根据是否命中强缓存/协商缓存策略。命中返回304,浏览器直接使用缓存的数据,没命中,返回200状态码和新数据,
- 8.数据传输完成,断开tcp连接(四次挥手)。如果http头部信息存在connection:keep-alive。则表示保持连接,提高资源加载速度
- 9.网络进程对返回的数据进行解析,通过响应头里的content-type判断数据类型
- 如果是字节流类型, 直接下载
- 如果是text/html 通知浏览器进程准备渲染
- 10.浏览器进程接收到通知,判断是否可以复用当前页面的渲染进程,若不能则新创建一个渲染进程
- 11.浏览器会发送消息给渲染进程,渲染进程和网络进程建立传输数据的通道,数据传输完成后,渲染进程会通知浏览器进程。浏览器进程收到数据传输完成消息,更新浏览器页面信息,包括地址栏url,history记录
- 12.渲染进程执行渲染步骤,让页面显示出来