一个小工具里需要require位于SMB存储设备的js文件作为配置文件,以前配置文件位于本地硬盘的时候是没有任何问题的,但自从把这个配置移动到SMB共享的服务器上了之后,程序执行就相当慢。
开了个调试发现是require执行了40多秒,但我如果直接用fs.readFileSync去读取那个配置文件的话是瞬间返回的,于是就奇怪了,并不是文件io慢,那怎么卡成这样。
接着开始在程序卡住的时候点开发者工具里的暂停,看程序卡完以后会停在什么地方,于是发现了在停下的位置之前是以下内容:
if (StringPrototypeEndsWith(filename, '.cjs')) {
format = 'commonjs';
} else if (StringPrototypeEndsWith(filename, '.mjs')) {
format = 'module';
} else if (StringPrototypeEndsWith(filename, '.js')) {
pkg = packageJsonReader.getNearestParentPackageJSON(filename);
const typeFromPjson = pkg?.data.type;
if (typeFromPjson === 'module' || typeFromPjson === 'commonjs' || !typeFromPjson) {
format = typeFromPjson;
}
}
我的配置文件是.js后缀的,从代码上来看,这段代码只有可能卡在`packageJsonReader.getNearestParentPackageJSON`上,那么就首先来排除是不是这里出了问题,只要绕开这个分支,比如换成`.cjs`后缀试一试。
果然换成`.cjs`后缀以后,`require`瞬间就返回了。
那么造成卡顿的原因终于找到了,是require一个js文件时,他需要去一层层往上找到一个`package.json`文件,目的是看看这个js文件到底是模块(module)类型的还是cjs(commonjs)类型的,目前由于另外一个未知原因导致这个过程非常慢,但我也没时间去细究咋回事了。
如果要解决这个问题,又不想改原来的文件后缀,那么就只要在该文件的目录里再新建一个`package.json`文件,并在里面写上需要的`type`就行了,比如:
{
"type": "commonjs"
}