網站搜尋

使用 Lerna 和 TypeScript 的單一代碼庫無法通過路徑別名導入套件


我正在嘗試使用 Lerna 建立一個基於 TypeScript 的 monorepo,其中我有兩個套件,bar 和 foo。foo 透過路徑別名導入 bar,但是導入失敗。

  1. tree
.
├── lerna.json
├── package.json
├── package-lock.json
├── packages
│   ├── bar
│   │   ├── lib
│   │   │   ├── index.d.ts
│   │   │   └── index.js
│   │   ├── package.json
│   │   ├── src
│   │   │   └── index.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   └── foo
│       ├── lib
│       │   ├── index.d.ts
│       │   └── index.js
│       ├── package.json
│       ├── src
│       │   └── index.ts
│       ├── tsconfig.build.json
│       └── tsconfig.json
├── tsconfig.build.json
└── tsconfig.json
  1. ./tsconfig.build.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "target": "es6",
    "module": "commonjs",
    "moduleResolution": "node",
    "declaration": true
  }
}
  1. ./tsconfig.json
{
  "extends": "./tsconfig.build.json",
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@company/bar": [
        "packages/bar"
      ],
      "@company/foo": [
        "packages/foo"
      ]
    }
  }
}
  1. ./lerna.json
{
  "packages": [
    "packages/*"
  ],
  "version": "0.0.0"
}
  1. ./package.json
{
  "name": "root",
  "private": true,
  "scripts": {
    "tsc": "lerna run tsc"
  },
  "devDependencies": {
    "lerna": "^3.22.1",
    "ts-node": "^9.0.0",
    "ts-node-dev": "^1.0.0-pre.63",
    "typescript": "^4.0.3"
  }
}

套件 bar:

  1. ./packages/bar/src/index.ts
export const bar = 'bar';
  1. ./packages/bar/package.json
{
  "name": "@company/bar",
  "version": "1.0.0",

  ...

  "main": "lib/index.js",
  "types": "lib/index.d.ts",
  "scripts": {
    "tsc": "tsc -p tsconfig.build.json"
  }
}
  1. ./packages/bar/tsconfig.build.json
{
  "extends": "../../tsconfig.build.json",
  "compilerOptions": {
    "outDir": "./lib"
  },
  "include": [
    "src/**/*"
  ]
}
  1. ./packages/bar/tsconfig.json
{
  "extends": "../../tsconfig.json"
}

套件 foo:

  1. ./packages/foo/src/index.ts
import { bar } from '@company/bar';

console.log(bar);
  1. ./packages/foo/package.json
{
  "name": "@company/foo",
  "version": "1.0.0",

  ...

  "main": "lib/index.js",
  "types": "lib/index.d.ts",
  "scripts": {
    "tsc": "tsc -p tsconfig.build.json"
  }
}
  1. ./packages/foo/tsconfig.build.json
{
  "extends": "../../tsconfig.build.json",
  "compilerOptions": {
    "outDir": "./lib"
  },
  "include": [
    "src/**/*"
  ]
}
  1. ./packages/foo/tsconfig.json
{
  "extends": "../../tsconfig.json"
}

最後:

執行 npm run tsc 會編譯我的套件,其中 foo 匯入 bar。它給我以下錯誤:

> lerna run tsc

lerna notice cli v3.22.1
lerna info Executing command in 2 packages: "npm run tsc"
lerna info run Ran npm script 'tsc' in '@company/bar' in 2.4s:

> @company/[email  tsc /.../monorepo-lerna/packages/bar
> tsc -p tsconfig.build.json

lerna ERR! npm run tsc exited 2 in '@company/foo'
lerna ERR! npm run tsc stdout:

> @company/[email  tsc /.../monorepo-lerna/packages/foo
> tsc -p tsconfig.build.json

src/index.ts(1,21): error TS2307: Cannot find module '@company/bar' or its corresponding type declarations.

錯誤本身相當清楚,雖然我不知道如何修復它(./tsconfig.json 裡的路徑別名我猜看起來沒問題)。有人知道我的配置出錯在哪裡嗎?我錯過了哪個環節?

如果我將 import { bar } from '@company/bar'; 改成 import { bar } from '../../bar/src';,一切都能正常運作,然而我仍然想保留第一種方式來匯入 bar。

答案#1

這部分允許你將套件以 @company/bar 的形式匯入

    "paths": {
      "@company/bar": [
        "packages/bar"
      ],
      "@company/foo": [
        "packages/foo"
      ]
    }

這在 ./tsconfig.json 中已經指定。當你嘗試編譯套件 foo 時,它使用的是 ./packages/foo/tsconfig.build.json,該檔案從未包含根配置或自行指定路徑,你可能想要從基礎 tscofig 中移除導入方案,並將它們添加到內部套件的配置中:

./packages/foo/tsconfig.build.json 應該納入這個:

{
  "compilerOptions": {
    "paths": {
      "@company/bar": [
        "../bar"
      ]
    }
  }
}

同樣地,如果需要,packages/bar/tsconfig.build.json 應該被允許匯入 @company/foo。