How do Downstream Toolchain Handle tsconfig.json
?
esbuild
专注于提供极致的构建性能,而将复杂的类型检查留给专门的工具。在现代前端工程化实践中,这种职责分离是完全合理的架构决策。
esbuild
在构建阶段并不会完全尊重项目中的 tsconfig.json
配置模块,仅有特定的 tsconfig.json
字段会被尊重。
在打包过程中,esbuild
中的 路径解析算法 将考虑 tsconfig.json
文件内容,其中 esbuild
会使用最靠近父目录的 tsconfig.json
文件,修改其行为。
在构建阶段可以使用 esbuild
的 build api
,通过 tsconfig
字段 显式指定 tsconfig.json
文件的路径。
在编译阶段可以使用 transform api
,通过 tsconfigRaw
字段 显式传入 tsconfig.json
文件的内容。
然而,esbuild
目前仅尊重 tsconfig.json
文件中的以下字段,其他的字段会被忽略掉。
Decorator
Reference Materials
此选项启用用来对 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
包含早于 ES2022
的 target
,则默认为 false
。但我建议如果你需要它,请显式设置 useDefineForClassFields
,而不是依赖于来自 target
设置值的默认值。请注意,tsconfig.json
中的 target
设置仅供 esbuild
用于确定 useDefineForClassFields
的默认值。它不会影响 esbuild
自己的 target
设置,尽管它们有相同的名称。
Path Resolution
这些选项影响 esbuild
将 import/require
路径解析到文件系统上的文件的方式。你可以使用他们来定义包别名并以其他方式重写导入路径。
请注意,使用 esbuild
进行导入路径转换需要 启用打包,因为 esbuild
的路径解析过程仅在打包期间发生。还要注意,esbuild
也有一个原生的 别名特性,你可能想要使用它。
JSX Transformation
这些选项影响 esbuild
将 jsx
语法转换为 javascript
的过程。它们相当于 esbuild
的原生选项:jsx
、jsxFactory
、jsxFragment
和 jsxImportSource
。这些选项影响 esbuild
将 jsx
语法转换为 javascript
的过程。它们相当于 esbuild
的原生选项:jsx
、jsxFactory
、jsxFragment
和 jsxImportSource
。
Strict Mode
如果启用了这些选项中的任何一个,esbuild
将认为所有 TypeScript
文件中的所有代码都处于严格模式,并会在生成的代码前加上 "use strict"
,除非输出格式设置为 esm
(因为所有 esm
模块默认处于 严格模式)。
Import Side Effect Control
默认情况下,typescript
编译器在将 typescript
转换为 javascript
时会删除未使用的导入。因此这导致了若模块仅依赖其他模块的类型(类型导入
),意外地成为仅类型导入的导入不会在运行时导致错误。esbuild
也实现了这一行为。
这些选项允许你禁用此行为并保留未使用的依赖导入,如果依赖导入的模块有副作用,这可能很有用。你应该为此使用 verbatimModuleSyntax
,因为它替代了较旧的 importsNotUsedAsValues
和 preserveValueImports
设置(TypeScript
现在已废弃)。
Configure Extensions
Reference Materials
此选项允许你将 tsconfig.json
文件拆分为多个文件。此值可以是单一继承的字符串,也可以是多重继承的数组(typescript
5.0+ 中的新功能)。
Others
所有其他 tsconfig.json
字段(即不在上述列表中的字段)将被忽略。
Summary
- 关注转译而非类型检查:
esbuild
重点支持 影响代码转译 和 模块解析 的配置,而不是类型系统的配置。这符合其作为高性能打包工具的定位。 - 性能取舍:通过只关注少量必要的字段,
esbuild
能保持其卓越的性能优势。完整支持typescript
配置会带来额外的复杂性和性能开销。 - 实用主义方法:支持的字段基本都直接影响生成代码的行为或模块解析,这些是打包过程中最核心的环节。
- 与原生功能的重叠:一些
tsconfig
字段(如jsx
相关配置)与esbuild
自身的配置选项重叠,为开发者提供了灵活性。 - 新标准支持不完整:值得注意的是,
esbuild
尚未实现新的装饰器设计,这可能会影响使用最新装饰器语法的项目。
实践认知:
若使用 esbuild
来打包 ts
项目。
- 可以使用
tsc
进行类型检查,esbuild
负责转译和打包,发挥各自优势。 - 同时需要注意 装饰器兼容性问题,特别是使用新装饰器语法的项目。
- 在
CI
流程中,将类型检查和构建分为独立步骤,充分利用esbuild
的速度优势。