面试之 一个页面从输入url到页面加载显示完成,中间都经历了什么

607 阅读8分钟
随着前端越来越成熟,前端的面试也越来越深入,面试就会经常问道一些和后台有些关系的问题,比如经常 见到的 当你在页面输入一个url到页面加载显示完成,中间都经历了什么?结果也就那么几个过程,百度一下你会发现有很多答案。 整体的过程大概就是一下几种
  • DNS域名解析
  • TCP连接
  • HTTP请求
  • 处理请求返回的HTTP响应
  • 页面渲染

前端呢主要了解http请求,处理请求返回的HTTP响应和页面渲染这一块的内容,别的呢 我们一笔略过 ,大约知道这里边发生什么事就可以了

DNS域名解析

首先我们要知道的是输入地址栏的域名并不是资源真实的位置,通过域名与ip地址的映射 找到资源的真实地址。

TCP连接 通过第一步把服务器的ip地址拿到 获取到ip地址后便开始建立连接 完成三次握手。

http请求 tcp建立连接以后 发起一个http请求, 客户端向服务器发起的http 请求的时候 请求信息包括三个部分 请求方法URI协议/版本 请求头 请求正文 。请求方法(一般浏览器发起GET 或者POST请求)当然还包括 PUT DELETE HEAD OPTION TREANE 方法

那么我们先看一个http的请求的例子
//请求的方法协议版本
GET/sample.jspHTTP/1.1 
//请求头
Accept:image/gif.image/jpeg,*/* //
Accept-Language:zh-cn   //
Connection:Keep-Alive
Host:localhost
User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)
Accept-Encoding:gzip,deflate
//请求正文
username=jinqiao&password=1234


对于请求的协议版本 没有什么好说的 就是几个固定的 http的版本 0.9 1.0 1.1 2.0

0.9 版本是http协议的第一个版本 已过时 它的组成及其简单  只允许客户发一个GET请求,不支持协议头, 造成0.9版本支持一种内容 纯文本

1.0版本 http的第二个版本, 第一个在通讯中指定版本号的http协议版本 至今被官方采用 相对于0.9 还加了一下主要特性
- 支持请求与响应头
- 响应对象以一个响应状态行开始
- 响应对象不限于超文本
- 开始支持客户端其他请求方法 POST PUT 等
- 支持长链接(但默认还是用的短链接) 缓存机制 及 身份认证

1.1 版本  是目前使用最广泛的协议版本 与1.0最大的区别就是默认支持长链接,而且1.1开始支持host 域 新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法

2.0 支持多路复用  做到一个连接并发处理多个请求 二轻并发的数量比1.1 大好几个数量级

请求头包含许多有关客户环境和请求正文有用的信息。 下边我们就说几个常用的请求头

首部字段名 说明
Accept 用户代理可处理的媒体类型
Content-Encoding 实体的编码方式
Content-Encoding 实体的编码方式
Content-Language 实体的自然语言
Content-Range 实体的位置范围
Content-Type 实体主体的媒体类型
Expires 实体过期时间
Last-Modified 资源的最后修改时间

前端 上传图片的时候 就会设置 上传实体主体的媒体类型为 multiparty/form-data 这样才能上传图片,另外 在用node 设置可以跨域访问的时候设置4个header头可以做到跨域

    Access-Control-Allow-Origin: http://foo.example //允许跨域的 域名  所有都允许可以用通配符 * 做值
    Access-Control-Allow-Methods: POST, GET, OPTIONS //允许跨域的方法
    Access-Control-Allow-Headers: X-PINGOTHER, Content-Type //  首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段。


    Access-Control-Max-Age: 86400 //请求的结果能够别缓存多久

接下来就是处理请求返回的HTTP响应 响应信息也是三个部分构成 状态行 响应头 响应体

状态行 例如 HTTP/1.1 200 OK

其中200 是状态码 Status-code 200 1.1 是版本 。说到状态码 就不得不提经常面试的状态码了

200 OK 客户端发过来的数据被正常处理
204 Not Content 正常响应,没有实体
206 Partial Content 范围请求,返回部分数据,响应报文中由Content-Range指定实体内容
301 (Moved Permanently) 永久重定向
302 (Found) 临时重定向,规范要求方法名不变,但是都会改变
303 (See Other) 和302类似,但必须用GET方法
304 (Not Modified) 状态未改变 配合(If-Match、If-Modified-Since、If-None_Match、If-Range、If-Unmodified-Since)
307 (Temporary Redirect) 临时重定向,不该改变请求方法
400 (Bad Request) 请求报文语法错误
401 (unauthorized) 需要认证
403 (Forbidden) 服务器拒绝访问对应的资源
404 (Not Found) 服务器上无法找到资源
500 (Internal Server Error)服务器故障
503 (Service Unavailable) 服务器处于超负载或正在停机维护

响应头主要由Cache-Control、 Connection、Date、Pragma等组成。

响应体为服务器返回给浏览器的信息,主要由HTML,css,js,图片文件组成

说到响应,就绕不过一个缓存的问题 那么我们根据这张图简单分析一下片 http的缓存机制

Expires 指缓存过期的时间,超过了这个时间点就代表资源过期。有一个问题是由于使用具体时间,如果时间表示出错或者没有转换到正确的时区都可能造成缓存生命周期出错。并且 Expires 是 HTTP/1.0 的标准,现在更倾向于用 HTTP/1.1 中定义的 Cache-Control。两个同时存在时也是 Cache-Control 的优先级更高。

Cache-Control

Cache-Control 可以由多个字段组合而成,主要有以下几个取值:

  • max-age 指定一个时间的长度 时间单位是秒
  • no-cache 告诉浏览器,一定要回服务器校验,不管有没有缓存数据。 如果确定没有被改,可以使用缓存中的数据
  • no-store 告诉浏览器任何情况下都不要被缓存。
  • public 仅体现在响应头,通知浏览器可以无条件的缓存该响应
  • private 仅体现在响应头,通知浏览器只针对单个用户缓存响应. 且可以具体指定某个字段.如private –“username”

协商缓存

缓存的资源到期了,并不意味着内容发生改变,如果服务器的资源没有差异,实际是上没有必要再次请求,客户端和服务器端通过某种验证机制验证当前请求资源是否可以使用缓存。

Last-modified/If-Modified-Since

Last-modified: 服务器端资源的最后修改时间,响应头部会带上这个标识。第一次请求之后,浏览器记录这个时间,再次请求时,请求头部带上 If-Modified-Since 即为之前记录下的时间。服务器端收到带 If-Modified-Since 的请求后会去和资源的最后修改时间对比。若修改过就返回最新资源,状态码 200,若没有修改过则返回 304。

注意:如果响应头中有 Last-modified 而没有 Expire 或 Cache-Control 时,浏览器会有自己的算法来推算出一个时间缓存该文件多久,不同浏览器得出的时间不一样,所以 Last-modified 要记得配合 Expires/Cache-Control 使用。

Etag/If-None-Match

由服务器端上生成的一段 hash 字符串,第一次请求时响应头带上 ETag: abcd,之后的请求中带上 If-None-Match: abcd,服务器检查 ETag,返回 304 或 200。

关于 last-modified 和 Etag 区别,已经有很多人总结过了:

  • 某些服务器不能精确得到资源的最后修改时间,这样就无法通过最后修改时间判断资源是否更新。
  • Last-modified 只能精确到秒。
  • 一些资源的最后修改时间改变了,但是内容没改变,使用 Last-modified 看不出内容没有改变。
  • Etag 的精度比 Last-modified 高,属于强验证,要求资源字节级别的一致,优先级高。如果服务器端有提供 ETag 的话,必须先对 ETag 进行 Conditional Request。

注意:实际使用 ETag/Last-modified 要注意保持一致性,做负载均衡和反向代理的话可能会出现不一致的情况。计算 ETag 也是需要占用资源的,如果修改不是过于频繁,看自己的需求用 Cache-Control 是否可以满足。

那么最后就是页面渲染了

浏览器拿到页面后开始解析html代码 遇到js css img 等静态资源时就像服务器请求下载, 解析成对应的DOM树 css 规则书 js脚本通过DOM api和 css api来操作DOM树

渲染 计算css样式 (js可动态修改dom或者css进一步渲染树和分布) 构建渲染树 确认布局 绘制 而渲染玩比以后就是关闭TCp连接或继续保持连接

通过四次挥手关闭连接

挥手完毕 页面加载完毕 这就是页面输入url后整个过程