基于nw.js架构的客户端卡死的解决方法

最近基于nw.js的一个客户端遇到一个很奇怪的问题,就是在有的用户电脑上客户端会出现卡死的现象,必须结束进程重新打开客户才正常,有时候会反复尝试几次才可以。现在将解决的过程记录如下:

尝试将nw.js升级到最新版

nw.js官方git页面使用 nw.js freeze作为关键词搜索issues,发现了很多相关的Issues,如#96 #1363 #2348 #2585 #3561 #5020 ,很多时候将nw.js SDK升级到最新版就能解决问题。

记录nw.js的日志

因为客户端需要在Windows XP环境下使用,因此无法将nw.js升级到最新版,另外卡死的问题在本机无法重现,在客户的电脑上也是随机出现的,因此记录日志就尤为重要。

在项目的package.json文件中的chromium-args项中增加--enable-logging=stderr --v=1参数:

{
    "chromium-args": "--enable-logging=stderr --v=1"
}

Windows系统下建议增加vmodule=metrics=2--no-sandbox两个参数,详细设置可以参考Chromium官方文档

这样设置之后,名为chrome_debug.log的日志文件默认存放在Chrome的用户目录下面。

注意:日志文件在每次重启客户端之后会被覆盖,建议创建一个自动上传日志文件的小功能在客户端。

关闭内存压缩功能

如果客户端在后端运行一段时间再次激活的时候,出现卡死的现象,可以在chromium-args中增加--memory-pressure-off参数,--memory-pressure-off参数用来关闭内存压缩功能。

使用异步的方式加载外部js文件

经过上述的设置之后,打开客户端出现卡死的问题得到了解决,但后来又发现每次用户访问某一个页面的时候,又会出现卡死的问题,并且同样无法再本地重现,在用户端也是随机出现。

通过对该页面进行了排查,发现如果加载一个外部的百度地图的js的话,就很容易出现卡死的问题。因此需要将其设置为异步加载的方式,就可以解决这个卡死的问题。

说到外部js异步加载的方式,常用的有以下三种:

  • defer
    使用方式:<script src="https://api.map.baidu.com/api?v=2.0&ak=xxx&s=1" defer></script>
    HTML4开始的异步加载方式,不会阻止HTML DOM的解析,但会等到 DOMContentLoaded (即全部页面解析完成)前依次执行,很多时候和将js文件放在body的最后效果相同,只是加了defer属性之后不需要一定放在body的最后,可以将引用代码放在页面的任意位置。

  • async
    使用方式:<script src="https://api.map.baidu.com/api?v=2.0&ak=xxx&s=1" async></script>
    HTML5开始增加的异步加载方式,这种方式是完全的异步记载方式,即不会保证在页面加载前执行,会早于此,也会晚于此,完全异步。这种方式用于在当前页面中的script代码不会立即用到外部引用的js文件,像访问统计代码这种外部js文件特别适合用于这种方式,如果当前页面中不会立即调用外部js文件的相关函数,也可以采用这种方式。

  • 动态创建script标签
    核心代码如下:

    var script = document.createElement("script");
    script.src = "https://api.map.baidu.com/api?v=2.0&ak=xxx&s=1";
    document.body.appendChild(script);

    这种方式同async的方式,只是兼容性更好。

结合上述三种异步加载方式,考录到出问题的页面是单应用方式,不需要在加载完之后立即调用百度地图的api,因此采用async的方式。至此,问题得到解决。


参考资料:
Helper renderer process hangs on opening and closing print window several times
How to enable logging
nw.js freeze after a long time in background
异步加载 js 脚本的方法有哪些?
脚本异步加载
浅谈script标签的defer和async

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注