es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo permitir que un paquete CJS requiera dinámicamente un módulo ES en tiempo de ejecución?

Estoy utilizando un paquete “loader” al que le paso el nombre de un módulo “loadee” y lo requiere usando “require()”.
El “loader” utiliza “require()” de CJS para requerir dinámicamente el “loadee”, pero el “loadee” es un módulo ES. Debido a esto, Node.js arroja un error.

Error [ERR_REQUIRE_ESM]: no se admite require() de ES Module LOADEE desde LOADER.
En su lugar, cambie el require de LOADEE en LOADER a un import() dinámico que está disponible en todos los módulos CommonJS.

Ni el “loader” ni el “loadee” están bajo mi gestión, por lo que no puedo modificarlos. Tampoco puedo evitar usarlos.

Por supuesto, puedo escribir un “loadee” intermedio, escrito en CJS (para que el “loader” pueda cargarlo), que luego cargue el verdadero “loadee” y lo pase de nuevo al “loader”. Pero no sé cómo hacerlo, ya que el “import()” dinámico es asíncrono (devuelve una promesa), pero el “require()” del “loader” es sincrónico y espera el módulo cargado inmediatamente.

¿Hay algo más que pueda hacer para que esto funcione?

Ejemplo para mostrar lo que está sucediendo:

En caso de que la descripción que di no sea lo suficientemente clara, estoy intentando publicar algunos fragmentos de código mínimos para mostrar lo que está sucediendo:

LOADER (CJS; no escrito por mí):

module.exports = function(pkg) {
const x = require(pkg)
console.log(x)
}

LOADEE (módulo ES; no escrito por mí):

export const x = 1

./index.js (este es mío: puedo elegir CJS o módulo ES o cualquier otra cosa):

import load from ‘LOADER’
load(‘LOADEE’)

Cuando ejecuto “node ./index.js”, esto es lo que obtengo:

Error [ERR_REQUIRE_ESM]: no se admite require() de ES Module LOADEE desde LOADER.
En su lugar, cambie el require de LOADEE en LOADER a un import() dinámico que está disponible en todos los módulos CommonJS.

Preguntas similares:

Ya encontré preguntas similares en stack overflow. Por ejemplo:

  • https://stackoverflow.com/questions/69041454/error-require-of-es-modules-is-not-supported-when-importing-node-fetch
  • https://stackoverflow.com/questions/69081410/error-err-require-esm-require-of-es-module-not-supported

Explican cómo utilizar “import()” para importar dinámicamente un módulo. Pero eso no me ayuda ya que no puedo cambiar la llamada “require()” en el “loader” y no sé cómo envolverla con un “import()” dinámico asincrónico.

¿Hay algo que pueda hacer para que esto funcione?

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Desafortunadamente, no hay forma de hacer que una operación asíncrona como import() funcione con una operación sincrónica como require(). Sin embargo, hay algunas soluciones alternativas que puedes probar.

    Una opción es crear un módulo intermediario de CJS que envuelva al módulo de ES, de esta manera:

    INTERMEDIARY LOADEE (CJS; escrito por ti)
    module.exports = require('esmLoader')('LOADEE')
    

    Luego, puedes pasar el nombre del módulo intermediario al cargador:

    load('INTERMEDIARY_LOADEE')
    

    Esto cargará el módulo intermediario, que a su vez cargará dinámicamente el módulo de ES utilizando import().

    Otra opción es utilizar una herramienta como esm o babel para transpilar el módulo de ES a CJS sobre la marcha, haciendo que sea compatible con la llamada require() del cargador. Luego puedes importar el módulo transpilado directamente en tu código.

    Finalmente, si ninguna de estas soluciones alternativas es factible, es posible que necesites buscar un cargador diferente que admita la carga de módulos de ES.

Comments are closed.