typescript - VSC finner ikke pakken i monorepo (kan ikke finne navn [package])


Jeg har satt opp et monorepo i TypeScript. Problemet jeg står overfor er at test-rammeverket mitt ikke kan bli funnet (som Visual Studio Code kunne før jeg byttet til et monorepo).

Jeg får følgende feilmelding: Kan ikke finne navnet 'jest' eller 'describe'... osv. Jeg tror Visual Studio Code ikke kan finne jest npm-pakken. Når jeg åpner /cli, /server, /shared-mappen blir bare pakken oppdaget av VSC.

Dette er min mappestruktur:

/cli
   node_modules
   src
   tsconfig.json
/server
   node_modules
   src
   tsconfig.json
/shared
   node_modules
   src
   tsconfig.json
tsconfig.base.json
tsconfig.json

Min tsconfig.base.json:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "lib": [
      "es2015"
    ],
    "strict": true,
    "declaration": true,
    "outDir": "dist",
    "sourceMap": true,
    "paths": {
      "@shared/*": [
        "./shared/src/*"
      ]
    }
  },
  "files": [],
  "references": [
    {
      "path": "./server"
    },
    {
      "path": "./cli"
    },
    {
      "path": "./shared"
    }
  ]
}

Min cli tsconfig.json:

{
  "extends": "../tsconfig.base.json",
  "compilerOptions": {
    "baseUrl": "..",
    "outDir": "dist",
    "types": [
      "jest"
    ],
    "typeRoots": [
      "./node_modules/@types"
    ]
  },
  "include": [
    "src/**/*",
    "../shared/src/**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.test.ts"
  ]
}

Et lite eksempel hvor feilen oppstår:

import { getUserInput } from "./console";
import { createInterface, ReadLineOptions } from "readline"; <----- error readline not found
jest.mock("readline"); <----- error jest not found

Jeg håper du kan hjelpe meg med å sette dette opp.

REDIGER: Jeg fant ut at når jeg fjerner "**/*.test.ts" fra ekskluderingen, fungerer det igjen som forventet. Men når jeg kompilerer, vil jeg ikke at testene skal bli inkludert...

Svar #1

Du vil prøve dette.

  1. Lag en tsconfig.build.json med de nåværende innstillingene fra tsconfig.json, unntatt testfilene dine:
{
  "extends": "../tsconfig.base.json",
  "compilerOptions": {
    // your specific compiler options for this module
  },
  "exclude": [
    "node_modules",
    "**/*.test.ts"
  ]
}
  1. Utvid tsconfig.json med din nye tsconfig.build.json, og fjern ekskluderingen av tester:
{
  "extends": "./tsconfig.build.json",
  "exclude": [
    "node_modules",
  ]
}
  1. Justér byggekommandoen din i package.json:
{
  "name": "server",
  "scripts": {
    "build": "tsc -b tsconfig.build.json"
  }
}

Den forrige konfigurasjonen din kunne ikke løse og typekontrollere Jest-medlemmer fordi du eksplisitt instruerte TypeScript om å ignorere testfilene dine.

Jeg fant dette svaret for meg selv da jeg så på andre monorepoer som typescript-eslint/eslint-plugin-internal som gjorde det samme.

Svar #2

Jeg har også gått rundt og rundt med dette problemet, jeg har Lerna monorepo (vel, egentlig bruker det npm workspaces, men det er det samme)

Mitt hovedproblem var fordi pluginen ser på roten for jest-konfigurasjonen, og jeg hadde en litt forskjellig konfigurasjon for hvert prosjekt. Min jest-konfigurasjon, som definerer bruken av TypeScript, var i package.json-filen til hver pakke.

Alt jeg måtte gjøre var å bruke Jest-prosjektenes mekanisme, og det fungerte som en drøm.

I rotmappen la jeg til en jest.config.js-fil som:

module.exports = {
  projects: [
    '<rootDir>/packages/package-a',
    '<rootDir>/packages/package-b',
    ...
  ]
}

Viktige punkter

  • <rootDir> er ikke en plassholder du bør erstatte! Det er en forhåndsdefinert plassholder kjent av jest for roten av prosjektet
  • måten jeg skrev det ovenfor med pakkenavnet er slik at det vil bruke package.json-filen - hvis du vil ha konfigurasjonen i en annen fil, for eksempel jest.config.js i hver pakke, legg den bare til (f.eks. '<rootDir>/packages/package-a/jest.config.js')

Bonus

hvis du ikke vil huske å legge til hver ny pakke i denne filen, kan du dynamisk generere prosjekter-arrayet:

const fs = require('fs')
const path = require('path')

const packagesDir = path.resolve(__dirname, 'packages') // or 'workspaces' what you have in your project
const packageDirs = fs.readdirSync(packagesDir).filter((file) => {
  return fs.statSync(path.join(packagesDir, file)).isDirectory()
})

const projects = packageDirs.map((dir) => `<rootDir>/packages/${dir}`)

module.exports = { projects }