宝哥软件园

谈解决VueJS SSR后端渲染内存泄漏的经验

编辑:宝哥软件园 来源:互联网 时间:2021-08-28

内存泄漏是最难调试的错误之一,因为内存泄漏是一个不可确定的问题,只有开发人员才能知道一块内存是否需要回收。另外,内存泄漏没有具体的错误消息,只能通过一定时间段的日志来判断是否存在内存泄漏。熟悉的调试工具对于排除内存泄漏是无用的。当然,除了专门用于排查内存泄漏的工具(抓取Heap等工具)之外。

对于不同的语言,有不同的方法来检查内存泄漏。对于JavaScript,不同平台的调试工具是不一样的。最常用的工具恐怕就是Chrome自带的sharp工具(无论是针对浏览器还是nodeJS),使用体验都不错,网上也有很多教程。

这次我要介绍的是内存泄漏的定位方法,不是工具的使用。是一些经验的总结,也就是我所知道的VueJS SSR中最容易发生内存泄漏的地方。如果你知道VueJS SSR中有更多的内存泄漏,可以在评论中留言告诉更多的人。

困难

遇到过VueJS SSR内存泄漏的朋友可能都知道,检查VueJS SSR的内存泄漏要比普通NodeJS和Browser平台麻烦得多。如果使用webpack-dev-server进行本地调试,会发现常用的内存泄漏工具并没有用,因为捕获的信息不仅包括VueJS SSR的进程信息,还包括webpack的进程信息,甚至webpack-dev-server的各种堆信息。当然,你可以通过各种方式过滤掉不相关的信息,只留下VueJS SSR的堆信息。

我在排查我们组项目内存泄漏的时候使用了各种常规工具,但最后发现VueJS SSR的内存泄漏很可能出现在以下几个地方,也就是说如果你恰好有VueJS SSR的内存泄漏问题,先不要使用内存泄漏排查工具,先从以下几个地方入手,看看有没有内存泄漏的逻辑。可能一针见血,节省时间。

可能发生泄漏的位置

在生命周期中创建/创建之前

下面是VueJS开发人员已经看过无数次的说明图。我也请大家再读一遍

在官方文件中,有这样一句话:

由于没有动态更新,在所有的生命周期挂钩中,只有在创建之前和创建之后才会在SSR期间被调用。这意味着其他生命周期挂钩(如beforeMount或Mount)中的任何代码都将只在客户端上执行。也就是说,和前端渲染一样,SSR也是有生命周期的,只不过SSR的生命周期中只存在beforeCreate和created。

因此,在Create和create之前,您需要首先检查组件中是否有任何泄漏内存的代码,或者它们是否调用了泄漏内存的代码。

在路线守卫那里

路由也是可能导致SSR内存泄漏的地方之一

与生命周期不同,所有路线守卫都在SSR中运行。他们都是分别的

每个before route前输入before route前的日期,每个before route后解析前的日期-首选项

还需要特别注意的是Date-prefetch,它容易出现内存泄漏代码。所谓的日期预取是一种自定义实现,它在SSR处预先获取第三方数据,用于绘图过程。

全球Mixin办公室

这个内存泄漏点想必大家都很熟悉,作者也详细阐述了github: GitHub的问题

简单地说,全局mixin会给每个Vue实例一个副本,而不是一个引用。

内存泄漏的例子

上面列举了一些可能发生内存泄漏的地方,那么什么样的代码会导致内存泄漏呢?网上有很多代码泄露的例子,我在这里介绍一些常见的泄露例子。

粗心导致的全局变量

function foo(arg) { bar='这是一个隐藏的全局变量';}上面的代码将顺利运行,但是bar的一个变量被意外声明。相当于:

function foo(arg) { window.bar='这是一个显式全局变量';}生成了全局变量window.bar

如果不手动回收,这个全局变量将一直存在内存中,不会被CG回收。积少成多,导致内存泄漏。

目前大家都在各种模块化环境下开发(CommonJS/AMD/CMD/等).),全局变量内存泄漏的问题基本消除。但是我们要提醒大家,由于JavaScript的各种特性,会出现很多意想不到的情况。当你迷茫的时候,可以试着从这些特征中发现问题。

被遗忘的计时器或回拨

请先看看下面的例子

var some resource=getData();setInterval(function(){ var Node=document . getelementbyid(' Node ');if(node) { //用node和someResource填充。node . innerhtml=JSON . stringify(some resource));}}, 1000);乍一看,没有问题。之后,如果从DOM中移除了Node node,因为上面的回调有对Node node的引用,Node Node将始终是内存驻留的,不会被CG回收。

为了避免上述问题,我们应该养成removeEventListener和clearInterval的习惯。

var some resource=getData();var interval=setInterval(function(){ var Node=document . getelementbyid(' Node ');if(node) { //用node和someResource填充。node . innerhtml=JSON . stringify(some resource));} else { //移除计时器清除间隔(interval);}}, 1000);又例如:

var元素=document . getelementbyid(' button ');函数OnClick(event){ element . innerHTMl=' text ';} element . addeventlistener(' click ',OnClick);//Do stuff element . removeeventlistener(' click ',onClick);element.parentNode.removeChild(元素);//现在,当元素超出范围时,//元素和onclick都将被收集,即使在旧浏览器中也不会//很好地处理循环。添加事件侦听器后,请记住移除事件侦听器

关闭

闭包导致的内存泄漏很复杂,很难找到。限于本文的主要观点,原则将不予解释。

摘要

个人认为VueJS SSR后端渲染的内存泄漏比普通VueJS前端的内存泄漏影响更大。

前端内存泄漏的影响发生在客户端,基本上现代浏览器也会做好保护机制,通常会在自刷新后解决。但是一旦后端绘图内存泄露导致停机,整个服务器都会受到影响,这就更危险了,年终奖也就没了。

前端工程师普遍关注浏览器端性能,开发过程中的内存泄漏问题不是很受关注,也不容易被发现。一般是项目上线一段时间后才发现内存泄漏。这时候重新开始,可能会有一些无法开始或者手忙脚乱的情况。

然后,我们来关注一下开发时的内存泄漏问题,干掉VueJS SSR后端渲染中的内存泄漏问题。

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

更多资讯
游戏推荐
更多+