最近基于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