Lerna avec Yarn, TypeScript et React Native : Impossible de trouver le module '@project/common' ou ses déclarations de type correspondantes.ts(2307)
Le projet utilise Yarn, React Native, Lerna et Typescript. Il est structuré comme un monorepo
Voici la structure :
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 ressemble à ceci :
{
"packages": [
"packages/*"
],
"npmClient": "yarn",
"version": "0.0.7",
}
La racine packages.json ressemble à ceci :
{
"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 racine tsconfig.json ressemble à ceci :
{
"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"]
}
Le fichier packages/common/packages.json typique ressemble à ceci :
{
"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": {
...
}
}
Le fichier packages/common/tsconfig.json typique ressemble à ceci :
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "lib",
"strict": true,
"target": "es6"
},
"compileOnSave": true,
"include": ["src"]
}
Le fichier React Native packages/mobile/packages.json ressemble à ceci :
{
"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"
},
}
J'ai d'abord rencontré :
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".
De toute évidence, Yarn essaie d'extraire les dépendances de son registre de packages. Cela échoue.
Ensuite, j'ai essayé de supprimer les références à @project/common1 et @project/common2 dans les dépendances des packages.
Dans le source, VS Code souligne les importations en rouge et affiche :
Cannot find module '@project/common1' or its corresponding type declarations.ts(2307)
J'ai également essayé d'utiliser Yarn Workspace, mais j'ai rencontré des problèmes de levage de modules avec React Native. Je ne voulais pas créer une liste de tous les packages éventuellement incompatibles, car cela semble difficile à maintenir.
"workspaces": {
"nohoist": ["react-native", "react-native/**", "@react-native-community/checkbox", "@react-navigation/native"]
}
Y-a-t-il une solution simple ?
Ou est-il plus simple pour ce cas d'utilisation d'abandonner Lerna et d'utiliser des référentiels communs basés sur GitHub ?
Réponses
Je ne sais pas si c'est l'approche la plus simple, mais je pourrais la faire fonctionner en ajoutant des espaces de travail Yarn.
Dans le package principal.json j'ai ajouté :
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"**mobile**",
"**react**",
"**react-native**",
...
]
},
Dans Lerna.json j'ai ajouté:
"useWorkspaces": true,
De la racine tsconfig.json j'ai supprimé :
"baseUrl": "./",
"paths": {
"@project/common1": ["packages/common1/lib"],
"@project/common2": ["packages/common2/lib"],
"@project/mobile": ["packages/mobile/src"],
"@project/cloud-functions": ["packages/cloud-functions/src"],
}