利用 Nuxt.js 中的缓存 利用 Nuxt.js 中的缓存

2025-06-07

在 Nuxt.js 中利用缓存

在 Nuxt.js 中利用缓存

在 Nuxt.js 中利用缓存

我第一次接触缓存这个话题是在用 Vue.js 实现电视机顶盒软件的时候。Evan You,我想在创建 Vue.js 库的时候,肯定没想到电视软件会用到前端 JavaScript 框架 :D 。好了,回到正题。那时候,大家都在讨论缓存。“缓存这个,缓存那个,但一定要缓存,因为里面包含敏感数据”。从那时起,我一直在研究各种缓存实现,所以现在我决定深入探讨一下这个话题,并以一种简洁有趣的方式呈现给大家。

实施缓存策略和策略可以帮助提升网站性能。如果您对此主题感兴趣,可以查看我的其他文章:

如果你已经了解缓存的概念,你可以转到Nuxt 部分

什么是 Web 缓存?

正如维基百科所述:

A Web cache (or HTTP cache) is a system for optimizing the World Wide Web. It is implemented both client-side and server-side. The caching of images and other files can result in less overall delay when browsing the Web.

换句话说,缓存是一种用于减少查看页面所需时间的系统(加载所有必要的静态资产、内容请求等)。

我们可以定义两种主要类型的缓存;forwardreverse

  • 转发- 转发缓存是指位于 Web 服务器网络之外的缓存,例如客户端的 Web 浏览器中的缓存。网络感知转发缓存仅缓存访问量较大的项目。位于客户端和 Web 服务器之间的代理服务器可以评估 HTTP 标头并选择是否存储 Web 内容。
  • 反向- 位于一台或多台 Web 服务器的前端,加速来自互联网的请求并降低服务器峰值负载。这通常是一个内容分发网络 (CDN),它会在整个网络的各个节点保留 Web 内容的副本。

CDN 允许快速传输加载互联网内容所需的资产,包括 HTML 页面、javascript 文件、样式表、图像和视频。

缓存如何工作?

想象一下以下请求以方法的形式从前端发送到后端。

getDataFromDatabase()-> 花费 X 毫秒来获取数据并将其返回到前端。

如果有多个用户使用您的网站(相信我,确实有),您的服务器很可能会在一定数量的请求之后无法将数据传递给用户。

那么,如果我们能以某种方式将响应存储在另一个工具中,这样就不用一遍又一遍地运行相同的方法并向数据库请求数据,而是直接返回前一个请求的结果,那会怎么样呢?这不是很棒吗?

我们来看看下面的伪代码:

if request in cache {
  return cache[request]  // This is called a cache hit
} else {
  req = getDataFromDatabase()  //
  cache[request] = req        // This is called a cache miss
  return req                  //
}
Enter fullscreen mode Exit fullscreen mode

这就是缓存的实际工作原理。如果某个请求在缓存中,它将从缓存中返回响应,而不是从服务器(和数据库)请求数据。

什么时候使用缓存?

缓存是一种强大的机制,可以大大提高我们页面的性能,但应谨慎使用。

如果出现以下情况,我们应该使用缓存:

  1. 我们的请求计算相当慢
  2. 计算将连续运行多次
  3. 当特定输入的输出相同时
  4. 托管提供数据库访问费用。

*记住不要对特定用户的请求/路由/资源使用缓存。如果对 IE/get-user-data端点使用缓存,最终可能会向不同的用户提供不同的用户数据。哎哟!

缓存类型

我们可以定义三种主要的缓存类型:browserserverproxy

服务器

在这种情况下,缓存机制以应用程序、工具或软件的形式位于服务器上。常见的服务器缓存软件类型包括:

浏览器

在这种情况下,缓存机制位于浏览器中,主要用于缓存图像、样式、资产等资源。

代理人

在这种情况下,缓存机制位于代理服务器或反向代理服务器中,如NginxApacheVarnish,并且很可能是 ISP(互联网服务提供商)的一部分。

使用缓存的好处

缓存是一种强大的机制,如果使用得当,可以大大提高我们网站的性能:

  • 减少延迟
  • 减少服务器带宽
  • 减少服务器负载

HTTP 标头

服务器的每个响应都会返回数据和特定的标头。这些标头会指示浏览器如何处理缓存,以便将某些请求存储在浏览器缓存中。为了更好地理解它们的工作原理,我们应该关注两个主要的缓存标头expirescache-control

过期

Expires HTTP 标头包含响应被视为过期的日期/时间。

无效到期日期值为 0,表示过去的日期,意味着资源已经过期。

注意:如果响应中存在带有 max-age 或 s-maxage 指令的 Cache-Control 标头,则会忽略 Expires 标头。

Expires: Wed, 21 Oct 2015 07:28:00 GMT

缓存控制

Cache-Control HTTP 标头包含请求和响应中用于缓存的指令(说明)。如果某个指令存在于请求中,并不意味着该指令也存在于响应中。

  • Private- 仅缓存在客户端
  • Public- 也可以缓存在代理中
  • no-store- 内容不会被缓存
  • no-cache- 内容可以缓存,但需要服务器验证
  • max-age- 告诉浏览器保留缓存一定秒数

欲了解更多指令,请访问开发者 Mozilla

缓存验证

为了检查验证,服务器可能会在响应中发送一个或多个验证标头,客户端使用这些验证标头向服务器发出条件请求。

为此使用了两个元素;Etag和'':

ETag

它是实体标签的缩写,是服务器发送的与资源关联的唯一标识符。客户端使用该 ETag 向服务器发送请求,以检查内容是否已更改。

Cache-Control: max-age=600 Public
ETag: "123dadwad3211wda"
Enter fullscreen mode Exit fullscreen mode

客户端将继续使用缓存中的这张图片 600 秒。此后,客户端将使用If-None-Match标头向服务器发出请求,服务器会将之前提到的 ETag 作为值发送。然后,服务器会将新的内容添加到 ETag 中。如果两者不匹配,服务器将返回新的 ETag 和新的资源,用于替换当前图片。

如果它与现有图像匹配,服务器将响应状态代码,304 Not Modified并且客户端将再更新缓存 600 秒。

ETag 有两种类型:

  • 强——ETag: "123dadwad3211wda"两种资源完全相同。
  • ETag: W/"123dadwad3211wda"——两种资源可以被认为是相同的。

上次修改时间

指示内容最后修改的日期和时间。当内容过期时,服务器将使用 If-Modified-Since 标头发出带有最后修改日期的条件请求,然后服务器将使用该请求返回304 Not Modified或返回新的响应。

服务器

Last-Modified: Mon, 24 Mar 2021 11:15:30 GMT
Enter fullscreen mode Exit fullscreen mode

客户

If-Modified-Since: Mon, 24 Mar 2021 11:15:30 GMT
Enter fullscreen mode Exit fullscreen mode

问答

问:如果响应中同时存在两个标头会怎样?
答:参数 ETag 和 If-None-Match 以及 Last-Modified 和 If-Modified-Since 都被发送,服务器会检查这两个值以返回 304 Not Modified 或返回新内容。

问:如果响应中没有验证标头会怎样?
答:不会调用任何验证和刷新现有缓存的函数。一旦内容过期,就会立即请求新的内容。

缓存策略

由于它受许多因素的影响,因此没有统一的答案,但通常我们可以定义两个主要的缓存类别:

  1. 轻量级缓存 - 即 HTML。它被缓存,但客户端在使用前需要与服务器进行验证。通过使用它,我们可以确保客户端始终获取最新的 HTML,只要服务器上有可用的 HTML 文件。但如果 HTML 文件尚未更新,客户端可以避免下载,而是直接使用浏览器中缓存的文件。
Cache-Control: Private, no-cache
Enter fullscreen mode Exit fullscreen mode
  1. 积极缓存 - 例如 CSS、JavaScript、图像。通过以下示例,我们将这些文件长期缓存在公共缓存中。
Cache-Control: Public, max-age=23412213
Enter fullscreen mode Exit fullscreen mode

Nuxt.js

您可以使用 Vue.js 提供并由 Nuxt 适配的内置保持活动缓存机制来缓存非活动组件实例而不销毁它们。

https://nuxtjs.org/docs/features/nuxt-components/#keep-alive

浏览器缓存中间件

通过使用以下辅助函数作为 Nuxt 中间件,您可以Cache-Control为页面设置标题并相应地缓存内容。

// helpers/cacheControl.js

const cacheControl = (values) => ({ res }) => {
  if (!process.server) return;

  const cacheControlValue = Object.entries(values)
    .map(([key, value]) => `${key}=${value}`)
    .join(',');

  res.setHeader('Cache-Control', cacheControlValue);
};

export default cacheControl;
Enter fullscreen mode Exit fullscreen mode

然后,在您的某个页面中将此帮助程序用作中间件,如下所示:

// Home.vue

export default {
  name: 'Home',
  middleware: cacheControl({
    'max-age': 60,
    'stale-when-revalidate': 5
  }),
  ...
}
Enter fullscreen mode Exit fullscreen mode

SSR缓存

nuxt-ssr-cache 包

用于 nuxt 服务端渲染的缓存中间件。它支持各种缓存提供程序,例如 Redis、memcached 等。

  cache: {
    useHostPrefix: false,
    pages: [
      '/page1',
      '/page2',
    ],
    store: {
      type: 'memory',
      max: 100,
      ttl: 60,
    },
  },
Enter fullscreen mode Exit fullscreen mode

nuxt-perfect-cache

基于 Redis 的缓存中间件:

  • 便于使用
  • 在 redis 中缓存整个页面
  • 每个页面有单独的过期时间
  • API请求缓存

并且有许多配置选项供您尝试。

[
  'nuxt-perfect-cache',
  {
    disable: false,
    appendHost: true,
    ignoreConnectionErrors:false, //it's better to be true in production
    prefix: 'r-',
    url: 'redis://127.0.0.1:6379',
    getCacheData(route, context) {          
      if (route !== '/') {
        return false
      }
      return {
        key: 'my-home-page',
        expire: 60 * 60
      } // 1 hour
    }
  }
]
Enter fullscreen mode Exit fullscreen mode

组件缓存

组件缓存

用于组件级缓存的 Nuxt.js 包装器

{
  modules: [
    // Simple usage
    '@nuxtjs/component-cache',

    // With options
    ['@nuxtjs/component-cache', { maxAge: 1000 * 60 * 60 }],
  ]
}
Enter fullscreen mode Exit fullscreen mode

概括

做得好!现在,你应该更加了解缓存的概念以及如何充分利用它的潜力了。

奖励链接

文章来源:https://dev.to/jacobandrewsky/leveraging-cache-in-vuejs-and-nuxtjs-4b26
PREV
使用模块和 Pinia 构建 Nuxt 3 应用
NEXT
前端 Web 性能检查表