一个可用的 Node、TypeScript、TS-Node 和 ESM 体验
Node.js 开发者表示,在将 TypeScript、`ts-node` 和 ECMAScript 模块结合使用时会遇到明显阻力,尤其是当项目涉及 monorepo、Jest 之类的测试框架以及复杂依赖树时。许多人认为,那些看似“开箱即用”的样板配置掩盖了重要复杂性,因此更倾向于使用更简单的工具,如 `tsx`、Vitest,甚至 Deno 和 Bun 这类试图让 TypeScript 与 ESM 支持更顺滑的替代运行时。也有人反驳说,只要配置得当,这套技术栈是可以稳定工作的,但同时承认,糟糕的互操作性、不断变化的标准,以及围绕模块解析的薄弱文档,让当前生态变得异常脆弱。
关于 Node + TypeScript + ESM 的总体感受
- 许多评论者表示,Node + TypeScript + ts-node + ESM 这套组合令人困惑、脆弱,而且充满边缘情况。
- 也有人说对他们来说这套组合“就是能用”,配置极少,因此不理解为什么别人会觉得困难。
- 还有不少人强调,真正的痛点往往是在加入多个包、子路径导入、测试运行器或 monorepo 之后才出现,而不是在玩具项目里。
ts-node 与 tsx 及其他 TS 运行器
- 很多人强烈支持用
tsx作为ts-node的替代品:更快、更好地处理 ESM、默认配置更简单。 - 有人以前在
tsx上遇到过问题(例如 Playwright、覆盖率),但表示最近的 v4 版本修复了其中很多问题。 - 提到的替代方案包括:
esno(现在基本上是tsx的别名)、tsm、node-dev、esyes。 - 也有人完全避开运行时转译器,偏好
tsc --build --watch再运行编译后的 JS。
测试、工具链与 monorepo
- Jest + TypeScript + ESM 被反复提及为令人痛苦;Vitest 经常被推荐为更顺手的替代方案。
- Node 内置测试运行器被认为很有前景,但它与 TS loader 和工具的集成仍然不够稳定。
- 使用 TypeScript、ESLint、Jest 以及混合 ESM/CJS 的 monorepo 被描述为“巫术”和脆弱;少数人分享了对他们来说可行的模板。
配置 vs 理解
- 争论焦点在于“直接照抄这些配置文件”与“理解每个选项的作用”之间的取舍。
- 有人认为,可运行的示例是最好的起点;也有人说这会滋生会在升级时出问题的“供奉式”配置。
- 有人抱怨 TS/Node 生态缺少优秀的“解释型”文档,无法说明模块解析和 tsconfig 选项如何相互影响,尤其是在 ESM 下。
ESM 设计与生态摩擦
- 很多人将生态分裂归咎于 Node 的 ESM 实现(CJS/ESM 不兼容、
type: module、失去__dirname、子路径导出问题)。 - 也有人认为 TypeScript 和 Jest 等工具多年里都没有及时支持 ESM,尽管早已得到警告。
- 一些人对 ESM 设计本身提出强烈批评,认为 CommonJS 更简单且“已经足够好”;另一些人则反驳说,声明式 ESM 能带来更好的优化,以及更接近浏览器原生模块。
替代方案:Deno 和 Bun
- Deno 因“开箱即用”的 TypeScript、内置工具和安全性而受到赞扬,但生态兼容性(尤其是 npm)和一些怪癖仍然存在。
- Bun 被看作能神奇地缓和 ESM/CJS 问题并提供极佳 DX,但它也非常新且仍有 bug;许多人在生产环境中使用它时仍持观望态度。