网站搜索

reactjs - Typescript pnpm 多包仓库,本地依赖在构建期间路径别名冲突


我有一个使用 TurbeRepo monorepo 的 PNPM,使用了这个模板。在这个 monorepo 中,我有一个使用 ui-shared 包(本地共享代码,实际上不是 npm 包)的 NextJS 应用。

ui-shared 的制作方式类似,但我的包当然要大得多。它有一个 index.ts 文件,导出所有组件和共享工具。

更新:添加了一个可以重现问题的最小仓库

在构建 ui-shared 时,它可以成功构建,但当我构建 Nextjs 应用时,ui-shared 构建失败,因为它无法解析来自 tsconfig 的路径。经过几天的排查,我成功找出了我认为的问题所在。当 Next 应用构建时,它也会构建 ui-shared,而这会失败,因为路径现在是基于 Nextjs 的,而不是库本身。我不确定这是不是原因,但我认为是,而且我不知道该如何解决。

(共享包或包是我将用来指代 ui-shared 的方式)

构建共享包结果成功

ESM ⚡️ Build success in 112ms
ESM dist/index.mjs 220.69 KB
DTS Build start
DTS ⚡️ Build success in 4792ms

package.json 的部分

  "main": "./src/index.ts",
  "module": "./dist/index.mjs",
  "types": "./src/index.ts",
  "scripts": {
    "lint": "eslint *.ts*",
    "build": "tsup ./src/index.ts --format esm,cjs --dts --external react",
    "dev": "tsup ./src/index.ts --format esm,cjs --watch --dts --external react"
  },

该包的 tsconfig

{
  "extends": "tsconfig/react-library.json",
  "compilerOptions": {
    "baseUrl": ".",
    "resolveJsonModule": true,
    "allowJs": true,
    "paths": {
      "@/*": ["src/*"]
    }
  },
  "include": ["**/*.ts", "**/*.tsx"],
  "exclude": ["dist", "build", "node_modules"]
}

当我运行 NextJs 应用的构建时,我遇到这个错误

pnpm build

> @company/[email  build /work/company/monorepo/apps/business
> next build

See more info here: https://nextjs.org/docs/messages/invalid-next-config
info  - Skipping linting
info  - Checking validity of types .Failed to compile.

../../packages/ui-shared/src/components/AnimatedLoadingMedia.tsx:9:23
Type error: Cannot find module '@/utils/clsxm' or its corresponding type declarations.

   7 | } from "react";
   8 | 
>  9 | import { clsxm } from "@/utils/clsxm";
     |                       ^
  10 | 
  11 | type AnimatedLoadingMediaProps = {
  12 |   isVideo: boolean;

> Build error occurred
Error: Call retries were exceeded
    at ChildProcessWorker.initialize (/work/company/monorepo/node_modules/.pnpm/[email _twoewwu6sg7cdf3ao6njtbftne/node_modules/next/dist/compiled/jest-worker/index.js:1:11661)
    at ChildProcessWorker._onExit (/work/company/monorepo/node_modules/.pnpm/[email _twoewwu6sg7cdf3ao6njtbftne/node_modules/next/dist/compiled/jest-worker/index.js:1:12599)
    at ChildProcess.emit (node:events:390:28)
    at Process.ChildProcess._handle.onexit (node:internal/child_process:290:12) {
  type: 'WorkerError'
}

Nextjs 应用 tsconfig

{
  "extends": "tsconfig/nextjs.json",
  "compilerOptions": {
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "baseUrl": ".",
    "module": "esnext",
    "paths": {
      "@/*": ["src/*"],
      "@": ["src"],
      "@public/*": ["public/*"],
      "@public": ["public"]
    },
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

在用 nextjs 构建时,库必须以某种方式解析自己的路径。或者更好的是,库应该在自己的作用域内构建,而 nextjs 只消耗输出。我不知道是否可以这样工作

我尝试过添加第三方库,比如 tsc-alias、tsconfig-path 等等。但构建还是一直失败。我试着查看并想要某种方式阻止 Next.js 构建这个包,但我找不到方法。

答案#1

在花了很多小时为这件事绞尽脑汁之后,我最终只是直接把包名本身作为别名使用。

package.json:

{
  "name": "@pkg/utils",
  ...
}

tsconfig:

"baseUrl": ".",
"paths": {
  "@pkg/utils/*": ["./src/*"]
}
// /packages/utils/src/bar.ts
import someSiblingUtil from '@pkg/utils/foo.util';

不完全确定,但我认为之所以这样工作的原因是,当包本身导入该文件时,它使用 ./src 别名,但当它被导入到依赖它的应用程序中时,应用程序看到 @pkg/utils 引用,并像导入包依赖一样简单地读取它。

相关文章