typescript - Implementación en Firebase - No se puede encontrar el módulo de una dependencia local
Tengo un submódulo llamado shared que se encuentra junto a la carpeta backend (que es la carpeta de funciones en la nube):
He añadido la dependencia local shared en backend/package.json de la siguiente manera:
"dependencies": {
...
"shared": "file:../shared"
}
Ejecuté npm install y me aseguré de que node_modules/shared exista. Sin embargo, cuando ejecuto el siguiente código:
firebase deploy --only functions
Recibo el siguiente error (por Firebase):
Error: Error parsing triggers: Cannot find module 'shared/common'
Try running "npm install" in your functions directory before deploying.
Este error se debe a esta línea:
import { currentWeek } from 'shared/common';
Si cambio el directorio a ../../../shared/common, Firebase se compilará sin ningún error.
compartido/común/index.ts:
export { currentWeek } from './current-week';
compartido/tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"target": "es5",
"module": "commonjs",
"declaration": true,
"strict": true,
"removeComments": true
}
}
backend/tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"declaration": true,
"outDir": "./dist",
"module": "commonjs",
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"allowSyntheticDefaultImports": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"resolveJsonModule": true,
"target": "es6",
"moduleResolution": "node",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2015",
"dom"
]
},
"include": [
"./src/**/*",
"../shared/**/*"
]
}
¿Por qué recibo este error si SÍ tengo este módulo? ¿Hay algo que me esté perdiendo?
Respuesta #1
Aunque la respuesta de @jrasm91 explica bien la razón de este error, de alguna manera echo de menos la solución al problema aquí.
Supongamos que tienes la siguiente estructura de monorepo
- common
- firebase
- functions
donde common es un módulo de NodeJS con código común, firebase es la carpeta raíz de tu proyecto de Firebase y firebase/functions es el proyecto de NodeJS de tus funciones.
En firebase/functions/package.json no puedes incluir tu módulo common como
"dependencies": {
"common": "file:../../common"
}
porque como explicó @jrasm91, la carpeta common está situada fuera de la carpeta functions y por lo tanto no se empaquetará ni se subirá al ejecutar firebase deploy --only functions, lo cual también se explica aquí.
La solución que funcionó para mí es además crear un enlace simbólico de la carpeta common en la carpeta functions
cd firebase/functions
ln -s ../../common common
y luego actualiza el package.json
"dependencies": {
"common": "file:common"
}
Respuesta #2
En resumen:
node_modulesse ignora por defecto, mientras quebackend/distse sube.npm run buildocurre localmente ynpm installocurre en la nube.npm installprobablemente falla en la nube debido a la falta de la carpetasharedo problemas de ruta incorrecta debido a una estructura de directorios diferente y/o un directorio “raíz” diferente en el entorno de la nube.
O, en más detalle:
Functions tiene un paso de predespliegue que construye (npm run build => tsc) el proyecto de TypeScript localmente y luego envía el resultado a la nube donde las dependencias se instalan (npm install).
Cuando incluyes shared mediante una ruta relativa (../../shared), el código compilado se genera en la carpeta backend/dist después de que el proyecto se construye (localmente) y, por lo tanto, se sube.
Cuando incluyes shared a través de una dependencia local de módulos de nodo, la salida se encuentra en la carpeta backend/node_modules después de que las dependencias son instaladas y, por lo tanto, no se sube ya que node_modules se ignora por defecto.
El otro problema que estás viendo es por qué npm install no puede instalar la dependencia local en la nube. Esto probablemente se deba a (1) no subir shared junto con backend y/o a que la estructura de directorios y rutas relativas en el entorno de la nube es diferente de lo que es localmente.
firebase.json{
"functions": {
"predeploy": ["npm --prefix \"$RESOURCE_DIR\" run lint", "npm --prefix \"$RESOURCE_DIR\" run build"],
"source": "functions",
"ignore": ["**/.env", "**/.runtimeconfig.js", "**/.log", "**/node_modules/**"]
},
...
}
