Nuxt页面级缓存的实现


Posted in Javascript onMarch 09, 2020

虽然 Vue 的服务器端渲染 (SSR) 相当快速,但是由于需要为每次请求为了避免交叉请求状态污染,都创建一个新的根Vue实例,创建组件实例和虚拟 DOM 节点的开销,无法与纯基于字符串拼接的模板的性能相当。在 SSR 性能至关重要的情况下,明智地利用缓存策略,可以极大改善响应时间并减少服务器负载。同时还可以大大减少后端接口服务器的负载。

在 vue SSR指南 中,缓存有两种,分为页面级缓存和组件级缓存。本次讲的是页面缓存,如果内容不是用户特定的并且在相对较短时间内,页面内容不需要更新。我们就可以使用页面缓存。对于页面级缓存我们可以通过这段koa服务器的代码大概知道缓存的思路:

const microCache = LRU({
 max: 100,
 maxAge: 1000 // 重要提示:条目在 1 秒后过期。
})

const isCacheable = req => {
 // 实现逻辑为,检查请求是否是用户特定(user-specific)。
 // 只有非用户特定 (non-user-specific) 页面才会缓存
}

server.get('*', (req, res) => {
 const cacheable = isCacheable(req)
 if (cacheable) {
 const hit = microCache.get(req.url)
 if (hit) {
  return res.end(hit)
 }
 }

 renderer.renderToString((err, html) => {
 res.end(html)
 if (cacheable) {
  microCache.set(req.url, html)
 }
 })
})

流程图如下:

Nuxt页面级缓存的实现

上面的代码为vue的ssr渲染提供了方案,但是对于使用nuxt框架的同学而言,用脚手架初始化完,框架对于vue服务端渲染的res.end()函数做了高度封装,从下图nuxt在接收到请求后进行渲染的流程可以看出,nuxt主要是通过nuxtMiddleware调用renderRoute()来进行渲染的:

Nuxt页面级缓存的实现

那么我们是否可以通过重写renderRoute()这个api拦截其内部渲染逻辑,在渲染之前加上缓存呢? nuxt-ssr-cache 插件已经这样做了。我们来看一下这个nuxt模块核心部分的源码:

const renderer = nuxt.renderer;
const renderRoute = renderer.renderRoute.bind(renderer);
renderer.renderRoute = function(route, context) {
 // hopefully cache reset is finished up to this point.
 tryStoreVersion(cache, currentVersion);

 const cacheKey = (config.cache.key || defaultCacheKeyBuilder)(route, context);
 if (!cacheKey) return renderRoute(route, context);

 function renderSetCache(){
  return renderRoute(route, context)
   .then(function(result) {
    if (!result.error) {
     cache.setAsync(cacheKey, serialize(result));
    }
    return result;
   });
 }

 return cache.getAsync(cacheKey)
  .then(function (cachedResult) {
   if (cachedResult) {
    return deserialize(cachedResult);
   }

   return renderSetCache();
  })
  .catch(renderSetCache);
};

在这段代码中,先保存了renderer原来的renderRoute代码,之后又重写了renderRoute代码,返回了一个通过cache缓存来获取缓存内容的逻辑。cache返回了一个promise,如果是resolve的,并且有缓存的内容,就直接返回缓存内容。如果没有缓存内容或者reject,就执行renderSetCache()。而renderSetCache()中,返回了原来最初的renderRoute()处理逻辑,同样如果renderRoute()返回的promise被resolve了,那么就通过cache的setAsync方法来进行缓存,之后返回渲染结果。

使用方法大家自行参考git中的readme文档,这里就不说了。

下面我们真正来仿真一下,看看这个模块的功效到底如何。我们通过ab命令

ab -n 4000 -c 50 -s 120 -r http://localhost:3000/

来进行压测:

第一种情况,没有添加页面缓存,大约持续请求了10秒钟,执行到3600个请求的时候,发生错误,不再继续请求了:

Nuxt页面级缓存的实现

我们来通过日志看下是什么错误:

Nuxt页面级缓存的实现

可以看到FATAL ERROR这一句,JavaScript heap out of memory。堆内存已经没有办法再进行分配,所以进程终止了。

我们在终止之前通过进程监视器可以看到node进程已经彪到了1.7GB的内存。

Nuxt页面级缓存的实现

第二种情况,我们添加了页面缓存,通过server端的日志,我们可以看出,只请求了一次后端的api数据接口,说明缓存已经成功拦截了页面请求。请求数据如下:

Nuxt页面级缓存的实现

在2秒钟之内,就顺利结束了4000个请求,内存没有任何明显波动,优化效果显而易见。

到此这篇关于Nuxt页面级缓存的实现的文章就介绍到这了,更多相关Nuxt 页面级缓存内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
基于jQuery的动态增删改查表格信息,可左键/右键提示(原创自Zjmainstay)
Jul 31 Javascript
JQuery判断子iframe何时加载完成解决方案
Aug 20 Javascript
对jquery的ajax进行二次封装以及ajax缓存代理组件:AjaxCache详解
Apr 11 Javascript
js轮盘抽奖实例分析
Apr 17 Javascript
浅谈angular懒加载的一些坑
Aug 20 Javascript
快速理解 JavaScript 中的 LHS 和 RHS 查询的用法
Aug 24 Javascript
node.js操作MongoDB的实例详解
Oct 11 Javascript
JavaScript中set与get方法用法示例
Aug 15 Javascript
jQuery使用ajax传递json对象到服务端及contentType的用法示例
Mar 12 jQuery
JS中FormData类实现文件上传
Mar 27 Javascript
vue Element左侧无限级菜单实现
Jun 10 Javascript
vue pages 多入口项目 + chainWebpack 全局引用缩写说明
Sep 21 Javascript
JavaScript设计模式之门面模式原理与实现方法分析
Mar 09 #Javascript
微信小程序自定义纯净模态框(弹出框)的实例代码
Mar 09 #Javascript
前端深入理解Typescript泛型概念
Mar 09 #Javascript
js实现无缝轮播图效果
Mar 09 #Javascript
js实现无缝轮播图
Mar 09 #Javascript
基于vue+echarts 数据可视化大屏展示的方法示例
Mar 09 #Javascript
原生js实现瀑布流效果
Mar 09 #Javascript
You might like
Search Engine Friendly的URL设计
2006/10/09 PHP
在PHP中养成7个面向对象的好习惯
2010/01/28 PHP
完美解决在ThinkPHP控制器中命名空间的问题
2017/05/05 PHP
PHP使用Nginx实现反向代理
2017/09/20 PHP
动态加载iframe
2006/06/16 Javascript
Extjs在exlipse中设置自动提示的方法
2010/04/07 Javascript
3Z版基于jquery的图片复选框(asp.net+jquery)
2010/04/12 Javascript
js异步加载的三种解决方案
2013/03/04 Javascript
html+css+js实现xp window界面及有关功能
2013/03/26 Javascript
js实现有时间限制消失的图片方法
2015/02/27 Javascript
JavaScript编写连连看小游戏
2015/07/07 Javascript
谈谈JavaScript的New关键字
2016/08/26 Javascript
EasyUI 中combotree 默认不能选择父节点的实现方法
2016/11/07 Javascript
AngularJS过滤器filter用法总结
2016/12/13 Javascript
jquery,js简单实现类似Angular.js双向绑定
2017/01/13 Javascript
AngularJS学习第一篇 AngularJS基础知识
2017/02/13 Javascript
vue+vuex+axios+echarts画一个动态更新的中国地图的方法
2017/12/19 Javascript
基于jQuery ztree实现表格风格的树状结构
2018/08/31 jQuery
浅谈webpack 四个核心概念之Entry
2019/06/12 Javascript
vue监听用户输入和点击功能
2019/09/27 Javascript
[49:05]Newbee vs TNC 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
python利用datetime模块计算时间差
2015/08/04 Python
以视频爬取实例讲解Python爬虫神器Beautiful Soup用法
2016/01/20 Python
基于Python如何使用AIML搭建聊天机器人
2016/01/27 Python
Python基于回溯法子集树模板解决马踏棋盘问题示例
2017/09/11 Python
Python实现PS滤镜特效Marble Filter玻璃条纹扭曲效果示例
2018/01/29 Python
python实现对文件中图片生成带标签的txt文件方法
2018/04/27 Python
python写文件时覆盖原来的实例方法
2020/07/22 Python
HTML5 Canvas 实现圆形进度条并显示数字百分比效果示例
2017/08/18 HTML / CSS
html5默认气泡修改的代码详解
2020/03/13 HTML / CSS
仓库管理员岗位职责
2014/03/19 职场文书
一般基层干部群众路线教育实践活动个人对照检查材料
2014/11/04 职场文书
自荐信格式模板
2015/03/27 职场文书
2015年办公室人员工作总结
2015/05/15 职场文书
导游词之云南丽江古城
2019/09/17 职场文书
Python 流媒体播放器的实现(基于VLC)
2021/04/28 Python