从输入URL到页面加载的过程都发生了什么
技术、总结 Oct 19, 2018
从输入URL到页面加载的过程,是各个公司面试都会提及到的问题。看似这是一个简单的问题,无非是浏览器发起请求、获取请求、dom渲染、js执行等,但是每一个过程都涉及到很多的知识内容,梳理起来会是一个很大的前端知识体系。
主干流程
1、从浏览器接收url到开启网络请求线程(这一部分可以展开浏览器的机制以及进程与线程之间的关系)
2、开启网络线程到发出一个完整的http请求(这一部分涉及到dns查询,tcp/ip请求,五层因特网协议栈等知识)
3、从服务器接收到请求到对应后台接收到请求(这一部分可能涉及到负载均衡,安全拦截以及后台内部的处理等等)
4、后台和前台的http交互(这一部分包括http头部、响应码、报文结构、cookie等知识,可以提下静态资源的cookie优化,以及编码解码,如gzip压缩等)
5、单独拎出来的缓存问题,http的缓存(这部分包括http缓存头部,etag,catch-control等)
6、浏览器接收到http数据包后的解析流程(解析html-词法分析然后解析成dom树、解析css生成css规则树、合并成render树,然后layout、painting渲染、复合图层的合成、GPU绘制、外链资源的处理、loaded和domcontentloaded等)
7、CSS的可视化格式模型(元素的渲染规则,如包含块,控制框,BFC,IFC等概念)
8、JS引擎解析过程(JS的解释阶段,预处理阶段,执行阶段生成执行上下文,VO,作用域链、回收机制等等)
9、其它(可以拓展不同的知识模块,如跨域,web安全,hybrid模式等等内容)
知识体系
从浏览器接收url到开启网络请求线程
1、多进程的浏览器
1.1 Browser进程:浏览器的主进程(负责协调、主控),只有一个。
1.2 第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建。
1.3 GPU进程:最多一个,用于3D绘制。
1.4 浏览器渲染进程(内核):默认每个Tab页面一个进程,互不影响,控制页面渲染,脚本执行,事件处理等(有时候会优化,如多个空白tab会合并成一个进程)。
2、多线程的浏览器内核
2.1 GUI线程
2.2 JS引擎线程
2.3 事件触发线程
2.4 定时器线程
2.5 网络请求线程
3、解析URL
输入URL后,会进行解析(URL的本质就是统一资源定位符)
网络请求都是单独的线程
每次网络请求时都需要开辟单独的线程进行,譬如如果URL解析到http协议,就会新建一个网络线程去处理资源下载。因此浏览器会根据解析出得协议,开辟一个网络线程,前往请求资源(这里,暂时理解为是浏览器内核开辟的,如有错误,后续修复)。
开启网络线程到发出一个完整的http请求
1、DNS查询到IP
1.1 如果浏览器有缓存,直接使用浏览器缓存,否则使用本机缓存,再没有的话就是用host。
1.2 如果本地没有,就向dns域名服务器查询(当然,中间可能还会经过路由,也有缓存等),查询到对应的IP。
2、TCP/IP请求
2.1 三次握手的步骤
2.2 四次挥手的步骤
2.3 TCP/IP的并发限制
2.4 get和post的区别
3、七层因特网协议栈
3.1 应用层:DNS解析成IP并发送http请求。
3.2 表示层:主要处理两个通信系统中交换信息的表示方式,包括数据格式交换,数据加密与解密,数据压缩与终端类型转换等。
3.3 会话层:它具体管理不同用户和进程之间的对话,如控制登陆和注销过程。
3.4 传输层:建立tcp连接(三次握手)。
3.5 网络层:IP寻址。
3.6 数据链路层:封装成帧。
3.7 物理层:物理传输(然后传输的时候通过双绞线,电磁波等各种介质)。
从服务器接收到请求到对应后台接收到请求
服务端在接收到请求时,内部会进行很多的处理。
负载均衡
用户发起的请求都指向调度服务器(反向代理服务器,譬如安装了nginx控制负载均衡),然后调度服务器根据实际的调度算法,分配不同的请求给对应集群中的服务器执行,然后调度器等待实际服务器的HTTP响应,并将它反馈给用户。
后台的处理
1、一般有的后端是有统一的验证的,如安全拦截,跨域验证
2、如果这一步不符合规则,就直接返回了相应的http报文(如拒绝请求等)
3、然后当验证通过后,才会进入实际的后台代码,此时是程序接收到请求,然后执行(譬如查询数据库,大量计算等等)
4、等程序执行完毕后,就会返回一个http响应包(一般这一步也会经过多层封装)
5、然后就是将这个包从后端发送到前端,完成交互
后台和前台的http交互
http报文结构
报文一般包括通用头部、请求/响应头部、请求/响应体
2、cookie以及优化
cookie是浏览器的一种本地存储方式,一般用来帮助客户端和服务端通信的,常用来进行身份校验,结合服务端的session使用。
3、gzip压缩
gzip是一种压缩格式,需要浏览器的支持,而且gzip压缩效率很好(高达70%左右)。
4、长连接与短连接
长连接:一个tcp/ip连接上可以连续发送多个数据包,在tcp连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接,一般需要自己做在线维持(类似于心跳包)。
短连接:通信双方有数据交互时,就建立一个tcp连接,数据发送完成后,则断开此tcp连接。
5、http2.0
http2.0的一些特性:
5.1 多路复用(即一个tcp/ip连接可以请求多个资源)
5.2 首部压缩(http头部压缩,减少体积)
5.3 二进制分帧(在应用层跟传送层之间增加了一个二进制分帧层,改进传输性能,实现低延迟和高吞吐量)
5.4 服务器端推送(服务端可以对客户端的一个请求发出多个响应,可以主动通知客户端)
5.5 请求优先级(如果流被赋予了优先级,它就会基于这个优先级来处理,由服务器决定需要多少资源来处理该请求。)
6、https
https是http的安全版本,在请求前会建立ssl连接,确保接下来的通信都是加密的。
http的缓存
http的缓存包括强制缓存与协商缓存,具体可以看之前的文章 《HTTP缓存机制详解》。
解析页面流程
1、解析HTML,构建DOM树
2、解析CSS,生成CSS规则树
3、合并DOM树和CSS规则,生成render树
4、布局render树(Layout/reflow),负责各元素尺寸、位置的计算
5、绘制render树(paint),绘制页面像素信息
6、浏览器会将各层的信息发送给GPU,GPU会将各层合成(composite),显示在屏幕上
CSS的可视化格式模型
css的可视化格式模型就是规定了浏览器在页面中如何处理文档树。
1、包含块:一个元素的box的定位和尺寸,会与某一矩形框有关,这个框就称之为包含块。
2、控制框:包含块框、行内框。
3、BFC规则
4、IFC规则
JS引擎解析过程
1、JS的解释阶段
1.1 读取代码,进行词法分析(Lexical analysis),然后将代码分解成词元(token)
1.2 对词元进行语法分析(parsing),然后将代码整理成语法树(syntax tree)
1.3 使用翻译器(translator),将代码转为字节码(bytecode)
1.4 使用字节码解释器(bytecode interpreter),将字节码转为机器码
2、JS的预处理阶段
2.1 分号补全
2.2 变量提升
3、JS的执行阶段
3.1 执行上下文简单解释
3.2 VO(变量对象)与AO(活动对象)
3.3 作用域链
3.4 this指针(可参考 《JavaScript的this原理简析》)
4、回收机制
4.1 标记清除:遍历所有可访问的对象,回收已不可访问的对象。
4.2 引用计数:跟踪记录每个值被引用的次数,当一个值被引用时,次数+1,减持时-1,下次垃圾回收器会回收次数为0的值的内存。
总结
上面是对整个浏览器从输入URL到页面加载的一个前端知识体系的简单概括,更详细的知识内容请参考原文大神的内容 《从输入URL到页面加载的过程?如何由一道题完善自己的前端知识体系》。