• 浏览器路由/缓存/HTTP报文


    浏览器路由

    前言

    路由这概念最开始是在后端出现的,在前后端不分离的时候,由后端来控制路由,服务器接收客户端的请求,解析对应的url路径,并返回对应的页面/资源。简单的说,路由就是根据不同的url地址来展示不同的内容或页面。

    现在的网络应用程序越来越多的使用AJAX异步请求完成页面的无缝刷新,虽然Ajax解决了用户交互时体验的痛点,但是多页面之间的跳转一样会有不好的体验,所以便有了spa(single-page application)使用的诞生。而spa应用便是基于前端路由实现的,所以便有了前端路由。

    前端路由的原理本质上就是在不刷新浏览器的情况下,请求下修改URL、检测URL的变化,截获URL的地址,通过解析、匹配路由规则从而实现UI的更新。路由的实现通常有两种形式一种是Hash模式,一种是History模式。

    hash

    vue-router 在实现单页面路由时,提供了两种方式:Hash 模式和 History 模式;vue2是 根据 mode 参数来决定采用哪种方式,默认是 Hash 模式,手动设置为 History 模式 。

    hash 模式是一种把前端路由的路径用井号 # 拼接在真实 url 后面的模式。当井号 # 后面的路径发生变化时,浏览器并不会重新发起请求,而是会触发 onhashchange 事件。

    hash 模式是利用了 window 可以监听 onhashchange 事件来实现的,也就是说 hash 值是用来指导浏览器动作的,对服务器没有影响,HTTP 请求中也不会包括 hash 值,同时每一次改变 hash 值,都会在浏览器的访问历史中增加一个记录,使用“后退”按钮,就可以回到上一个位置。所以,hash 模式 是根据 hash 值来发生改变,根据不同的值,渲染指定DOM位置的不同数据。

    特点

    • url中带一个 # 号
    • 可以改变URL,但不会触发页面重新加载(hash的改变会记录在 window.hisotry 中)因此并不算是一次 HTTP 请求,所以这种模式不利于 SEO 优化
    • 只能修改 # 后面的部分,因此只能跳转与当前 URL 同文档的 URL
    • 只能通过字符串改变 URL
    • 通过 window.onhashchange 监听 hash 的改变,借此实现无刷新跳转的功能。
    • 每改变一次 hash ( window.location.hash),都会在浏览器的访问历史中增加一个记录。
    • 路径中从 # 开始,后面的所有路径都叫做路由的 哈希值 并且哈希值它不会作为路径的一部分随着 http 请求,发给服务器
    • hash 永远不会提交到 server 端(可以理解为只在前端自生自灭)。

    history

    window.history 属性指向 History 对象,它表示当前窗口的浏览历史。当发生改变时,只会改变页面的路径,不会刷新页面。 History 对象保存了当前窗口访问过的所有页面网址。通过 history.length 可以得出当前窗口浏览网址的记录。 由于安全原因,浏览器不允许脚本读取这些地址,但是允许在地址之间导航。 浏览器工具栏的“前进”和“后退”按钮,其实就是对 History 对象进行操作。

    属性

    • History.length:当前窗口访问过的网址数量(包括当前网页)
    • History.state:History 堆栈最上层的状态值

    主要API

    • history.back():移动到上一个网址,等同于点击浏览器的后退键。对于第一个访问的网址,该方法无效果。
    • history.forward():移动到下一个网址,等同于点击浏览器的前进键。对于最后一个访问的网址,该方法无效果。
    • history.go(): 这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n),n可为正数可为负数; 默认参数为0,相当于刷新当前页面。
    • History.pushState(satbleObject,title,URL):用于在历史中添加一条记录。pushState()方法不会触发页面刷新,只是导致 History 对象发生变化,地址栏会有变化。
    • History.replaceState(satbleObject,title,URL):用来修改 History 对象的当前记录,用法与 pushState() 方法一样。

    satbleObject 是一个JavaScript对象,与用pushState()方法创建的新历史记录条目关联。无论何时用户导航到新创建的状态,都会触发popstate事件,并能在事件中使用该对象。

    popstate 事件:

    每当 history 对象出现变化时,就会触发 popstate 事件。 window.addEventListener('popstate', e => {});

    注意
    • 仅仅调用pushState()方法或replaceState()方法 ,并不会触发该事件。
    • 只有用户点击浏览器倒退按钮和前进按钮,或者使用 JavaScript 调用History.back()、History.forward()、History.go()方法时才会触发。
    • 该事件只针对同一个文档,如果浏览历史的切换,导致加载不同的文档,该事件也不会触发。
    • 页面第一次加载的时候,浏览器不会触发popstate事件。

    缓存

    在前端性能优化的方式中,最重要的当然是缓存了,使用好了缓存,对项目有很大的帮助。比如我们访问网页时,使用网页后退功能,会发现加载的非常快,体验感很好,这就是缓存的力量。

    缓存有哪些好处?

    • 缓解服务器压力,不用每次都去请求某些数据了。
    • 提升性能,打开本地资源肯定会比请求服务器来的快。
    • 减少带宽消耗,当我们使用缓存时,只会产生很小的网络消耗。

    Web缓存种类: 数据库缓存,CDN缓存,代理服务器缓存,浏览器缓存

    浏览器缓存

    每个浏览器都实现了HTTP缓存,我们通过浏览器使用HTTP协议与服务器交互的时候,浏览器会根据一套与服务器约定的规则进行缓存工作。浏览器的前进/后退,利用的是浏览器的缓存机制。

    浏览器缓存其实就是指在本地使用的计算机中开辟一个内存区,同时也开辟一个硬盘区作为数据传输的缓冲区,然后用这个缓冲区来暂时保存用户以前访问过的信息。

    浏览器缓存位置一般分为四类: Service Worker–>Memory Cache–>Disk Cache–>Push Cache。

    强缓存

    强缓存是当我们访问URL的时候,不会向服务器发送请求,直接从缓存中读取资源,但是会返回200的状态码。

    我们第一次进入页面,请求服务器,然后服务器进行应答,浏览器会根据response Header来判断是否对资源进行缓存,如果响应头中expires、pragma或者cache-control字段,代表这是强缓存,浏览器就会把资源缓存在memory cache 或 disk cache中。

    第二次请求时,浏览器判断请求参数,如果符合强缓存条件就直接返回状态码200,从本地缓存中拿数据。否则把响应参数存在request header请求头中,看是否符合协商缓存,符合则返回状态码304,不符合则服务器会返回全新资源。

    以下是强缓存的字段

    • expires

      是HTTP1.0控制网页缓存的字段,值为一个时间戳,服务器返回该请求结果缓存的到期时间,意思就是,再次发送请求时,如果未超过过期时间,直接使用该缓存,如果过期了则重新请求。

      有个缺点,就是它判断是否过期是用本地时间来判断的,本地时间是可以自己修改的。

    • Cache-Control

      是HTTP1.1中控制网页缓存的字段,当Cache-Control都存在时,Cache-Control优先级更高,主要取值为:

      public:客户端和服务器都可以缓存(所有内容都将被缓存)。

      privite:资源只有客户端可以缓存(Cache-Control的默认值)。

      no-cache:客户端缓存资源,但是是否缓存需要经过协商缓存来验证。

      no-store:不使用缓存(不使用强缓存,也不使用协商缓存)。

      max-age:设置缓失效时间。

      Cache-Control使用了max-age相对时间,解决了expires的问题。

    • pragma

      这个是HTTP1.0中禁用网页缓存的字段,其取值为no-cache,和Cache-Control的no-cache效果一样。 http1.1中可用Cache-Control替换

    缓存位置

    强缓存会把资源房放到memory cache 和 disk cache中

    • 存储图像和网页等资源主要缓存在disk cache
    • 操作系统缓存文件等资源大部分都会缓存在memory cache中。
    • 具体操作浏览器自动分配,看谁的资源利用率不高就分给谁。

    查找浏览器缓存时会按顺序查找: Service Worker–>Memory Cache–>Disk Cache–>Push Cache。

    1. Service Worker

    是运行在浏览器背后的独立线程,一般可以用来实现缓存功能。使用 Service Worker的话,传输协议必须为 HTTPS。因为 Service Worker 中涉及到请求拦截,所以必须使用 HTTPS 协议来保障安全。Service Worker 的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的。

    2. Memory Cache

    内存中的缓存,主要包含的是当前页面中已经抓取到的资源,例如页面上已经下载的样式、脚本、图片等。读取内存中的数据肯定比磁盘快,内存缓存虽然读取高效,可是缓存持续性很短,会随着进程的释放而释放。一旦我们关闭 Tab 页面,内存中的缓存也就被释放了。

    2.Disk Cache

    存储在硬盘中的缓存,读取速度慢点,但是什么都能存储到磁盘中,比之 Memory Cache 胜在容量和存储时效性上。

    在所有浏览器缓存中,Disk Cache 覆盖面基本是最大的。它会根据 HTTP Herder 中的字段判断哪些资源需要缓存,哪些资源可以不请求直接使用,哪些资源已经过期需要重新请求。并且即使在跨站点的情况下,相同地址的资源一旦被硬盘缓存下来,就不会再次去请求数据。绝大部分的缓存都来自 Disk Cache。

    4.prefetch cache(预取缓存)

    link标签上带了prefetch,再次加载会出现。

    prefetch是预加载的一种方式,被标记为prefetch的资源,将会被浏览器在空闲时间加载。

    5. Push Cache

    Push Cache(推送缓存)是 HTTP/2 中的内容,当以上三种缓存都没有命中时,它才会被使用。它只在会话(Session)中存在,一旦会话结束就被释放,并且缓存时间也很短暂,在Chrome浏览器中只有5分钟左右,同时它也并非严格执行HTTP头中的缓存指令。

    协商缓存

    协商缓存就是强缓存失效后,浏览器携带缓存标识向服务器发送请求,由服务器根据缓存标识来决定是否使用缓存的过程。

    主要有以下两种情况:

    协商缓存生效,返回304

    请添加图片描述

    304 状态码表示客户端发送携带有缓存标识(GET方法的请求报文中包含If-Math,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since中任意首部)的请求时,因为服务器端的资源未改变,可直接使用客户端未过期的缓存。304状态码返回时,不包含任何响应的主体部分,304虽然划分到3XX类型状态码中,但是和重定向没有关系

    协商缓存失效,返回200和请求结果

    如果发起携带缓存标识资源请求时候服务器的资源已经更新。则返回请求结果,成功的话状态码为200

    如何设置协商缓存

    Last-Modified / If-Modified-Since

    Last-Modified是服务器响应请求时,返回该资源文件在服务器最后被修改的时间。

    If-Modified-Since则是客户端再次发起该请求时,携带上次请求返回的Last-Modified值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。服务器收到该请求,发现请求头含有If-Modified-Since字段,则会根据If-Modified-Since的字段值与该资源在服务器的最后被修改时间做对比,若服务器的资源最后被修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用缓存文件。

    Etag / If-None-Match

    Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成)。

    If-None-Match是客户端再次发起该请求时,携带上次请求返回的唯一标识Etag值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。服务器收到该请求后,发现该请求头中含有If-None-Match,则会根据If-None-Match的字段值与该资源在服务器的Etag值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200。

    Etag / If-None-Match优先级高于Last-Modified / If-Modified-Since,同时存在则只有Etag / If-None-Match生效。

    缓存方案

    目前的项目大多使用的缓存方案:

    • HTML:协商缓存
    • css、js、图片:强缓存,文件名带上hash

    强缓存与协商缓存的区别

    1. 强缓存不发请求到服务器,所以有时候资源更新了浏览器还不知道,但是协商缓存会发请求到服务器,所以资源是否更新,服务器肯定知道。

    2. 大部分web服务器都默认开启协商缓存。

    刷新对于强缓存和协商缓存的影响

    当ctrl+f5强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存。

    当f5刷新网页时,跳过强缓存,但是会检查协商缓存。

    浏览器地址栏中写入URL,回车 浏览器发现缓存中有这个文件了,不用继续请求了,直接去缓存拿。(最快)

    HTTP报文

    HTTP请求报文

    由请求行和HTTP头组成

    请求行

    包含请求的方法,请求的URI和HTTP版本3个字段组成

    http协议得请求方法有:

    • GET 获取资源
    • POST 向服务器端发送数据,传输实体主体
    • PUT 传输文件
    • HEAD 获取报文首部
    • DELETE 删除文件
    • OPTIONS 询问支持的方法
    • TRACE 追踪路径

    HTTP请求头

    • 包括通用信息头、请求头、实体头、空行
    • 通用信息头指的是请求和响应报文都支持的头域,分别为Cache-Control、Connection、Date、Pragma、Transfer-Encoding、Upgrade、Via;
    • 实体头则是实体信息的实体头域,分别为Allow、Content-Base、Content-Encoding、Content-Language、Content-Length、Content-Location、Content-MD5、Content-Range、Content-Type、Etag、Expires、Last-Modified、extension-header。
    • User-Agent:产生请求的浏览器类型。
    • Accept:客户端可识别的内容类型列表。
    • Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
    • 最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。

    HTTP响应报文

    HTTP响应也由四个部分组成,分别是:响应行响应头空行响应体

    状态行

    包含响应状态码,原因短语和HTTP协议版本

    HTTP头

    包括通用信息头、请求头、实体头

    响应报文主体

    响应状态码

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

    通用首部字段

    首部字段名说明
    Cache-Control控制缓存行为
    Connection链接的管理
    Date报文日期
    Pragma报文指令
    Trailer报文尾部的首部
    Trasfer-Encoding指定报文主体的传输编码方式
    Upgrade升级为其他协议
    Via代理服务器信息
    Warning错误通知

    请求首部字段

    首部字段名说明
    Accept用户代理可处理的媒体类型
    Accept-Charset优先的字符集
    Accept-EncodingAccept-Encoding
    Accept-Langulage优先的语言
    AuthorizationWeb认证信息
    Expect期待服务器的特定行为
    From用户的电子邮箱地址
    Host请求资源所在的服务器
    If-Match比较实体标记
    If-Modified-Since比较资源的更新时间
    If-None-Match比较实体标记
    If-Range资源未更新时发送实体Byte的范围请求
    If-Unmodified-Since比较资源的更新时间(和If-Modified-Since相反)
    Max-Forwards最大传输跳数
    Proxy-Authorization代理服务器需要客户端认证
    Range实体字节范围请求
    Referer请求中的URI的原始获取方
    TE传输编码的优先级
    User-AgentHTTP客户端程序的信息
  • 相关阅读:
    Java程序设计——JDBC基础(JDBC编程)
    微信小程序开发:页面分享卡片、风格选择、通道启用等可配置
    代码整洁之道
    HTML+CSS+JS+Django 实现前后端分离的科学计算器、利率计算器(附全部代码在gitcode链接)
    【C++】运算符重载 ⑧ ( 左移运算符重载 | 友元函数 / 成员函数 实现运算符重载 | 类对象 使用 左移运算符 )
    【java】实现自定义注解校验——方法一
    【设计模式】2.工厂模式
    第 114 场 LeetCode 双周赛题解
    ABP.Next系列02 项目下载 运行 -Fstyle
    Profibus主站转Profinet网关介绍
  • 原文地址:https://blog.csdn.net/weixin_51445423/article/details/126721518