Skip to content

How do Downstream Toolchain Handle tsconfig.json?

esbuild

专注于提供极致的构建性能,而将复杂的类型检查留给专门的工具。在现代前端工程化实践中,这种职责分离是完全合理的架构决策。

esbuild 在构建阶段并不会完全尊重项目中的 tsconfig.json 配置模块,仅有特定的 tsconfig.json 字段会被尊重。

在打包过程中,esbuild 中的 路径解析算法 将考虑 tsconfig.json 文件内容,其中 esbuild 会使用最靠近父目录的 tsconfig.json 文件,修改其行为。

在构建阶段可以使用 esbuildbuild api,通过 tsconfig 字段 显式指定 tsconfig.json 文件的路径。

在编译阶段可以使用 transform api,通过 tsconfigRaw 字段 显式传入 tsconfig.json 文件的内容。

然而,esbuild 目前仅尊重 tsconfig.json 文件中的以下字段,其他的字段会被忽略掉。

Decorator

Reference Materials

experimentalDecorators

此选项启用用来对 typescript 模块中装饰器语法进行转换。当启用 experimentalDecorators 时,转换遵循 typescript 本身遵循的过时装饰器设计。

请注意,javascript 正在添加一种更新的装饰器设计,当 experimentalDecorators 被禁用时,typescript 也会采用这种设计。这不是 esbuild 目前实现的功能,因此当 experimentalDecorators 被禁用时,esbuild 目前不会转换装饰器。

Class Fields

这些选项控制 typescript 文件中的类字段是使用 define 语义还是 assign 语义进行编译:

  • Define 语义(esbuild 的默认行为):typescript 类字段的行为类似于普通 javascript 类字段。字段初始化器不会触发基类上的 setter。你应该在将来编写所有新代码时采用这种方式。
  • Assign 语义(需要显式启用):esbuild 模拟 typescript 的传统类字段行为。字段初始化器将触发基类 setter。这可能是运行传统代码所必需的。

esbuild 中禁用 define 语义(因此启用 assign 语义)的方法与在 typescript 中禁用它的方法相同:在 tsconfig.json 文件中将 useDefineForClassFields 设置为 false。为了与 typescript 兼容,esbuild 还复制了 typescript 的行为,即当未指定 useDefineForClassFields 时,如果 tsconfig.json 包含早于 ES2022target,则默认为 false。但我建议如果你需要它,请显式设置 useDefineForClassFields,而不是依赖于来自 target 设置值的默认值。请注意,tsconfig.json 中的 target 设置仅供 esbuild 用于确定 useDefineForClassFields 的默认值。它不会影响 esbuild 自己的 target 设置,尽管它们有相同的名称。

Path Resolution

Reference Materials

baseUrl

paths

这些选项影响 esbuildimport/require 路径解析到文件系统上的文件的方式。你可以使用他们来定义包别名并以其他方式重写导入路径。

请注意,使用 esbuild 进行导入路径转换需要 启用打包,因为 esbuild 的路径解析过程仅在打包期间发生。还要注意,esbuild 也有一个原生的 别名特性,你可能想要使用它。

JSX Transformation

这些选项影响 esbuildjsx 语法转换为 javascript 的过程。它们相当于 esbuild 的原生选项:jsxjsxFactoryjsxFragmentjsxImportSource。这些选项影响 esbuildjsx 语法转换为 javascript 的过程。它们相当于 esbuild 的原生选项:jsxjsxFactoryjsxFragmentjsxImportSource

Strict Mode

Reference Materials

alwaysStrict

strict

如果启用了这些选项中的任何一个,esbuild 将认为所有 TypeScript 文件中的所有代码都处于严格模式,并会在生成的代码前加上 "use strict",除非输出格式设置为 esm(因为所有 esm 模块默认处于 严格模式)。

Import Side Effect Control

默认情况下,typescript 编译器在将 typescript 转换为 javascript 时会删除未使用的导入。因此这导致了若模块仅依赖其他模块的类型(类型导入),意外地成为仅类型导入的导入不会在运行时导致错误。esbuild 也实现了这一行为。

这些选项允许你禁用此行为并保留未使用的依赖导入,如果依赖导入的模块有副作用,这可能很有用。你应该为此使用 verbatimModuleSyntax,因为它替代了较旧的 importsNotUsedAsValuespreserveValueImports 设置(TypeScript 现在已废弃)。

Configure Extensions

Reference Materials

extends

此选项允许你将 tsconfig.json 文件拆分为多个文件。此值可以是单一继承的字符串,也可以是多重继承的数组(typescript 5.0+ 中的新功能)。

Others

所有其他 tsconfig.json 字段(即不在上述列表中的字段)将被忽略。

Summary

  • 关注转译而非类型检查esbuild 重点支持 影响代码转译模块解析 的配置,而不是类型系统的配置。这符合其作为高性能打包工具的定位。
  • 性能取舍:通过只关注少量必要的字段,esbuild 能保持其卓越的性能优势。完整支持 typescript 配置会带来额外的复杂性和性能开销
  • 实用主义方法:支持的字段基本都直接影响生成代码的行为或模块解析,这些是打包过程中最核心的环节
  • 与原生功能的重叠:一些 tsconfig 字段(如 jsx 相关配置)与 esbuild 自身的配置选项重叠,为开发者提供了灵活性。
  • 新标准支持不完整:值得注意的是,esbuild 尚未实现新的装饰器设计,这可能会影响使用最新装饰器语法的项目。

实践认知:

若使用 esbuild 来打包 ts 项目。

  1. 可以使用 tsc 进行类型检查,esbuild 负责转译和打包,发挥各自优势
  2. 同时需要注意 装饰器兼容性问题,特别是使用新装饰器语法的项目。
  3. CI 流程中,将类型检查和构建分为独立步骤,充分利用 esbuild 的速度优势。

@rollup/plugin-typescript

Contributors

Changelog

Discuss

Released under the CC BY-SA 4.0 License. (2619af4)