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 引用,并像导入包依赖一样简单地读取它。
