Lerna con Yarn, TypeScript y React Native: no se puede encontrar el módulo '@project/common' o sus declaraciones de tipo correspondientes.ts(2307)
El proyecto utiliza Yarn, React Native, Lerna y Typescript. Está estructurado como un monorepo
Aquí está la estructura:
project
|- packages
| - mobile
| - src
| - packages.json
| - tsconfig.json
| - cloud-functions
| - src
| - packages.json
| - tsconfig.json
| - common1
| - lib
| - src
| - packages.json
| - tsconfig.json
| - common2
| - lib
| - src
| - packages.json
| - tsconfig.json
| - packages.json
| - tsconfig.json
| - lerna.json
lerna.json se ve así:
{
"packages": [
"packages/*"
],
"npmClient": "yarn",
"version": "0.0.7",
}
La raíz packages.json se ve así:
{
"name": "project",
"private": true,
"scripts": {
...
},
"devDependencies": {
"@types/node": "^14.0.27",
"lerna": "^3.22.1",
"ts-node": "^8.10.2",
"typescript": "^3.9.7"
}
}
La raíz tsconfig.json se ve así:
{
"compilerOptions": {
"noImplicitAny": true,
"noUnusedLocals": true,
"removeComments": true,
"noLib": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"baseUrl": "./",
"paths": {
"@project/common1": ["packages/common1/lib"],
"@project/common2": ["packages/common2/lib"],
"@project/mobile": ["packages/mobile/src"],
"@project/cloud-functions": ["packages/cloud-functions/src"],
}
},
"exclude": ["node_modules", "**/*.spec.ts", "**/__tests__/*", "babel.config.js", "metro.config.js", "jest.config.js"]
}
Los típicos paquetes/común/paquetes.json se ven así:
{
"name": "@project/common1",
"version": "0.0.7",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"files": [
"lib/**/*"
],
"private": true,
"devDependencies": {
"@project/common2": "latest", //for common1 only
"@types/node": "^14.0.27",
"ts-node": "^8.10.2",
"typescript": "^3.9.7"
},
"dependencies": {
...
}
}
Los típicos paquetes/common/tsconfig.json se ven así:
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "lib",
"strict": true,
"target": "es6"
},
"compileOnSave": true,
"include": ["src"]
}
El archivo de React Native packages/mobile/packages.json se ve así:
{
"name": "@project/mobile",
"version": "0.0.7",
"private": true,
"dependencies": {
"@project/common1": "latest",
"@project/common2": "latest",
...
},
"devDependencies": {
...
"ts-node": "^8.10.2",
"typescript": "^3.8.3"
},
}
Primero me encontré con:
lerna ERR! yarn install --mutex network:42424 --non-interactive stderr:
warning Waiting for the other yarn instance to finish (19560)
warning Waiting for the other yarn instance to finish (21568)
error An unexpected error occurred: "https://registry.yarnpkg.com/@project%2fcommon1: Not found".
Obviamente, Yarn está tratando de extraer las dependencias de su registro de paquetes. esto falla
Luego traté de eliminar las referencias a @project/common1 y @project/common2 en las dependencias de los paquetes.
En la fuente, VS Code subraya las importaciones en rojo e imprime:
Cannot find module '@project/common1' or its corresponding type declarations.ts(2307)
También traté de usar Yarn Workspace, pero me encontré con problemas de levantamiento de módulos con React Native. No quería crear una lista de todos los paquetes posiblemente incompatibles, ya que parece ser difícil de mantener.
"workspaces": {
"nohoist": ["react-native", "react-native/**", "@react-native-community/checkbox", "@react-navigation/native"]
}
¿Hay una solución sencilla?
¿O es más simple para este caso de uso abandonar Lerna y usar repositorios comunes basados en GitHub?
Respuestas
No sé si este es el enfoque más simple, pero podría hacerlo funcionar agregando espacios de trabajo de Yarn.
En los paquetes principales.json agregué:
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"**mobile**",
"**react**",
"**react-native**",
...
]
},
En Lerna.json agregué:
"useWorkspaces": true,
Desde la raíz tsconfig.json eliminé:
"baseUrl": "./",
"paths": {
"@project/common1": ["packages/common1/lib"],
"@project/common2": ["packages/common2/lib"],
"@project/mobile": ["packages/mobile/src"],
"@project/cloud-functions": ["packages/cloud-functions/src"],
}