Estoy tratando de iniciar mi API de NodeJS en un servidor de producción usando Phusion Passenger. Usé la última sintaxis de ECM para importar/exportar mis módulos. Sin embargo, cuando intento llegar a mi API, Passenger devuelve este mensaje de error:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/***/api/server.mjs at Module.load (internal/modules/cjs/loader.js:948:11) at Function.Module._load (internal/modules/cjs/loader.js:790:14) at Module.require (internal/modules/cjs/loader.js:974:19) at Module.require (/opt/passenger/src/helper-scripts/node-loader.js:80:25) at require (internal/modules/cjs/helpers.js:92:18) at loadApplication (/opt/passenger/src/helper-scripts/node-loader.js:243:2) at setupEnvironment (/opt/passenger/src/helper-scripts/node-loader.js:214:2) at Object.<anonymous> (/opt/passenger/src/helper-scripts/node-loader.js:133:1) at Module._compile (internal/modules/cjs/loader.js:1085:14) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10) { code: 'ERR_REQUIRE_ESM' Tengo la línea "type": "module" en mi paquete.json e intenté cambiar la extensión de .js a .mjs sin efecto.
Noté que el pasajero usa CJS con la sintaxis "requerir" para cargar mi server.js como podemos ver aquí: https://github.com/phusion/passenger/blob/stable-6.0/src/helper-scripts/node-loader .js .
function loadApplication() { var appRoot = PhusionPassenger.options.app_root || process.cwd(); var startupFile = PhusionPassenger.options.startup_file || (appRoot + '/' + 'app.js'); require(startupFile); }Entonces mi pregunta es: ¿Hay alguna forma de no cambiar todo mi código de ECM a CJS para que coincida con Passenger?
Hay una manera: teniendo en cuenta que todos sus archivos tienen la extensión .mjs , solo necesita crear un .js para que sea el archivo de entrada para Passenger, y en este archivo (que está en formato CommonJS) puede importar dinámicamente el ESM.
Entonces, en lugar de ejecutar node server.mjs a través de Passenger, cree una entry.js con el siguiente contenido:
import("./server.mjs"); Y luego llame node entry.js a través de Passenger.
Nota: puede usar cualquier otro nombre para el archivo entry.js .
En caso de que esté trabajando con mecanografiado (ese es mi caso), logré deshacerme de este error al compilar mi código en el módulo commonJs en dos simples pasos
"type": "module" en su archivo packeage.json a "type": "commonjs"tsconfig.json a "module": "CommonJS"Reconstruir y ahora debería funcionar :)
Una actualización del código anterior: esto no funcionaría para mí a menos que la importación dinámica se llame de forma asíncrona:
Cree un archivo entry.cjs y use async/await para importar dinámicamente el archivo de entrada de sus aplicaciones que normalmente establecería en Plesk:
// entry.cjs async function loadApp() { const { app } = await import("./app.js"); // this is your normal entry file - (index.js, main.js, app.mjs etc.) } loadApp()Luego, en Plesk, establezca el archivo de entrada de su aplicación en ./entry.cjs