De la documentación de node.js:
Los módulos se almacenan en caché después de la primera vez que se cargan. Esto significa (entre otras cosas) que cada llamada a requerir ('foo') obtendrá exactamente el mismo objeto devuelto, si se resuelve en el mismo archivo.
¿Hay alguna manera de invalidar este caché? es decir, para pruebas unitarias, me gustaría que cada prueba funcione en un objeto nuevo.
Respuestas:
Siempre puede eliminar de forma segura una entrada en require.cache sin problemas, incluso cuando hay dependencias circulares. Porque cuando elimina, simplemente elimina una referencia al objeto del módulo en caché, no el objeto del módulo en sí, el objeto del módulo no será GCed porque en caso de dependencias circulares, todavía hay un objeto que hace referencia a este objeto del módulo.
Supongamos que tienes:
script a.js:
y script b.js:
Cuando tu lo hagas:
conseguirás:
ahora si editas tu b.js:
y hacer:
conseguirás:
===
Lo anterior es válido si se ejecuta directamente node.js. Sin embargo, si usa herramientas que tienen su propio sistema de almacenamiento en caché de módulos, como jest , la declaración correcta sería:
fuente
{ ... a: undefined}
cuando lo requiereb.js
por primera vez? Yo esperaría igualar'a from a.js'
. Graciasb[a]
no está definido la primera vez ya que hay una dependencia circular.a.js
requiereb.js
que a su vez requierea.js
.a.js
aún no está completamente cargado yexports.a
aún no se ha definido, por lob.js
que no obtiene nada.require.main.require(path)
como se describe aquí? stackoverflow.com/questions/10860244/…Si siempre desea volver a cargar su módulo, puede agregar esta función:
y luego usar en
requireUncached('./myModule')
lugar de requerir.fuente
fs.watch
método que escucha los cambios de archivo.Sí, puede acceder a la memoria caché a través de
require.cache[moduleName]
dondemoduleName
está el nombre del módulo al que desea acceder. Eliminar una entrada al llamardelete require.cache[moduleName]
harárequire
que se cargue el archivo real.Así es como eliminaría todos los archivos en caché asociados con el módulo:
El uso sería:
Dado que este código usa el mismo resolutor
require
, simplemente especifique lo que necesite.Creo que debería haber una forma de realizar una carga explícita de módulo sin caché.
fuente
require.uncache
función. `` `// ver github.com/joyent/node/issues/8266 Object.keys (module.constructor._pathCache) .forEach (function (k) {if (k.indexOf (moduleName)> 0) delete module.constructor ._pathCache [k];}); `` Digamos que ha requerido un módulo, luego lo desinstaló, luego reinstaló el mismo módulo pero usó una versión diferente que tiene un script principal diferente en su paquete.json, el siguiente requerimiento fallará porque ese script principal no existe porque está en cachéModule._pathCache
require.uncache
Hay un módulo simple para eso ( con pruebas )
Tuvimos este problema exacto al probar nuestro código ( elimine los módulos en caché para que puedan volver a requerirse en un estado nuevo ), por lo que revisamos todas las sugerencias de las personas en las diversas preguntas y respuestas de StackOverflow y armamos un módulo simple node.js ( con pruebas ):
Como era de esperar, funciona tanto para paquetes npm publicados como para módulos definidos localmente . Windows, Mac, Linux, etc.
¿Cómo? ( uso )
El uso es bastante simple:
Instalar en pc
Instale el módulo desde npm:
npm install decache --save-dev
Úselo en su código:
Si tiene alguna pregunta o necesita más ejemplos, cree un problema de GitHub: https://github.com/dwyl/decache/issues
fuente
Para cualquiera que se encuentre con esto que esté usando Jest, porque Jest hace su propio almacenamiento en caché del módulo, hay una función incorporada para esto, solo asegúrese de
jest.resetModules
ejecutar, por ejemplo. después de cada una de tus pruebas:Encontré esto después de tratar de usar decache como sugiere otra respuesta. Gracias a Anthony Garvan .
Documentación de funciones aquí .
fuente
La solución es usar:
Encuentre aquí algunas explicaciones básicas para aquellos que, como yo, son un poco nuevos en esto:
Supongamos que tiene un
example.js
archivo ficticio en la raíz de su directorio:Entonces te
require()
gusta esto:Si luego agrega una línea como esta a
example.js
:Y continuar en la consola, el módulo no se actualiza:
Ahí es cuando puedes usar lo
delete require.cache[require.resolve()]
indicado en la respuesta de luff :Por lo tanto, el caché se limpia y
require()
captura el contenido del archivo nuevamente, cargando todos los valores actuales.fuente
rewire es ideal para este caso de uso, obtienes una nueva instancia con cada llamada. Fácil inyección de dependencia para la prueba de la unidad node.js.
rewire agrega un setter y getter especial a los módulos para que pueda modificar su comportamiento para una mejor prueba de la unidad. Puedes
inyectar simulacros para otros módulos o globales como las fugas privadas del proceso. Las variables privadas anulan las variables dentro del módulo. rewire no carga el archivo y evalúa el contenido para emular el mecanismo requerido del nodo. De hecho, utiliza los requisitos del nodo para cargar el módulo. Por lo tanto, su módulo se comporta exactamente igual en su entorno de prueba que en circunstancias normales (excepto sus modificaciones).
Buenas noticias para todos los adictos a la cafeína: rewire funciona también con Coffee-Script. Tenga en cuenta que en este caso CoffeeScript debe aparecer en sus devDependencies.
fuente
Agregaría a la respuesta de luff una línea más y cambiaría el nombre del parámetro:
fuente
Sí, puedes invalidar el caché.
El caché se almacena en un objeto llamado require.cache al que puede acceder directamente de acuerdo con los nombres de archivo (por ejemplo,
/projects/app/home/index.js
en lugar de./home
lo que usaría en unarequire('./home')
declaración).Nuestro equipo ha encontrado útil el siguiente módulo. Invalidar ciertos grupos de módulos.
https://www.npmjs.com/package/node-resource
fuente
No pude agregar código en el comentario de una respuesta. Pero usaría la respuesta de @Ben Barkay y luego agregaría esto a la
require.uncache
función.Supongamos que ha requerido un módulo, luego lo desinstaló, luego reinstaló el mismo módulo pero usó una versión diferente que tiene un script principal diferente en su paquete.json, el siguiente requerimiento fallará porque ese script principal no existe porque está en caché
Module._pathCache
fuente
No estoy 100% seguro de lo que quieres decir con 'invalidar', pero puedes agregar lo siguiente arriba de las
require
declaraciones para borrar el caché:Tomado del comentario de @ Dancrumb aquí
fuente
requireUncached
con ruta relativa: 🔥invocar requireUncached con ruta relativa:
fuente
El siguiente procedimiento de dos pasos me funciona perfectamente.
Después de cambiar el
Model
archivo, es decir'mymodule.js'
, dinámicamente, primero debe eliminar el modelo precompilado en el modelo de mangosta y luego volver a cargarlo con require-reloadfuente
Si es para pruebas unitarias, otra buena herramienta para usar es proxyquire . Cada vez que solicita proxy el módulo, invalidará el caché del módulo y almacenará uno nuevo. También le permite modificar los módulos requeridos por el archivo que está probando.
fuente
Hice un pequeño módulo para eliminar el módulo del caché después de cargarlo. Esto fuerza la reevaluación del módulo la próxima vez que se requiera. Ver https://github.com/bahmutov/require-and-forget
PD: también puedes poner "autodestrucción" en el módulo mismo. Ver https://github.com/bahmutov/unload-me
PSS: se requieren más trucos con Node en mi https://glebbahmutov.com/blog/hacking-node-require/
fuente