热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

nuxt.js缓存实践

这篇文章主要介绍了nuxt.js缓存实践,nuxt的缓存可以分为组件级别缓存,API级别缓存以及页面级别缓存,本文就详细的介绍了这三种缓存,感兴趣的小伙伴们可以参考一下

nuxt 是基于 vue 的 ssr 解决方案,可以是使用vue语法完成前后端的同构。

然而在与传统纯字符串拼接的 ssr 方案相比,性能就没那么好了, nuxt 需要在服务端生成虚拟 dom ,然后再序列化出HTML字符串,我们常说 nodejs 的高性能指的是异步IO操作频繁的场景而非CPU操作密集的场景,毕竟 nodejs 是运行在单线程下的,在涉及到高并发的场景下,性能就会有所下降,可以考虑采用合理的缓存策略

nuxt 的缓存可以分为 组件级别缓存 , API级别缓存 以及 页面级别缓存

组件级别的缓存

配置项 nuxt.config.js 的配置大概长这样子:

const LRU = require('lru-cache')
module.exports = {
 render: {
  bundleRenderer: {
   cache: LRU({
    max: 1000,           // 最大的缓存个数
    maxAge: 1000 * 60 * 15    // 缓存15分钟
   })
  }
 }
}

并不是说配了该项就实现了组件级别的缓存,还需要在需做缓存的 vue 组件上增加 name 以及 serverCacheKey 字段,以确定缓存的唯一键值,比如:

export default {
 name: 'AppHeader',
 props: ['type'],
 serverCacheKey: props => props.type
}

上述组件会根据父组件传下来的 type 值去做缓存,键值是: AppHeader::${props.type} ,由此,新的请求到来时,只要父组件传下来的 type 属性之前处理过,就可以复用之前的渲染缓存结果,以增进性能

从该例子可以看出,如果该组件除了依赖父组件的 type 属性,还依赖于别的属性, serverCacheKey 这里也要做出相应的改变,因此,如果组件依赖于很多的全局状态,或者,依赖的状态取值非常多,意味需要缓存会被频繁被设置而导致溢出,其实就没有多大意义了,在 lru-cache 的配置中,设置的最大缓存个数是1000,超出部分就会被清掉

其次,不应该缓存可能对渲染上下文产生副作用的子组件,比如,组件的 created beforeCreated 的钩子在服务端也会走,组件被缓存后就不会执行了,这些可能影响到渲染上下文的地方也要小心,更多内容请参考:组件级别缓存

一般来说,比较适合的场景是 v-for 大量数据的渲染,因为循环操作比较耗cpu

API级别的缓存

在服务端渲染的场景中,往往会将请求放在服务端去做,渲染完页面再返回给浏览器,而有些接口是可以去做缓存的,比如,不依赖登录态且不依赖过多参数的接口或者是单纯获取配置数据的接口等,接口的处理也是需要时间的,对接口的缓存可以加快每个请求的处理速度,更快地释放掉请求,从而增进性能

api的请求使用 axios , axios 即可以在服务端使用也可是在浏览器使用,代码大概长这样子

import axios from 'axios'
import md5 from 'md5'
import LRU from 'lru-cache'

// 给api加3秒缓存
const CACHED = LRU({
 max: 1000,
 maxAge: 1000 * 3
})

function request (config) {
 let key
 // 服务端才加缓存,浏览器端就不管了
 if (config.cache && !process.browser) {
  const { params = {}, data = {} } = config
  key = md5(config.url + JSON.stringify(params) + JSON.stringify(data))
  if (CACHED.has(key)) {
   // 缓存命中
   return Promise.resolve(CACHED.get(key))
  }
 }
 return axios(config)
  .then(rsp => {
   if (config.cache && !process.browser) {
    // 返回结果前先设置缓存
    CACHED.set(key, rsp.data)
   }
   return rsp.data
  })
}

使用上跟平时使用 axios 还是一样的,就多加了个 cache 的属性标识是否需要在服务端做缓存

const api = {
 getGames: params => request({
  url: '/gameInfo/gatGames',
  params,
  cache: true
 })
}

页面级别的缓存

在不依赖于登录态以及过多参数的情况下,如果并发量很大,可以考虑使用页面级别的缓存, 在 nuxt.config.js 增加 serverMiddleware 属性

const nuxtPageCache = require('nuxt-page-cache')

module.exports = {
 serverMiddleware: [
  nuxtPageCache.cacheSeconds(1, req => {
   if (req.query && req.query.pageType) {
    return req.query.pageType
   }
   return false
  })
 ]
}

上面的例子根据链接后面的参数 pageType 去做缓存,如果链接后面有 pageType 参数,就做缓存,缓存时间为1秒,也就是说在1秒内相同的 pageType 请求,服务端只会执行一次完整的渲染

nuxt-page-cache 参考了route-cache ,写得比较简陋,你也可以重新封装下,nuxt最终返回数据是使用 res.end(html, 'utf-8') ,页面级别的缓存大概的思想如下:

const LRU = require('lru-cache')

let cacheStore = new LRU({
 max: 100,     // 设置最大的缓存个数
 maxAge: 200
})

module.exports.cacheSecOnds= function (secondsTTL, cacheKey) {
 // 设置缓存的时间
 const ttl = secondsTTL * 1000
 return function (req, res, next) {
  // 获取缓存的key值
  let key = req.originalUrl
  if (typeof cacheKey === 'function') {
   key = cacheKey(req, res)
   if (!key) { return next() }
  } else if (typeof cacheKey === 'string') {
   key = cacheKey
  }

  // 如果缓存命中,直接返回
  const value = cacheStore.get(key)
  if (value) {
   return res.end(value, 'utf-8')
  }

  // 缓存原先的end方案
  res.original_end = res.end

  // 重写res.end方案,由此nuxt调用res.end实际上是调用该方法,
  res.end = function () {
   if (res.statusCode === 200) {
    // 设置缓存
    cacheStore.set(key, data, ttl)
   }
   // 最终返回结果
   res.original_end(data, 'utf-8')
  }
 }
}

如果缓存命中,直接将原先的计算结果返回,大大提供了性能

总结

在高并发的情况下可以考虑使用缓存,而缓存策略的使用需要视场景而定,这里不再赘述,还可以考虑使用pm2开启集群模式去管理我们的进程,从而满足更高的并发。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 利用树莓派畅享落网电台音乐体验
    最近重新拾起了闲置已久的树莓派,这台小巧的开发板已经沉寂了半年多。上个月闲暇时间较多,我决定将其重新启用。恰逢落网电台进行了改版,回忆起之前在树莓派论坛上看到有人用它来播放豆瓣音乐,便萌生了同样的想法。通过一番调试,终于实现了在树莓派上流畅播放落网电台音乐的功能,带来了全新的音乐享受体验。 ... [详细]
  • 利用Flask框架进行高效Web应用开发
    本文探讨了如何利用Flask框架高效开发Web应用,以满足特定业务需求。具体案例中,一家餐厅希望每天推出不同的特色菜,并通过网站向顾客展示当天的特色菜。此外,还增加了一个介绍页面,在bios路径下详细展示了餐厅主人、厨师和服务员的背景和简介。通过Flask框架的灵活配置和简洁代码,实现了这一功能,提升了用户体验和餐厅的管理水平。 ... [详细]
  • 在遍历集合的过程中,若需根据特定条件对集合进行修改操作,如添加或删除元素,应特别注意避免引发 `ConcurrentModificationException` 异常。例如,在当前场景中,当集合中的对象ID与另一个集合中的对象ID不匹配时,需要向集合中添加新元素。为了避免这一异常,建议使用迭代器的 `remove` 方法或采用线程安全的集合类型,如 `CopyOnWriteArrayList`,以确保操作的安全性和一致性。 ... [详细]
  • 为了实现跨浏览器兼容的禁用文本选择功能,可以通过在全局CSS样式中定义一个特定的类来禁止用户选中文本。具体做法是在全局样式表中添加一个名为 `.no-select` 的类,并在需要禁用文本选择的元素上应用该类。这样可以确保在不同浏览器中都能达到一致的效果。此外,还可以结合JavaScript进一步增强用户体验,例如在某些交互场景下动态启用或禁用文本选择功能。 ... [详细]
  • 本文全面解析了 gRPC 的基础知识与高级应用,从 helloworld.proto 文件入手,详细阐述了如何定义服务接口。例如,`Greeter` 服务中的 `SayHello` 方法,该方法在客户端和服务器端的消息交互中起到了关键作用。通过实例代码,读者可以深入了解 gRPC 的工作原理及其在实际项目中的应用。 ... [详细]
  • vtkGlyph3D 是一种强大的符号化可视化工具,能够将三维数据集中的每个点用预定义的几何图形(如球体或箭头)进行表示。该工具不仅支持自定义符号的方向和缩放比例,还能够在复杂的数据场中突出显示关键特征,从而提高数据的可解释性和可视化效果。通过这种方式,用户可以更直观地理解和分析三维数据集中的重要信息。 ... [详细]
  • HDU1176:免费馅饼问题的动态规划解法分析
    题目“免费馅饼”通过动态规划方法进行了解析。该问题的时间限制为 Java 2000ms 和其他语言 1000ms,内存限制为 Java 65536K 和其他语言 32768K。本文详细探讨了如何利用动态规划算法高效求解此问题,并对算法的时间复杂度和空间复杂度进行了深入分析。此外,还提供了具体的实现步骤和代码示例,帮助读者更好地理解和应用这一方法。 ... [详细]
  • 在处理遗留数据库的映射时,反向工程是一个重要的初始步骤。由于实体模式已经在数据库系统中存在,Hibernate 提供了自动化工具来简化这一过程,帮助开发人员快速生成持久化类和映射文件。通过反向工程,可以显著提高开发效率并减少手动配置的错误。此外,该工具还支持对现有数据库结构进行分析,自动生成符合 Hibernate 规范的配置文件,从而加速项目的启动和开发周期。 ... [详细]
  • CAS 机制下的无锁队列设计与实现 ... [详细]
  • 2016-2017学年《网络安全实战》第三次作业
    2016-2017学年《网络安全实战》第三次作业总结了教材中关于网络信息收集技术的内容。本章主要探讨了网络踩点、网络扫描和网络查点三个关键步骤。其中,网络踩点旨在通过公开渠道收集目标信息,为后续的安全测试奠定基础,而不涉及实际的入侵行为。 ... [详细]
  • 概率与期望动态规划的深入探讨与应用分析
    本文深入探讨了概率与期望动态规划的基本原理及其在实际问题中的应用。概率是指某一事件发生的可能性大小,用P(A)表示。若某一事件的所有可能结果共有n种,且每种结果出现的概率相等,而事件A包含其中的m种结果,则该事件的概率P(A)为m/n。例如,在投掷骰子的情况下,如果事件A定义为掷出偶数点,由于共有3种偶数点(2、4、6),而总共有6种可能的结果,因此P(A)为1/2。文章进一步分析了概率与期望动态规划在复杂场景下的建模方法和求解策略,并通过具体实例展示了其在决策优化和风险管理中的应用价值。 ... [详细]
  • 本文详细介绍了 Windows API 中的按钮控件及其应用实例。主要功能包括:1. `CheckDlgButton` 用于更改对话框中按钮的选中状态;2. `CheckRadioButton` 用于设置单选按钮的选中状态。此外,还探讨了按钮控件在实际开发中的多种应用场景,帮助开发者更好地理解和使用这些功能。 ... [详细]
  • 计算机图形学基础:辐照度学原理与应用综述
    辐照度(irradiance)是指单位面积上接收到的电磁辐射功率,可视为入射点处的能量密度。在计算机图形学领域,辐照度计算是确定场景中每个位置光照效果的关键步骤。通过对辐照度的精确建模,可以实现更加逼真的光照渲染,提升视觉效果的真实感和沉浸感。本文综述了辐照度的基本原理及其在计算机图形学中的多种应用,探讨了当前研究的热点和技术挑战。 ... [详细]
  • 采购订单条件类型配置的开发流程详解
    为了满足采购业务的需求,需开发新的价格类型。首先,在SPRO配置中定位到相应的配置节点,创建新的条件类型“ZMM00”。接着,创建定价过程“ZMM003”。具体步骤包括:1. 配置条件类型;2. 设置定价过程。此外,还需确保新条件类型与现有系统中的其他模块兼容,以保证整体业务流程的顺畅运行。 ... [详细]
  • 如何在CAD阅图软件中将PDF文件高效转换为CAD格式?
    如何在CAD阅图软件中将PDF文件高效转换为CAD格式? ... [详细]
author-avatar
秋秋
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有