近期比较忙,也遇到了很棘手的问题,vue ssr 内存泄漏,一直找不到问题根源,目前项目慢慢稳定下来,内存也维持在正常水平,通过alinode监测内存情况表现正常(由于我的服务器上部署了多个项目,维持在60%是正常状态): ce’。
服务端渲染除了需要了解基本原理之外,需要特别注意性能问题,起初将 DoraCMS2.0 部署到阿里云服务器上(内存1G),过了一晚上跑到300多M,很明显的内存泄漏了,之前也有考虑过ssr是否适合内容比较多的应用,也有想过是否改架构,但作为vue ssr实践,有必要去了解下哪些地方会引起内存问题。
1、合理使用缓存。vue ssr 官方案例中用到了lru-cache,以缓解性能方面的问题,要知道lru-cache缓存数据都是存内存的,需要合理使用,原则上讲缓存静态内容,经常变动频繁的内容最好不要缓存。
2、axios 的使用。axios 允许客户端和服务端发起请求,但是使用不当也会造成内存泄漏,在vue ssr项目中,可以考虑将axios封装一下,针对不同环境进行调用,具体用法可以参考下面的文章。 Vue2 SSR 缓存 Api 数据
3、合理使用 v-once 。官网介绍如下:
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。一般用在
渲染数据比较多的列表,而且内容不会经常变动。
<!-- 单个元素 -->
<span v-once>This will never change: {{msg}}</span>
<!-- 有子元素 -->
<div v-once>
<h1>comment</h1>
<p>{{msg}}</p>
</div>
<!-- 组件 -->
<my-component v-once :comment="msg"></my-component>
<!-- v-for 指令-->
<ul>
<li v-for="i in list" v-once>{{i}}</li>
</ul>
我在几个组件用到了该标签:
header,footer,topicItem等
<el-col v-for="(nav,index) in headerNav" :key="index" v-once>
<router-link :to="{path: '/'+nav.defaultUrl+ '___'+nav._id}">{{nav.name}}</router-link>
</el-col>
4、合理使用keep-alive。主要用于保留组件状态或避免重新渲染。要知道,重复渲染数据量大的列表代价很大。 5、vue ssr 中的 runInNewContext 属性(2.3.1+)。官方解释非常详细了:
默认情况下,对于每次渲染,bundle renderer 将创建一个新的 V8 上下文并重新执行整个 bundle。这具有一些好处 - 例如,应用程序代码与服务器进程隔离,我们无需担心文档中提到的状态单例问题。然而,这种模式有一些相当大的性能开销,因为重新创建上下文并执行整个 bundle 还是相当昂贵的,特别是当应用很大的时候。 出于向后兼容的考虑,此选项默认为 true,但建议你尽可能使用 runInNewContext: false 或 runInNewContext: 'on https://ssr.vuejs.org/zh/api.html#runinnewcontext
原文地址: vue ssr 性能问题分析
最后 vue ssr 内存泄露的地方是哪里呢?
来自酷炫的 CNodeMD
之前通过chrome 的 memory 工具 并没有分析出什么原因,因为几个内存产生多,释放少的地方都是dom渲染数据列表的地方,通过loadtest压测rps个位数,没办法使用排查法和可能出现的地方进行优化,关键总结了以上几点,另外 runInNewContext 这个地方比较重要,重新压测问题得到缓解。
性能没问题,我的SSR博客在一核一G阿里云上能压出100的QPS,并且没上API缓存(我觉得没到性能瓶颈做这件事纯粹是吃饱了撑的只为QPS好看而已),也还没用vue2.4.0的字符串模板(按手上的压测数据目测能压到110QPS), 内存泄漏两个点,一个是axios拦截器泄漏,一个是SSR端的vue.mixin({})的泄漏,然而它俩也不是什么大事,两者的泄漏均是预期之内的行为,具体解释在这