一、浏览器缓存机制
1. 强缓存
浏览器直接从本地缓存中获取数据,不与服务器进行交互;它有两种依据:Expires 和 Cache-Control可以用来判断是否命中缓存(可以直接从缓存中读取资源)。
1)Expires
Expires即过期时间,存在于服务端返回的响应头中,即浏览器在这个过期时间之前可以直接从缓存里面获取数据,无需再次请求。比如:
Expires: Wed, 22 Nov 2019 08:41:00 GMT
缺点: 客户端与服务端的时间因为某些原因(例如时区不同;客户端和服务端有一方的时间不准确)发生误差,那强制缓存就可能会失效。
2)Cache-Control
在HTTP1.1中,采用了一个非常关键的字段:Cache-Control。
我们利用Cache-Control来控制缓存时,我们一般设置
Cache-Control:max-age=3600
这表示代表这个响应返回后在 3600 秒,也就是一个小时之内可以直接使用缓存。 这样的话,之前所说的expires所设置的时间值是一个绝对值,而Cache-Control所设置的时间值是一个相对值。
此外,Cache-Control可以组合非常多的指令,完成更多场景的缓存判断,比如
public: 表示响应可以被客户端和代理服务器缓存;
private: 表示响应只可以被客户端缓存,而代理服务器不能缓存;
no-store: 表示不缓存任何响应。
(还有很多属性···)
小结: 当Expires和Cache-Control同时存在的时候,Cache-Control会优先考虑。
当强缓存失效了,就进入协商缓存。
2. 协商缓存
协商缓存就是强制缓存失效后,浏览器(携带缓存标识)向服务器发起请求,由服务器(根据缓存标识)决定是否使用本地缓存 的过程,主要有两种情况。
1)Last-Modified / If-Modified-Since
- 浏览器在第一次访问资源时,服务器返回资源的同时,在响应头中添加 Last-Modified,值是这个资源在服务器上的最后修改时间,浏览器接收后就会缓存文件和header;
Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT
-
当浏览器
下一次请求这个资源时,浏览器检测到有Last-Modified这个header,于是添加If-Modified-Since这个header,值就是Last-Modified中的值; -
服务器再次收到这个资源请求,会根据 If-Modified-Since 中的值与服务器中这个资源的最后修改时间对比,
如果没有变化,返回304和空的响应体,直接从缓存读取,
如果If-Modified-Since的时间小于服务器中这个资源的最后修改时间,说明文件有更新,于是返回新的资源文件和200。
2)Etag / If-None-Match
-
ETag是服务器给文件生成的唯一标识,只要里面的内容有改动,这个值就会变化。服务器通过响应头把这个值给浏览器。
-
浏览器在
下一次向服务器发送请求时,会将上一次返回的Etag值放到请求头里的If-None-Match中, -
服务器只需要比较客户端传来的If-None-Match跟自己服务器上的ETag是否一致,就能很好地判断资源是否被修改过了。
如果ETag是一致的,则直接返回304知会客户端直接使用本地缓存即可。
如果服务器发现ETag匹配不上,说明要更新了。返回新的资源,状态码200。
小结:
1)在精确度上,Etag要优于Last-Modified。
因为Last-Modified的时间单位是秒,如果某个文件在1秒内发生了改变,那么Last-Modified的值并不会发生改变;而Etag是只要内容一变化变化,所以会更加准确。
而且一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们使用ETag更好。
2)在性能上,Last-Modified要优于Etag。
因为Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值。
二、浏览器本地存储
1. Cookie
HTTP Cookie(也叫 Web Cookie或浏览器 Cookie)是浏览器第一次发送请求到服务器时,然后 服务器 返回给 浏览器 并保存在本地的一小块 数据,然后在 浏览器 下次再向同一域名发起请求时,都会携带相同的Cookie。服务器拿到Cookie 进行解析,便能获得客户端的状态。
根据这一特点,Cookie的应用有,比如说保持用户的登录状态,或者像淘宝根据喜好来推荐商品等等。总之,Cookie 使 无状态的 HTTP 协议 能够记录 稳定的状态信息成为了可能。
缺点:
- 容量小:容量不能超过4kb,只能用来存储少量信息;
- 安全性低:由于 Cookie以纯文本的形式在浏览器和服务器中传递,很容易被非法用户截获,然后进行一系列的篡改,在 Cookie 的有效期内重新发送给服务器,那后果不堪设想。
- 影响性能:Cookie 紧跟域名,不管域名下面的某一个地址需不需要这个 Cookie ,在每次http请求中都会带上Cookie,这样就携带了一些不必要的内容,从而会影响网络性能。
2. localStorage
localStorage有一点跟Cookie一样,就是针对一个域名,即在同一个域名下,会存储相同的一段localStorage。
localStorage与Cookie的区别:
-
容量更大,localStorage 的容量上限为5M,相比于Cookie的 4K 大大增加。当然这个 5M 是针对一个域名的,因此对于一个域名是持久存储的。
-
安全性更高,只存在客户端,默认不参与与服务端的通信。这样就很好地避免了 Cookie 带来的性能问题和安全问题。
-
接口封装,操作更方便。通过localStorage暴露在全局,并通过它的setItem(存值)和 getItem(取值)等方法进行操作,非常方便。
应用:
利用localStorage的较大容量和持久特性,可以用来存储一些内容稳定的资源,比如官网的logo,存储Base64格式的图片资源。
3. sessionStorage
sessionStorage以下方面和localStorage一致:
- 容量上限也为 5M。
- 只存在客户端,默认不参与与服务端的通信。
- 接口封装,除了sessionStorage名字有所变化,存储方式、操作方式均和localStorage一样。
sessionStorage与localStorage的区别:
- sessionStorage只是会话级别的存储,并不是持久化存储,当关闭页面,数据就不再被保存;
- localStorage生命周期永久生效,关闭页面也保存数据,而且支持多窗口,数据可共享。
应用:
可以用它存储本次浏览记录。如果关闭页面后不需要这些记录。
4. IndexedDB
由于webStorage容量上限只有5M,而且不提供搜索功能,不能建立自定义的索引。所以,就出现了IndexedDB。通俗地说,IndexedDB就是浏览器提供的本地数据库,它可以被网页脚本创建和操作。IndexedDB 允许储存大量数据,提供查找接口,还能建立索引。
三、从输入URL到页面加载完成的过程
1. 在浏览器输入URL
2. 先检查强缓存,如果命中直接使用,否则进入下一步
详解见上
3. DNS域名解析系统对输入的网址进行解析
1)浏览器根据地址,首先,在浏览器缓存中查找,如果没有,就去系统缓存(即操作系统中的 hosts 文件)中查找,如果没有,就去路由器缓存中查找。
2)若没有,主机就向本地域名服务器进行(递归)查询。
3)如果还是没有,本地域名服务器就向根域名服务器进行(迭代)查询。
4)根服务器就会给本地域名服务器返回一个顶级域名服务器(也就是com域服务器)的地址。(如.com、.cn、.org等,全球只有13台左右。) 本地域名服务器向顶级域名服务器进行查询。
5)顶级域名服务器会告诉本地域名服务器下一次应查询的权限域名服务器(也就是baidu域服务器)的IP地址。
6)本地域名服务器向权限域名服务器查询该域下主机名为www的计算机对应的IP地址,
7)权限域名服务器就会把最终查询到的结果IP给本地域名服务器,然后本地域名服务器再给主机。
4. 三次握手建立TCP连接
具体连接过程请戳 -> (之后再更)
5. 客户端发送http请求
现在TCP连接建立完毕,浏览器可以和服务器开始通信,即开始发送 HTTP 请求。
浏览器发送HTTP请求需要包含请求起始行、请求头、请求主体三部分。
6. 服务端响应请求
网络响应也具有三个部分:响应行、响应头和响应体。
7. 浏览器解析响应请求,进行页面渲染
1)浏览器通过 HTML解析器 根据深度遍历的原则把 HTML 解析成 DOM 树;
2)浏览器通过 CSS解析器 将 CSS 解析成 CSS Rule 树(CSSOM Tree);
3)浏览器将 JS 代码解析并把逻辑(HTML和CSS的操作)应用到布局中,按要求呈现响应的结果;
4)根据 DOM 树和 CSSOM 树来构造 render Tree;
5)layout:当 render tree 中任一节点的几何尺寸发生改变,render tree 就会重新布局,重新来计算所有节点在屏幕的位置,这个过程叫重排(也可以叫回流);
6)repaint:当 render tree 中任一元素样式属性(几何尺寸没改变)发生改变时,render tree 都会重新画,比如字体颜色,背景等变化,这个过程叫重绘;
7)paint:遍历 render tree,并调动硬件图形 API 来绘制每个节点。
二、Cookie,Session和token
1. Cookie
HTTP Cookie(也叫 Web Cookie或浏览器 Cookie)是浏览器第一次发送请求到服务器时,然后 服务器 返回给 浏览器 并保存在本地的一小块 数据,然后在 浏览器 下次再向同一域名发起请求时,都会携带相同的Cookie。服务器拿到Cookie 进行解析,便能获得客户端的状态。
根据这一特点,Cookie的应用有,比如说保持用户的登录状态,或者像淘宝根据喜好来推荐商品等等。总之,Cookie 使 无状态的 HTTP 协议 记录 稳定的状态信息成为了可能。
相当于给客户端们颁发一个通行证,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。
2. Session
Session是另一种记录服务器和客户端会话状态的机制,
Session 是基于 Cookie 实现的,Session 存储在服务器端,SessionId 会被存储到客户端的Cookie 中
。
认证过程:
1)用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建对应的 Session;
2)请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器;
3)浏览器接收到 SessionID 后,会将它存入到 Cookie 中,同时 Cookie 记录此 SessionID 属于哪个域名;
4)当用户第二次访问服务器的时候,服务端会从 Cookie 中获取 SessionID,再根据 SessionID 查找对应的 Session 信息;
5)如果没有找到说明用户没有登录或者登录失效,如果找到 Session 证明用户已经登录可执行后面操作。
从这里就可以看出Session 是基于 Cookie 实现的,当用户在会话的过程中关闭浏览器结束进程,则这个sessionid将消失,如果用户又打开浏览器想继续这次会话的时候,就会因为发送的请求中没有这个sessionid而使服务器无法辨别该把那个session信息给他,注意(这个时候服务器端的sessionid和sessionid所指向的session都还存在,只是没有正确的sessionid和它匹配而占用服务器内存,只有session过期或服务器重启才释放内存)。
上面这种方式叫会话cookie,把cookie放在浏览器内存里,只能在这个浏览器的内存范围里完成会话,是一种不长久的方式;
为了能长久会话,就出现了持久化cookie,把cookie固化在用户的计算机上,现在的cookie不单单能存放sessionid,还能放用户信息,样式表信息等。
客户端访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。
有效期:Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。但由于会有越来越多的用户访问服务器,因此Session也会越来越多。为防止内存溢出,服务器会把定期清理长时间内没有活跃的Session。 Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。
如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。
Cookie和Session的区别:
1)存放位置:Cookie是运行在客户端,Session是运行在服务器端。
2)安全性:Cookie因为在客户端保存,所以数据存放在Session,安全性更高。
3)资源占用:Session因为保存在服务器端,因此会消耗大量服务器资源,而Cookies保存于客户端,不会占用服务器资源。
4)内存大小:Cookie有大小限制以及浏览器在存Cookie的个数也有限制,Session是没有大小限制和服务器的内存大小有关。
5)有效期:只需要设置Cookie的过期时间属性为一个很大很大的数字,Cookie就可以在浏览器保存很长时间。 由于Session依赖于名为SessionID的Cookie,而Cookie SessionID的过期时间默许为–1,只需关闭了浏览器(一次会话结束),该Session就会失效。
3. token
Session是基于Cookie进行用户识别的, Cookie如果被截获,用户就会很容易受到跨站请求伪造CSRF的攻击。 所以采用token会更加安全。
认证过程:
- 客户端使用用户名跟密码请求登录
- 服务端收到请求,去验证用户名与密码
- 验证成功后,服务端会对当前用户数据进行加密,生成一个加密字符串token,返回给客户端
- 客户端收到 token 以后,会把它存到 localStorage 里
- 客户端再次访问服务器时,服务端去对传来的 token 进行解密,如何进行验证 ,如果验证成功,就向客户端返回请求的数据。