【高薪常问】从浏览器搜索框输入内容到页面渲染 这过程发生了什么

582 阅读7分钟

这是一道很经典的面试题,看似一句话其中暗藏很多玄机也涉及了多方面知识的知识考查。
首先我们按照进程大致梳理一下:

1、在浏览器搜索栏中输入内容会先进行URL解析 (编码...)

2、通过URL进行页面访问请求 ( 网络进程<浏览器进程...>、HTTP、HTTPS的区别、各自特点... )

3、查询本地是否有缓存有则用,没有就通过DNS解析IP,从浏览器本地缓存、本地hosts文件、DNS服务器查询IP ( 缓存相关、DNS<概念、解析规则...> )

4、拿到IP地址后发送HTTP请求 ( 此时一大波网络基础知识向你奔来,TCP、UDP、IP、HTTP2..各种死亡追问 )

5、建立TCP三次握手连接 ( 为毛三次,两次不行么 ),如果HTTPS会建立TLS安全通道连接 ( HTTPS加密方式 )

6、代理服务器或源服务器进行对请求进行响应 ( 服务器代理 )

7、浏览器拿到HTTP响应 (HTTP响应状态码) 根据Content-Type进行处理 ( 常用响应头字段 )

  • stream类:浏览器启动下载界面下载文件
  • text、图片类:浏览器直接显示在页面上
  • html类型:浏览器会进行页面解析

8、渲染进程对页面进行解析( 浏览器工作原理 ),网络进程向渲染进程传输HTML数据,对HTML进行词法分析,通过堆栈算法构建DOM树。( AST语法树 ),如果需要外部资源浏览器会交给网络进程去下载。

9、构建完DOM数据的同时浏览器会解析css代码构建css对象模型(CSSOM),然后融合DOM和CSSOM开始布局和构建渲染树,根据渲染树完成页面渲染

及格版

及格版没有过多的拓展知识介绍,毕竟每一点研究下去都是一章大篇幅,有兴趣的小伙伴可以自行了解。

整个过程可以分为四个阶段:

  • URL解析
  • DNS解析
  • 前后端基于HTTP请求交互获取数据
  • 浏览器渲染

URL解析

在浏览器搜索框内输入内容搜索后,浏览器会先对用户输入的内容进行URL解析。
如果是文本,会作为参数拼接在默认搜索引擎的URL后进行搜索。
如果是URL,浏览器先对URL进行编码,通过编码后的URL进行页面访问。

为什么要进行URL解析(编码)

因为URL只能使用英文字母、阿拉伯数字和某些标点符号、某些保留字,不能使用其他文字和符号。
以下情况都需要进行URL编码

  • URL或查询参数中包含汉字等特殊字符
  • URL或查询参数中包含#、?、&、=等让URL有歧义的字符

encodeURI、encodeURIComponent
它们都是Javascript中对URL编码的函数,它们的区别:

encodeURI
着眼于对整个URL进行编码,特殊含义的符号; / ? : @ & = + $ , #

encodeURIComponent
对URL的组成部分进行个别编码,所以; / ? : @ & = + $ , #在这里是可以进行编码

一般会对完整的URL链接采用encodeURI编码,路径中携带的参数采用encodeURIComponent编码

DNS解析

浏览器会对编码后的URL进行DNS解析来获取对应的IP地址,DNS解析主要分为本地解析DNS服务器解析两个阶段。

本地解析

这个阶段是递归的过程

  • 首先客户端先去浏览器缓存查看是否解析过该DNS,没有对应的IP地址就继续查询
  • 去查看本地操作系统hosts文件有没有解析过DNS
  • 看本地DNS解析器有没有缓存,如果本地没有DNS记录就开始向DNS服务器解析

DNS服务器解析

这个阶段是迭代的过程

  • 先找DNS根域名服务器,没有找到IP地址,根域名服务器返回顶级域名服务器地址
  • 顶级域名服务器没有找到IP地址,顶级域名服务器返回权威域名服务器地址。
  • 权威域名服务器返回自身真正的外网IP地址

前后端网络交互

通常HTTP请求基于TCP/IP,而TCP/IP是基于IP地址的。这个阶段客户端向服务器发送HTTP请求,客户端与服务端会先通过TCP三次握手建立TCP连接。在此之后,客户端发送具体的请求,等待服务端响应。浏览器根据响应的结果进行处理,当数据包传输完毕,双方通过TCP四次挥手断开连接。

为什么TCP建立连接需要进行三次握手?

这是为了建立安全可靠的连接,首先客户端进行第一次握手尝试建立连接,服务端接收到指令进行答应此时进行第二次握手,在第二次握手后,客户端了解到服务端可以接收到自己发送的数据,但是服务端并不确定客户端是否能接收到自己发送的数据,所以需要进行第三次握手来确定连接是否成功。

在前后端网络交互方面做过哪些 性能和体验优化

1、对资源进行DNS预解析,将资源放到本地缓存中。DOM树和CSSOM树从本地缓存获取资源 2、将资源进行合并压缩
3、使用字体图标、小图片使用base64格式
4、使用GZIP对文件进行进一步压缩
5、图片进行懒加载处理
6、使用CDN资源部署 实现资源负载均衡
7、对js代码按类型分块打包,js库等短期内不需要更新的单独打包到一起,其他业务代码放到一起。通过HTTP的强缓存和协商缓存对这两种资源分别做缓存处理。

浏览器渲染

浏览器根据请求头Content-Type字段判断资源类型,如果资源为html,浏览器会将字节编码数据转化为HTML标记语言。对其进行词法分析,分析结构确定层级关系,生成DOM树。

DOM树构建完成后加载所有css代码,包括使用link标签、@import(@import导入的css代码为同步加载,会阻塞页面渲染应避免使用)生成CSSStyleSheet、构建CSSOM树。

融合DOM跟CSSOM布局渲染树,浏览器根据渲染树通过重绘、回流计算所有节点在页面中的大小、位置等数据,然后绘制(栅格化)页面元素。如果修改DOM(内容、样式),同样也是这个流程:构建DOM、CSSOM、布局并构建渲染树,重绘/回流计算节点数据后绘制页面元素。

DOM树与Render树的区别

1、Render树是有DOM树和CSSOM树 合并渲染出的 2、DOM树与HTML标签一一对应的,包括head、隐藏标签 3、Render树不包括head、隐藏标签,并且大段文字每一行都是独立节点,每个节点都有自己的css属性

什么是回流和重绘

回流: Render树的一部分或全部的元素因为改变自身的宽高、布局、显示或隐藏、或内部文字结构发生变化导致重构页面时,回流就产生了。

重绘: 当一个元素的宽高、布局、显示或隐藏没有改变,只是改变元素的样式例如背景色,就会发生重绘

发生回流就一定会发生重绘,发生重绘不一定会发生回流

在浏览器渲染方面做过哪些 性能和体验优化

1、构建DOM树进行词法分析时,不遵循W3C标准的词法会造成解析时的性能浪费。我们应该遵循W3C的标准使用合理具备语义化的标签。
2、尽量避免深层次DOM嵌套,以提升DOM树构建的速度
3、@import引入的css资源是同步加载的 会阻塞页面渲染应当避免使用
4、HTML中javascript代码加载ye会阻塞页面渲染,应该将其放入HTML中最底部或者改为异步加载
5、减少页面回流跟重绘(修改元素位置和结构),样式集中处理放入统一一个class中批量修改样式。
6、增加骨架屏