![](/img/trans.png)
[英]npm install not working, can't install any of the node modules after cloning my project from git
[英]Node can't find certain modules after synchronous install
我有一个脚本,可以在启动时同步安装非内置模块,如下所示
const cp = require('child_process')
function requireOrInstall (module) {
try {
require.resolve(module)
} catch (e) {
console.log(`Could not resolve "${module}"\nInstalling`)
cp.execSync(`npm install ${module}`)
console.log(`"${module}" has been installed`)
}
console.log(`Requiring "${module}"`)
try {
return require(module)
} catch (e) {
console.log(require.cache)
console.log(e)
}
}
const http = require('http')
const path = require('path')
const fs = require('fs')
const ffp = requireOrInstall('find-free-port')
const express = requireOrInstall('express')
const socket = requireOrInstall('socket.io')
// List goes on...
当我卸载模块时,它们将在我再次启动服务器时成功安装。 但是,当我卸载使用功能requireOrInstall
的列表的前两个模块时,脚本开始抛出Cannot find module
错误”。 没错,仅在脚本必须安装第一个或前两个模块时才会发生错误,而不是仅在第二个模块需要安装时才发生错误。
在此示例中, 除非卸载require
至少一个点的\\ _(•_•)_ /¯, 否则我将在卸载find-free-port时抛出该错误。
我还尝试过在同步安装后直接添加一个延迟,以通过以下两行使它有更多的呼吸时间:
var until = new Date().getTime() + 1000
while (new Date().getTime() < until) {}
暂停在那里。 它没有解决任何问题。
@velocityzen带有检查缓存的想法 ,现在我已将其添加到脚本中。 它没有显示任何异常。
@vaughan对另一个问题的评论指出,当需要两次模块时,会发生此确切错误。 我已将脚本更改为使用require.resolve()
,但错误仍然存在。
有人知道是什么原因造成的吗?
编辑
既然问题已经回答,我将发布一线(139个字符!)。 它没有全局定义child_modules
,没有最后一次try-catch
,也没有在控制台中记录任何内容:
const req=async m=>{let r=require;try{r.resolve(m)}catch(e){r('child_process').execSync('npm i '+m);await setImmediate(()=>{})}return r(m)}
该函数的名称是req()
,可以像在@ alex-rokabilis的answer中那样使用 。
我认为您最好的选择是:
首先,您可以考虑使用npm-programmatic软件包。
然后,您可以使用以下方式定义存储库路径:
const PATH='/tmp/myNodeModuleRepository';
然后,将您的安装说明替换为以下内容:
const npm = require('npm-programmatic');
npm.install(`${module}`, {
cwd: PATH,
save:true
}
最终,将您的故障回复要求说明替换为:
return require(module, { paths: [ PATH ] });
如果仍然无法正常工作,则可以更新require.cache变量,例如使模块失效,您可以执行以下操作:
delete require.cache[process.cwd() + 'node_modules/bluebird/js/release/bluebird.js'];
加载之前,您可能需要手动更新它,以添加有关新模块的信息。
似乎在npm install
后require
执行操作。 同样,在Windows中问题更严重,如果模块需要npm installed
,它将始终失败 。 就像在特定的事件快照中,已经知道需要什么模块,不需要什么模块。 也许这就是为什么require.cache
中提到了require.cache
的原因。 不过,我建议您检查以下2个解决方案。
const cp = require("child_process");
const requireOrInstall = async module => {
try {
require.resolve(module);
} catch (e) {
console.log(`Could not resolve "${module}"\nInstalling`);
cp.execSync(`npm install ${module}`);
// Use one of the two awaits below
// The first one waits 1000 milliseconds
// The other waits until the next event cycle
// Both work
await new Promise(resolve => setTimeout(() => resolve(), 1000));
await new Promise(resolve => setImmediate(() => resolve()));
console.log(`"${module}" has been installed`);
}
console.log(`Requiring "${module}"`);
try {
return require(module);
} catch (e) {
console.log(require.cache);
console.log(e);
}
}
const main = async() => {
const http = require("http");
const path = require("path");
const fs = require("fs");
const ffp = await requireOrInstall("find-free-port");
const express = await requireOrInstall("express");
const socket = await requireOrInstall("socket.io");
}
main();
await
始终需要一个承诺,但是并不需要显式创建一个承诺,因为await
将没有等待的承诺包装在等待中。
const cp = require("child_process");
function requireOrInstall(module) {
try {
require.resolve(module);
} catch (e) {
console.log(`Could not resolve "${module}"\nInstalling`);
cp.execSync(`npm install ${module}`);
console.log(`"${module}" has been installed`);
}
console.log(`Requiring "${module}"`);
try {
return require(module);
} catch (e) {
console.log(require.cache);
console.log(e);
process.exit(1007);
}
}
const cluster = require("cluster");
if (cluster.isMaster) {
cluster.fork();
cluster.on("exit", (worker, code, signal) => {
if (code === 1007) {
cluster.fork();
}
});
} else if (cluster.isWorker) {
// The real work here for the worker
const http = require("http");
const path = require("path");
const fs = require("fs");
const ffp = requireOrInstall("find-free-port");
const express = requireOrInstall("express");
const socket = requireOrInstall("socket.io");
process.exit(0);
}
这里的想法是在缺少模块的情况下重新运行该过程。 这样,我们就可以完全复制手动npm install
以便您猜对了! 同样,它似乎更同步,而不是第一种选择,但更为复杂。
cp.execSync是异步调用,因此请尝试检查模块是否已安装在其回调函数中。 我已经尝试过了,现在安装干净了:
const cp = require('child_process') function requireOrInstall (module) { try { require.resolve(module) } catch (e) { console.log(`Could not resolve "${module}"\\nInstalling`) cp.execSync(`npm install ${module}`, () => { console.log(`"${module}" has been installed`) try { return require(module) } catch (e) { console.log(require.cache) console.log(e) } }) } console.log(`Requiring "${module}"`) } const http = require('http') const path = require('path') const fs = require('fs') const ffp = requireOrInstall('find-free-port') const express = requireOrInstall('express') const socket = requireOrInstall('socket.io')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.