nuxt 添加 redis 缓存

news/2025/1/10 21:05:55/文章来源:https://www.cnblogs.com/limoonrise/p/18640801

这个文章的主要目的是通过 redis 缓存 nuxt2 中服务端渲染的页面。从而优化加载速度以及减轻服务端的压力。

Nuxt

是什么

Nuxt.js 是一个基于 Vue.js 的开源框架,旨在为开发者提供一个简单的方式来构建高性能的 Vue 应用。它提供了许多功能,使得开发服务器端渲染(SSR)、静态站点生成(SSG)和单页面应用(SPA)变得更加容易。nuxt2官网、nuxt3的地址

Redis

是什么

Redis 是一个开源的内存数据结构存储系统,广泛用于数据库、缓存和消息代理。它支持多种数据结构,如字符串、哈希、列表、集合和有序集合。它具有高性能的特性,可以处理每秒数百万个请求,具有极高的读写性能。通常会被我们使用在缓存的存储中,提高应用程序的响应速度。Redis的官网

前期准备

首先我们本地开发的时候,本地要先安转 redis。下载后,终端运行 redis-server 既可开启 Redis 服务。开启后终端中就能看到这个图标。

# 开启 redis-server
redis-server
# 打开 redis cli
redis-cli

Nuxt 通过 Redis 添加缓存

开始

首先我们要有一个 nuxt 项目,这里我新建一个项目,如果原先有项目,也可以直接在原项目中进行。通过官方文档,建立一个新的项目。

# npm
npm init nuxt-app nuxt2

然后就是下载依赖,选择所需框架。最后 cd nuxt2 ,执行 npm run dev 跑起来。

下载 Node Redis

npm install redis@3

这里我们下载 redis npm 包,我们这里用的nuxt2,所以这里指定版本下载的是 redis@3redis@3 的文档可以看这个(https://www.npmjs.com/package/redis/v/3.1.2)。

在根目录下创建一个 cache 目录文件,用来存储 redis 相关配置。

// cache > index.js
const redis = require('redis')const client = redis.createClient(6379, '127.0.0.1')client.on('error', function(error) {console.error('redis error:', error)
})// 封装 get、set
function getRedis(key, callback) {client.get(key, callback)
}function setRedis(key, value, timeout = 60*60) {client.set(key, value, redis.print)// 设置超时时间client.expire(key, timeout)
}export {getRedis,setRedis
}

通过 redis 的文档可以看到,get [key] 的时候会传进一个回调函数,用来获取错误信息或对应的 value

redis@3 目前不支持原生 Promise,这一个功能会在 v4 版本中推出。但是文档中给出了包装成 promise 的方法,利用的是 util.promisify 方法。具体的文档位置

// 文档中的 promise 包装例子
const { promisify } = require('util')
const getAsync = promisify(client.get).bind(client)getAsync.then(console.log).catch(console.error)

在进行下一步之前,我们可以将 redis 的相关配置提取出来,可以在 cache 中创建一个 _config.js 文件,用来存储配置相关。而 redis.createClient 方法的相关配置,可以查看文档位置

// cache > _config.js
let redisConfig = {post: 6379,host: '127.0.0.1'
}// production 判断,redisConfig = { ... }module.exports = {redisConfig
}

index 中修改

const { redisConfig } = require('./_config')// 修改部分
// - const client = redis.createClient(6379, '127.0.0.1')
const client = redis.createClient(redisConfig.post, redisConfig.host)

写中间件

redis 相关封装完毕后,我们就可以来写中间件了。首先在根目录创建 middleware 文件夹,用来存储所有的中间件。在 nuxt 中,中间件有 middlewareserverMiddleware 。他们是两个完全不同的概念。

middleware

middleware 一般用于 页面 与 路由 之间执行的函数,可以用来处理用户请求前的逻辑。一般用来进行 身份验证、用户权限判断、重定向用户、数据预处理等 。适用于 客户端 与 服务端。

serverMiddleware

serverMiddleware 则是用于服务器端运行的中间件,用来处理 HTTP 请求。所以他用来 处理 API 请求、处理文件上传、或者是其他自定义的服务器逻辑。他运行在服务器接收到请求时执行。

两者的写法

// middleware
export default function ({ store, redirect }) {// ...
}// serverMiddleware
export default function (req, res, next) {// ...next()
}

cache 中间件

我们来写 cache 中间件,在 middleware 文件夹中创建一个 cache.js 文件。

这里为了区别 serverMiddleware 和 middleware。可以在 middleware 中创建 server,然后在 server 中创建 cache.js。也有在根目录中创建 server > middleware > [servermiddleware].js 的。都是可以的。

// middleware > cache.js
import { getRedis, setRedis } from '../cache'export default function (req, res, next) {const reg = /.(js|css|png|json)$/gconst useCache = !reg.test(req.url)if (useCache) {const redisKey = `PN:PAGE:${req.url}`getRedis(redisKey, function(err, val) {if (err) next()else cacheMain(redisKey, val, req, res, next)})} else {next()}
}function cacheMain(key, val, req, res, next) {if (val) {// 有缓存res.end(val, 'utf-8')} else {// 没有缓存,存缓存,并且返回res.origin_end = res.endres.end = (data) => {if (res.statusCode === 200) {// 写入setRedis(key, data)}}res.origin_end(data, 'utf-8')}next()
}

然后我们在 nuxt.config.js中配置 serverMiddleware

// nuxt.config.js
export default {// ... 其他配置serverMiddleware: ['~/middleware/cache.js']
}

验证

这时我们在浏览器访问 localhost:3000,然后在终端 redis-cli 中查看 keys *,可以看到已经存在相关数据。get [key],即可得到我们的页面数据。

keys *
get [key]

这里我们也可以创建多个页面进行验证,在 pages 目录下创建一个 m.vue 文件,浏览器再访问 location:3000/m

<!-- pages > m.vue -->
<template><div><p style="color: blue;">移动端页面</p></div>
</template>

这时我们可以看到 keys * 中有两条数据。

超时检测,这个可以调小 timeout ,比如设置成 60s 来进行测试。

至此,我们已经完成了对页面的缓存。

缓存优化

存储内容

目前我们存储在 redis 中的页面数据是整个 html 文件。当前我初始化的项目的页面内容比较少,但是如果是一个正式上线的项目,页面渲染的内容就不一定是简单的内容展示了。所以这里我们来对缓存内容进行优化,缓存前进行压缩,读取后进行解压处理。

数据压缩和解压的库这里我选择用 zlib,他对比与 pako,更适用于服务器端。

# 安装 zlib
npm i zlib

下载完后再 cache 目录下创建 zlib.js 文件,首先我们先写一段代码测试下 zlib 的压缩和解压功能。

const zlib = require('zlib')
const str = 'hello, zlib'let compressData
zlib.deflate(Buffer.from(str), (err, end) => {console.log(err, end.toString('base64'), 'deflate')compressData = end.toString('base64')
})setTimeout(() => {zlib.inflate(Buffer.from(compressData, 'base64'), (err, data) => {console.log(err, data.toString(), 'inflate')})
}, 1000)

测试可以看出加压和解压的功能是可行的,接下来就是对加压和解压功能做封装处理。

// cache > zlib.js
const zlib = require('zlib')/*** 压缩* @param {*} string*/
function compress(string) {return new Promise((resolve, reject) => {const buffer = Buffer.from(string)zlib.deflate(buffer, (err, compressData) => {if (err) { reject(err) }else {resolve(compressData.toString('base64'))}})})
}/*** 解压* @param {*} compressData*/
function decompress(compressData) {return new Promise((resolve, reject) => {const buffer = Buffer.from(compressData, 'base64')zlib.inflate(buffer, (err, decompressData) => {if (err) { reject(err) }else {resolve(decompressData.toString())}})})
}export {compress,decompress
}

同时 middleware 中的 cache.js 要引入并使用相关方法。

// middleware > cache.js
import { compress, decompress } from "../cache/zlib"function cacheMain(val, key, req, res, next) {if (val) {// 有缓存,直接获取缓存数据decompress(val).then(decompressRes => {res.end(decompressRes, 'utf-8')}).catch(err => {console.error(err)})} else {// 没有缓存,通过 res.end 获取页面数据res.original_end = res.endres.end = (data) => {if (res.statusCode === 200) {// 修改位置setRedisCache(key, data)}res.original_end(data, 'utf-8')}
}function setRedisCache(key, data) {// setRedis(key, data)compress(data).then(res => {setRedis(key, res)}).catch(() => {// 压缩失败return false})
}

配置完上面的数据,我们重新运行可以项目是可以正常运行的,页面也没有异常。我们的验证重心要放在 redis 中存储的数据。在进行验证之前,我们先查看一下当前存储的页面数据大小。通过 memory usage [key] 查看。我本地的 / 页的大小是:

随后我们进行数据压缩存储,通过 get [key] 可以看出,redis 中存储的数据已经变成了 base64 格式。同时我们查看数据大小也已经发生了改变。

缓存时间

完成页面内容压缩后,我们再从缓存时间来找一下优化点。目前项目中的页面都是统一缓存时间。但是页面被访问的次数并不一定是一致的。有时我们就想,如果在页面缓存过期时间内,页面被多次访问,或到达一定的访问次数,页面缓存过期时间就跟着叠加。这个功能实现起来不难,主要是我们要去记录这个访问次数以及如何去记录这个访问次数。

目前我们 redis 中记录的内容是压缩后的 page 内容。我们可以修改这个存储内容,将存储信息变成一个对象,里面存储着访问次数,page 内容等。

const needCacheData = {content: pageData,accessCount: 1
}

然后存储的时候压缩 JSON.stringify(needCacheData),取值的时候获取 needCacheData.content,访问次数则是 accessCount。

// middleware > cache.js
function cacheMain(val, key, req, res, next) {if (val) {decompress(val).then(decompressRes => {// 修改位置,这里的 decompressRes 不是 pageContent 了,而是 { accessCount, content }const cacheData = JSON.parse(decompressRes)if (cacheData.accessCount === 1) {// 更新缓存cacheData.accessCount++setRedisCache(key, cacheData)}res.end(cacheData.content)})} else {// ... 其他代码// 修改部分res.end = (data) => {// 写入缓存前初始化缓存数据const cacheData = {accessCount: 1,content: data}setRedisCache(key, cacheData)}}
}// setRedisCache 第二个参数改成 obj
function setRedisCache(key, obj) {// 初始化let expire = 60 * 60if (data.accessCount !== 1) {expire = 24 * 60 * 60}compress(JSON.stringify(data)).then(res => {setRedis(key, res, expire)}).catch(err => {// ...})
}

这里的 expire 超时可以按照自己的需求设置。例如 accessCount 次数到达多少次后再加长时间等。至于验证的话,第一次访问的时候,可以通过 TTL [key] 查看当前时间,二次访问后再看过期时间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/861325.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自定义开关(switch)

演示代码 <!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>custom_switch</title><…

鸿蒙ArkUI-X简介

ArkUI是一套构建分布式应用的声明式UI开发框架。它具备简洁自然的UI信息语法、丰富的UI组件、多维的状态管理,以及实时界面预览等相关能力,帮助您提升应用开发效率,并能在多种设备上实现生动而流畅的用户体验。 ArkUI-X进一步将ArkUI扩展到了多个OS平台:目前支持OpenHarmon…

腾讯云 AI 代码助手:从 0 到 1 打造自己的专属产品网页

手把手教零基础前端小白运用腾讯云 AI 代码助手,从 0 到 1 打造自己的专属产品网页:手把手教零基础前端小白运用腾讯云 AI 代码助手,从 0 到 1 打造自己的专属产品网页: 安装腾讯云 AI 代码助手 在开始编码之前:我在IDE插件市场搜索腾讯云AI 代码助手,本教程以在 Visual …

【日记】明年或许会是非常重要的一年(1231 字)

正文时间紧迫,简单写写。今天下午全国上下计划财务处条线的人都加班。从 14:30 开始,一直等通知到 15:30 多才开始做,说是系统只开放到 17:00,但是因为找数据、找会计科目、计算会计等式、冲账这一套下来挺花时间也蛮难的,所以我们折腾到了 16:30 左右才搞完。部分支行还涉…

《HarmonyOS第一课》焕新升级,赋能开发者快速掌握鸿蒙应用开发

随着HarmonyOS NEXT发布,鸿蒙生态日益壮大,广大开发者对于系统化学习平台和课程的需求愈发强烈。近日,华为精心打造的《HarmonyOS第一课》全新上线,集“学、练、考”于一体,凭借多维融合的教学模式与系统课程设置,助力开发者快速掌握HarmonyOS应用开发技能。四大课程模块…

【密码学】RSA的攻击方法总结

总结一下收集到的RSA的所有攻击方法。 一、RSA的前世今生 RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。RSA是1977年由罗纳德李维斯特(Ron Rivest)、阿迪萨莫尔(Adi Shamir)和伦纳德阿德曼(Leonard Adleman)一起提出的。RSA就是他们三人姓…

manim边学边做--改变动画速度

ChangeSpeed类是Manim库中用于修改动画速度的类。 它提供了一种灵活的方式来控制动画的播放速度,使动画在不同时间段内以不同的速度播放,从而创造出更加丰富多样的动画效果。 比如,在创建包含多个元素动画的场景中,通过ChangeSpeed可以精确控制不同元素在不同时间点的移动速…

进程间通信组件ZeroMQ详解

在一些复杂的项目中,往往会由不同功能的程序组成,且在程序运行期间,各个程序还需要进行互相通信,实现进程间通信的方式有很多种,最常用的就是通过消息中间件,比如RabbitMQ,Kafaka,以及ZeroMQ等,而RabbitMQ和Kafaka这两款中间件往往都需要独立安装步骤才能使用,ZeroMQ…

Mongodb安装步骤 (.msi安装方式)

我之前发的Mongodb安装步骤 ,被人建议使用 .msi安装方式 所以重新发一版 Mongodb安装步骤 (.msi安装方式) 一、首先下载安装程序 下载链接 Try MongoDB Community Edition | MongoDB 选择 .msi 二、安装 1、双击.msi 2、next: 3、勾选接受,next: 4、complete是默认安装…

[Windows] 数据恢复软件R-Studio 8.14.179623

R-Studio是一个功能强大、节省成本的反删除和数据恢复软件系列。它采用独特的数据恢复新技术,为恢复FAT12/16/32、NTFS、NTFS5(由 Windows 2000/XP/2003/Vista/Windows 8/Windows 10创建或更新)、Ext2FS/Ext3FS(OSX LINUX 文件系统)以及 UFS1/UFS2(FreeBSD/OpenBSD/NetBS…

期末考试

每日总结管理系统: 此软件的主要用户包括学生、小组长、教师;各个用户主要功能为: (1)学生:写日报,修改日报,浏览日报、查询个人日报,查看站内消息。 (2)小组长:日报形式审核,发表情况统计,日报消息,查询日报。 (3)教师:日报评分,发表情况统计,日报消息,查…

【转载】什么是Banner以及测试时需要注意的点

设计中的banner图和测试中的banner图大家好,我是莫宁。相信很多新手小白在近几年也有听说过“banner”吧,是不是很疑惑。反正莫宁刚入门的时候是对这个词很陌生,不知道什么。今天就来为各位小伙伴解答这个疑问吧!什么是Banner?大家都知道“banner”翻译过来是横幅的意思,…