返回博客

你可能不需要 TypeScript 项目引用

Jared Palmer
姓名
Jared Palmer
X
@jaredpalmer

如果你在较大的 TypeScript 代码库或 monorepo 中工作过,你可能对项目引用非常熟悉。它们确实非常强大。

当你在 tsconfig.json 中引用一个项目时,会发生一些新的事情

听起来很棒!对吧?!嗯...也许吧。一旦你向项目添加了引用,你现在就需要在每次添加或删除包时不断更新它们。这有点糟糕。

嗯...如果你不需要这样做呢?

“内部”TypeScript 包

事实证明,你甚至可能不需要引用,也不需要我即将向你展示的这种模式的中间 TypeScript 构建步骤,我将其称为“内部包”。

“内部包”是一个没有 tsconfig.json 的 TypeScript 包,其 package.json 中的 typesmain 字段都指向该包的未转译入口点(例如 ./src/index.tsx)。

package.json
{
  "name": "@sample/my-internal-package"
  "main": "./src/index.ts"
  "types": "./src/index.ts", // yes, this works!
  "dependencies": {
    ...
  },
  "devDependencies": {
    ...
  }
}

事实证明,TypeScript 语言服务器 (在 VSCode 中) 和类型检查器可以将原始的 .ts.tsx 文件视为其自己的有效类型声明。最后这句话当你读两遍时就很明显了。但不太明显的是,你可以将 types 字段直接指向原始源代码。

一旦你这样做,只要你遵守 2 条规则,就可以无需项目引用或 TypeScript 构建步骤(通过 tscesbuild 等)来使用此包

据我所知,无论你是否使用 Turborepo 或其他工具,这种内部包模式都适用于所有 yarn/npm/pnpm 工作区实现。我个人使用几种不同的元框架测试过这种模式(见下文),但我确信它也适用于其他框架。

Next.js

Next.js 13 可以自动转译和捆绑来自本地包(如 monorepo)或外部依赖项 (node_modules) 的依赖项。

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  transpilePackages: ['@acme/ui', 'lodash-es'],
};
 
module.exports = nextConfig;

从 Next.js 13.1 开始,你不再需要 next-transpile-modules 包。有关更多信息,请访问 Next.js 内置模块转译博客文章。

Vite

内部包可以直接使用。不需要额外的配置。

React Native

如果你使用 Expo 并使用 expo-yarn-workspaces@turborepo/adapter-expo 包,只要你的目标是 iOS 或 Android,就可以使用内部包。当你为这些平台运行 Expo 时,所有 node_modules 都会使用 Metro 自动转译。但是,如果你的目标是用于 Web 的 Expo,内部包将不起作用,因为 node_modules 很奇怪地没有为 Web 转译。

我已就这种不一致之处联系了 Expo 团队。他们意识到了这个问题。我被告知这是一个遗留问题。

这种模式的优点

这种模式很棒,因为它使你免于额外的、不必要的或重复的构建步骤。它还为你提供了项目引用的所有编辑器优点,但无需任何配置。

注意事项

当你使用内部包时,这有点像告诉消费应用程序你有另一个源目录——这有利有弊。随着你的消费应用程序的增长,添加更多内部包与向该消费应用程序添加更多源代码是相同的。因此,当你添加更多源代码时,会有更多的代码需要转译/捆绑/类型检查...因此,这可能会导致消费应用程序的构建速度变慢(因为需要做更多的工作),但可能会更快(且更简单)地完成整体构建时间。当/如果整体构建时间开始变长时,你可能会决定将较大的内部包转换回带有 .d.ts 文件和正常 TypeScript 构建步骤的“常规”包。

如前所述,这种模式实际上与 Turborepo 没有什么关系。它只是非常非常棒,我认为你应该知道它。由于我们正在积极开发 Turborepo 的预设包构建规则(即“构建器”),我们将使用内部包模式来跳过构建步骤。

说到漫长的构建时间...

这里厚颜无耻地宣传一下。如果你正在阅读这篇文章,并且你正在为缓慢的构建和测试时间而苦恼,我很乐意向你展示 Turborepo 如何提供帮助。我保证 Turborepo 会将你的 monorepo 的构建时间缩短 50% 或更多。你可以在这里申请现场演示。