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 相关文章推荐
javascript 验证日期的函数
Mar 18 Javascript
js函数在frame中的相互调用详解
Mar 03 Javascript
一个奇葩的最短的 IE 版本判断JS脚本
May 28 Javascript
js实现div闪烁原理及实现代码
Jun 24 Javascript
JavaScript设计模式之代理模式介绍
Dec 28 Javascript
javascript设置和获取cookie的方法实例详解
Jan 05 Javascript
indexedDB bootstrap angularjs之 MVC DOMO (应用示例)
Jun 20 Javascript
js实现简单的网页换肤效果
Jan 18 Javascript
react实现点击选中的li高亮的示例代码
May 24 Javascript
在Vue methods中调用filters里的过滤器实例
Aug 30 Javascript
微信小程序公用参数与公用方法用法示例
Jan 09 Javascript
javascript条件式访问属性和箭头函数介绍
Nov 17 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
基于mysql的论坛(4)
2006/10/09 PHP
一个PHP操作Access类(PHP+ODBC+Access)
2007/01/02 PHP
迅速确定php多维数组的深度的方法
2014/01/07 PHP
ThinkPHP的常用配置选项汇总
2016/03/24 PHP
PHP5.6新增加的可变函数参数用法分析
2017/08/25 PHP
PHP实现微信对账单处理
2018/10/01 PHP
TP5框架实现一次选择多张图片并预览的方法示例
2020/04/04 PHP
[原创]提供复制本站内容时出现,该文章转自脚本之家等字样的js代码
2007/03/27 Javascript
javascript 面向对象全新理练之继承与多态
2009/12/03 Javascript
jquery中获得$.ajax()事件返回的值并添加事件的方法
2010/04/15 Javascript
js固定DIV高度,超出部分自动添加滚动条的简单方法
2013/07/10 Javascript
简介可以自动完成UI的AngularJS工具angular-smarty
2015/06/23 Javascript
AngularJS基础教程之简单介绍
2015/09/27 Javascript
理解js对象继承的N种模式
2016/01/25 Javascript
深入理解事件冒泡(Bubble)和事件捕捉(capture)
2016/05/28 Javascript
js 函数式编程学习笔记
2017/03/25 Javascript
基于node下的http小爬虫的示例代码
2018/01/11 Javascript
Auto.js自动收取自己和好友蚂蚁森林能量脚本
2018/06/28 Javascript
详解使用Next.js构建服务端渲染应用
2018/07/10 Javascript
js中null与空字符串""的区别讲解
2019/01/17 Javascript
javascript-hashchange事件和历史状态管理实例分析
2020/04/18 Javascript
[01:20:06]TNC vs VG 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
[57:59]完美世界DOTA2联赛循环赛 Ink Ice vs LBZS BO2第一场 11.05
2020/11/05 DOTA
代码讲解Python对Windows服务进行监控
2018/02/11 Python
Python 2.7中文显示与处理方法
2018/07/16 Python
Python反射和内置方法重写操作详解
2018/08/27 Python
使用python实现unix2dos和dos2unix命令的例子
2019/08/13 Python
使用matlab或python将txt文件转为excel表格
2019/11/01 Python
发现两个有趣的CSS3动画效果
2013/08/14 HTML / CSS
幼儿园托班开学寄语
2014/01/18 职场文书
信用卡结清证明怎么写
2014/09/13 职场文书
村主任群众路线个人对照检查材料
2014/09/26 职场文书
民用住房租房协议书
2014/10/29 职场文书
有限公司股东合作协议书
2014/10/29 职场文书
2015年项目经理工作总结
2015/04/30 职场文书
Java集成swagger文档组件
2021/06/28 Java/Android