Lerna mit Yarn, TypeScript und React Native: Kann das Modul „@project/common“ oder die entsprechenden Typdeklarationen nicht finden.ts(2307)

Aug 19 2020

Das Projekt verwendet Yarn, React Native, Lerna und Typescript. Es ist als Monorepo strukturiert

Hier ist die Struktur:

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 sieht so aus:

{
  "packages": [
    "packages/*"
  ],
  "npmClient": "yarn",
  "version": "0.0.7",
}

Die Root-packages.json sieht so aus:

{
  "name": "project",
  "private": true,
  "scripts": {
    ...
  },
  "devDependencies": {
    "@types/node": "^14.0.27",
    "lerna": "^3.22.1",
    "ts-node": "^8.10.2",
    "typescript": "^3.9.7"
  }
}

Die Root-tsconfig.json sieht so aus:

{
  "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"]
}

Die typische packages/common/packages.json sieht so aus:

{
  "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": {
    ...
  }
}

Die typische packages/common/tsconfig.json sieht so aus:

{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "module": "commonjs",
    "outDir": "lib",
    "strict": true,
    "target": "es6"
  },
  "compileOnSave": true,
  "include": ["src"]
}

Die React Native-Datei packages/mobile/packages.json sieht folgendermaßen aus:

{
    "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"
    },
}

Ich stieß zuerst auf:

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".

Offensichtlich versucht Yarn, die Abhängigkeiten aus seiner Paketregistrierung zu ziehen. Dies schlägt fehl.

Dann habe ich versucht, die Verweise auf @project/common1 und @project/common2 in den Abhängigkeiten der Pakete zu entfernen.

In der Quelle unterstreicht VS Code die Importe in Rot und druckt:

Cannot find module '@project/common1' or its corresponding type declarations.ts(2307)

Ich habe auch versucht, Yarn Workspace zu verwenden, bin jedoch auf Probleme beim Heben von Modulen mit React Native gestoßen. Ich wollte keine Liste aller möglicherweise inkompatiblen Pakete erstellen, da es schwierig zu warten scheint.

"workspaces": {
  "nohoist": ["react-native", "react-native/**", "@react-native-community/checkbox", "@react-navigation/native"]
}

Gibt es eine einfache Lösung?

Oder ist es für diesen Anwendungsfall einfacher, Lerna aufzugeben und GitHub-basierte gemeinsame Repositories zu verwenden?

Antworten

Xiiryo Aug 20 2020 at 22:32

Ich weiß nicht, ob dies der einfachste Ansatz ist, aber ich könnte es zum Laufen bringen, indem ich Yarn-Arbeitsbereiche hinzufüge.

In der Haupt-packages.json habe ich hinzugefügt:

  "workspaces": {
    "packages": [
      "packages/*"
    ],
    "nohoist": [
      "**mobile**",
      "**react**",
      "**react-native**",
      ...
    ]
  },

In Lerna.json habe ich hinzugefügt:

  "useWorkspaces": true,

Aus dem Stamm tsconfig.json habe ich gelöscht:

    "baseUrl": "./",
    "paths": {
      "@project/common1": ["packages/common1/lib"],
      "@project/common2": ["packages/common2/lib"],
      "@project/mobile": ["packages/mobile/src"],
      "@project/cloud-functions": ["packages/cloud-functions/src"],
    }