Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: typescript lib path resolution for api-extractor in monorepo #360

Merged
merged 2 commits into from
Aug 6, 2024

Conversation

qwqcode
Copy link
Contributor

@qwqcode qwqcode commented Aug 2, 2024

该 PR 修复 Monorepo 项目中 vite-plugin-dts 对 TypeScript 依赖库路径获取的问题。

问题描述

Monorepo 项目的 Workspace Root 安装 TS 版本为 v5.5.4,在子项目中 vite-plugin-dts 没有正确获取 Workspace Root 的 TS(通过 debug 观察 libFolder 变量值为 undefined),而它使用了 api-extractor 内置的 TS v5.4.2 版本,如图:

SCR-20240802-mhnz SCR-20240802-miud

可能相关的 ISSUE:#266

问题触发条件

Monorepo 项目,如果 <WorkspaceRoot>/node_modules/typescript 存在,但子项目 <WorkspaceRoot>/packages/xxx/node_modules/typescript 不存在。

复现步骤

  1. 创建 Monorepo 并初始化 Node 子项目
  2. 在 Workspace Root 安装 typescript v5.5.4 (pnpm add -D --workspace-root typescript)
  3. 执行子项目的编译(pnpm -F vite-project build

复现代码

https://github.com/qwqcode/vite-plugin-dts-mre

clone 后给 node_modules 中的相关代码打上断点,通过 VSCode JS 调试终端执行 pnpm build

旧版实现

生成 dts 文件调用 @microsoft/api-extractorExtractor.invoke 方法会传递 typescriptCompilerFolder 参数,指定 TypeScript 库的路径:

typescriptCompilerFolder: libFolder ? resolve(libFolder) : undefined,

为了让 api-extractor 工具中调用的 TS 和用户开发环境的 TS 版本一致,需正确设置 typescriptCompilerFolder 参数。

如果为 undefined 则会默认使用 api-extractor 自带的 TS,与开发环境 TS 版本可能不符,从而导致问题。目前旧版在 Monorepo 项目下 libFolder 变量可能为 undefined

TS 库路径变量 libFolder 是通过字符串拼接得到的:

if (rollupTypes) {
logger.info(green(`${logPrefix} Start rollup declaration files...`))
let libFolder: string | undefined = resolve(root, 'node_modules/typescript')
if (!existsSync(libFolder)) {
if (root !== entryRoot) {
libFolder = resolve(entryRoot, 'node_modules/typescript')
if (!existsSync(libFolder)) libFolder = undefined
}
libFolder = undefined
}

新版实现

修改为通过调用 Node 的 API require.resolve('typescript') 获取编译时用户当前项目中安装的 TS 路径。

兼容性方面,为了同时兼容 ES Modules 和 CommonJS,使用 createRequire(import.meta.url) 获取 require 对象并调用 resolve 方法 1

为了保险起见,仍然通过 try catch 提供了 fallback 的解决方案,保留旧版的字符串拼接代码。

性能方面,libFolder 通过 require.resolve 只需在编译过程中获取一次。

已测试 TS 路径在 Monorepo 项目中也能正确获取:

SCR-20240802-mwih


其他可能的改进:通过更新日志发现 3.0.0-beta.2 版本将 libFolderPath 参数移除,目前 rollupTypes 功能不支持自定义 TS 库路径,可以考虑增加一个参数。

Footnotes

  1. 参考:https://stackoverflow.com/questions/54977743/do-require-resolve-for-es-modules

@qmhc qmhc merged commit da4af65 into qmhc:main Aug 6, 2024
4 checks passed
@qwqcode qwqcode deleted the fix/ts-path branch August 7, 2024 01:40
@thy486
Copy link

thy486 commented Aug 9, 2024

注意: Windows 环境下, /node_modules\/typescript.*/ 匹配不上

@qwqcode
Copy link
Contributor Author

qwqcode commented Aug 9, 2024

注意: Windows 环境下, /node_modules\/typescript.*/ 匹配不上

已在 PR #366 中修复 Win 环境下的问题

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants