虽然标题称错误为前端打包错误,但更具体的说这个错误是react-native打bundle包的时候出现的。因为排查过程有一定的通用性,所以我将这个错误描述成是前端打包的错误。
错误信息如下图所示:
从错误信息可以看出这个错误是json字串解析错误(JSON.parse),并且跟缓存相关(Cache.get)。然而除此之外就看不出更多的信息了(上面的描述跟react native没有任何关系,没有引入过上面说的包,我也不清楚是哪的错误)。
那么自然能够想到的方案是先清空npm包缓存,然后再看错误是否重现。我就这么做了,清空缓存没效后我又删除了依赖包,重新install。也是然并软。
接下来这么办?去Google搜索这招我觉得没毛病。然而也许是这种类型的bug太常见(指JSON解析错误),也有可能是react-native这种打包错误很少见。我将关键词增增减减搜了半天愣是没有找到相关的错误。
正当我一筹莫展之时,我发现这个打包错误也能定位到对应的打包代码段。代码如下,
class FileStore {
/*...*/
get(key) {
try {
return JSON.parse(fs.readFileSync(this._getFilePath(key), "utf8"));
} catch (err) {
if (err.code === "ENOENT") {
return null;
}
throw err;
}
}
_getFilePath(key) {
return path.join(
this._root,
key.slice(0, 1).toString("hex"),
key.slice(1).toString("hex")
);
}
/*...*/
}
复制代码
可以发现字符串由fs.readFileSync
从文件中读取,而文件路径由this._getFilePath(key)
获取。那么我们只要将字符串和文件路径打印出来就可以发现具体出问题的地方了。修改的代码过于简单就不发出来了。
小插曲
当然你也许会问为什么不使用打断点的方式,而使用这么low B的方案。原因是我并不知道react-native bundle的命令如何打断点,网上也没找到相关说明。如果是npm调用node执行程序的话,在webstorm中,可以通过在npm scripts命令调用前设置调试字符串实现断点
webstorm的说明如下,有兴趣的可以看下:
To debug the "pkg" script, make sure the %NODE_DEBUG_OPTION% string is specified as the first argument for the node command you'd like to debug.
For example:
"scripts": {
"start": "node %NODE_DEBUG_OPTION% server.js"
}
复制代码
通过以上打出的路径可以发现,缓存文件存在于用户目录下的临时文件中(AppData\Local\Temp
)。
打开文件夹后可以看到,跟bug提及的名字相关的文件夹具有两个metro-cache
与metro-bundler
,将他们同时删除问题解决。在删除之前我还做了个备份,防止出现意外,我真是个机灵鬼。
然而故事到此还没有结束
使用react-native bundle --help
命令打印可以发现,react-native bundle
本身带有一个选项--reset-cache
。
将原来的缓存放入之后执行:react-native bundle --platform android --entry-file index.js --bundle-output ./bundles/index.android.bundle --assets-dest ./bundles --dev false --reset-cache
居然也可以解决。。。
这个故事事故告诉我们,解决bug和写代码一样都需要灵性。