前端实践选题-HTTP的场景实践 | 豆包MarsCode AI刷题

42 阅读5分钟

一、缓存的具体应用实例

假设服务器上有一个图片资源。

首次请求时的交互过程

当浏览器首次发起请求时,服务器会将响应头中的 Cache-Control 和 ETag 值返回给浏览器。比如服务器响应可能如下所示:

HTTP/1.1 200 OK
Cache-Control: max-age=3600
ETag:"123456"
Content-Length:10240
Content-Type: image/png
<binary image data...>

此时,浏览器接收到响应头中的相关信息后,将资源保存到本地缓存中。

再次请求时的交互过程

当浏览器再次请求这个资源时,浏览器会先检查本地缓存中是否有该资源的缓存条目。如果有,则会直接返回本地缓存中的数据;如果没有,则会向服务器发起请求。浏览器在发起请求时,会将 If-None-Match 和 If-Modified-Since 字段添加到请求头中,告诉服务器自己本地缓存的该资源的 ETag 和 Last-Modified 时间戳。如下所示:

GET /img/logo.png HTTP/1.1
Host: example.com
If-None-Match:"123456"
If-Modified-Since:Thu,20May202110:10:10 GMT

服务器接收到请求后,会根据请求头中的 If-None-Match 和 If-Modified-Since 字段和资源的当前 ETag 和 Last-Modified 时间戳,来判断该资源是否更新。如果资源未更新,则服务器返回 304 Not Modified 响应码,表示不需要重新下载资源,可以直接使用本地缓存。如果资源已更新,则服务器返回新的资源,并更新浏览器的本地缓存。

这样的缓存机制在实际应用中,可以极大地提高网页加载速度,减少服务器的负载。例如,在一个新闻网站中,大量的图片资源如果每次都从服务器重新获取,会消耗大量的带宽和服务器资源。而通过合理设置缓存策略,可以让浏览器在一定时间内使用本地缓存的图片,只有当图片资源有更新时才从服务器获取新的资源,从而提高用户体验。

二、缓存与浏览器行为

1. 分析浏览器读取缓存的顺序为 memory->disk,解释 from memory cache 和 from disk cache 的含义及使用场景。

  • 含义
    • from memory cache:代表使用内存中的缓存。这个资源是直接从内存中拿到的,不会请求服务器。一般已经加载过该资源且缓存在了内存当中,当关闭该页面时,此资源就被内存释放掉了,再次重新打开相同页面时不会出现from memory cache的情况。
    • from disk cache:代表使用的是硬盘中的缓存。此资源是从磁盘当中取出的,也是在已经在之前的某个时间加载过该资源,不会请求服务器。但是此资源不会随着该页面的关闭而释放掉,因为是存在硬盘当中的,下次打开仍会from disk cache。
  • 使用场景
    • 通常,脚本、字体、图片等可能会被缓存在内存中,因为这些资源可能随时会被执行或使用,从内存中读取速度更快。例如,在加载一个包含大量动态交互的网页时,脚本文件可能会被放入内存缓存中,以便快速响应用户操作。
    • 对于 CSS 文件等非脚本资源,一般会被缓存在硬盘中。这是因为 CSS 样式加载一次即可渲染出网页,不需要像脚本那样随时快速响应执行,从硬盘读取虽然速度相对较慢,但可以节省内存空间。例如,在浏览一个电商网站时,页面的 CSS 样式表会被缓存在硬盘中,下次访问时直接从硬盘读取,减少网络请求。

2. 探讨在页面引入静态资源文件时,静态资源改变后仍读取缓存的问题及解决办法,如使用打包工具加上 hash 码。

  • 问题分析:当静态资源文件发生改变后,浏览器可能仍然读取缓存中的旧版本资源,这是因为浏览器的缓存机制会优先使用本地缓存以提高加载速度。例如,在前端项目部署后,如果没有采取相应措施,用户必须强刷浏览器后才能看到最新的代码和效果,而很多用户并不知晓强刷浏览器这一操作,这就导致了用户体验不佳。
  • 解决办法
    • 使用打包工具加上 hash 码是一种有效的解决方法。以 gulp 为例,使用gulp-rev插件可以给打包的 js 或者 css 增加一个 hash 值,这个 hash 值是随机生成的,意味着每个文件带着的 hash 值是不一样的。如果希望文件携带的 hash 值是一样的话,就必须使用gulp-rename重新命名。生成的一个 json 映射表,然后按照这个映射表进行替换。在 html 引入的时候也需要发生变化,使用gulp-rev-collector和gulp-replace进行替换,给引入路径的.js 替换成 hash 值 +.js。
    • 在 Vue 项目中,也可以通过配置webpack来给 css 和 js 增加 hash。例如,使用mini-css-extract-plugin插件,设置filename: 'css/[name].[contenthash].css',给 css 文件加上 hash。对于 js 文件,可以在chainWebpack中设置config.output.filename(js/[name].[contenthash].js),给 js 文件加上 hash。这样,当静态资源文件发生改变时,由于文件的 hash 值发生了变化,浏览器就会认为这是一个新的资源,从而去服务器请求新的资源,而不是使用缓存中的旧资源。