У меня есть скрипт, который синхронно устанавливает не встроенные модули при запуске, который выглядит следующим образом
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...
Когда я удаляю модули, они успешно устанавливаются при следующем запуске сервера, чтоэто то, что я хочуОднако скрипт начинает выдавать ошибки Cannot find module
, когда я удаляю первые или первые два модуля списка, которые используют функцию requireOrInstall
.Это верно, ошибки возникают только тогда, когда скрипт должен установить либо первый, либо первые два модуля, а не когда требуется установка только второго модуля.
В этом примере ошибка будет выдана, когда я удаляю find-free-port, если я не переместил require
хотя бы на одну точку вниз ¯ \ _ (• _ •) _ / ¯
Я также пытался добавить задержку сразу послесинхронная установка, чтобы дать ему немного больше времени дыхания со следующими двумя строками:
var until = new Date().getTime() + 1000
while (new Date().getTime() < until) {}
Пауза была там.Это ничего не исправило.
@ speedzen пришло с идеей проверить кэш , который я сейчас добавил в скрипт.Он не показывает ничего необычного. Комментарий
@ 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 'ответ .