如何能够引入刚下载的第三方模块?
我想实现一个函数,当目标模块已下载时,直接通过 require 引入,否则去npm下载,完成后再引入。 原先的代码是这样的:
const execa = require('execa');
const requireDynamic = async moduleName => {
try {
return require(moduleName);
} catch {
await execa('npm', ['install', moduleName]);
return require(moduleName);
}
};
但是这样会报错,提示模块不存在。 而我在模块安装结束后用下面这段代码确认模块已经安装,模块文件夹是存在的:
const fs = require('fs-extra');
const path = require('path');
console.log(fs.pathExists(path.resolve(process.cwd(), 'node_modules', moduleName)));
我怀疑模块下载成功后没能立即允许引入,所以开了定时器setInterval 来确认什么时候可以引入,但是一直都不可以。
后来我先找到这个模块的package.json ,然后在main字段找到模块的入口文件,引入这个文件,是可以的。
const execa = require('execa');
const path = require('path');
const requireDynamic = async moduleName => {
try {
return require(moduleName);
} catch {
await execa('npm', ['install', moduleName]);
const modulePath = path.resolve(process.cwd(), 'node_modules', moduleName);
const { main } = require(path.resolve(modulePath, 'package.json'));
return require(path.resolve(modulePath, main));
}
};
我就是没明白,npm模块从下载,解压,还要经过什么流程,才可以被正常引入。希望有好心人解答下,谢谢了。
7 回复
目测 require 缓存造成的,catch 语句里面先删除一次缓存试试
await execa('npm', ['install', moduleName]);
delete require.cache[moduleName];
return require(moduleName);
@xiaoxiaojx 我找到解决方案了。
delete require.cache[] 数组里面填写的不能是moduleName,因为之前require失败,缓存里面找不到moduleName对应的地址。
应该改成path.resolve(process.cwd(), 'node_modules', moduleName)就可以成功删除了。