2023 使用 TypeScript + Node.js ESM 的使用体验.
截至 2023.8
可选方案
- ts-node
- tsx / @swc-node/core
- tsc
- tsup
ts-node
支持 esm, 需要
package.json
中type=module
,tsconfig.json
中{ts-node: {"esm": true}
node v20 还有新问题
https://github.com/TypeStrong/ts-node/issues/1997
其他问题
- tsconfig-paths 只支持 cjs https://github.com/dividab/tsconfig-paths/issues/243
- ts-node 准备自己实现, https://github.com/TypeStrong/ts-node/pull/1585 但是 years passed
tsx
- 支持 tsconfig.paths without config
- 但是发布有问题, 同 tsc
update when Node.js v20 become Active LTS
ts-node 依旧没有资源投入适配 node v20 module.register
API.
对于直接执行 ts file, tsx 是更好的选择.
发布
使用 TypeScript 编写的 cli 工具, 直接发布 TypeScript 源码, 发布需带上 tsconfig, 可以使用类似下面的代码
1
2
3
4
5
6
7
8
9// <project-root>/entry.mjs
import esmUtils from 'esm-utils'
import path from 'path'
const { __dirname } = esmUtils(import.meta)
process.env.ESBK_TSCONFIG_PATH = path.join(__dirname, 'tsconfig.json')
await import('tsx')
await import('./src/entry.ts')使用 dynamic import function 可以使
./src/entry.ts
使用上 esm loader 逻辑作为库, 不应发布 TypeScript. 因为使用库的项目不一定使用 TypeScript, 就算用很可能 tsconfig 不同, 而无法使用项目的 tsconfig 编译库包含的 TypeScript 代码
工具链的更改
vscode code-runner 更改
1 | "code-runner.executorMap": { |
tsc
开发可以用
tsc --watch --incremental
速度还可以可以正常发布
不支持 tsconfig.paths 编译
typescript-transform-paths 只支持 cjs, esm on the way https://github.com/LeDDGroup/typescript-transform-paths/issues/134 但同样是 years passed. 同时依赖 ttypescript / ts-patch 等修改版的 TypeScript 编译器.
TypeScript 5.2 在考虑增加 custom transform
tsup
体验下来比较爽的方案
- 基于 esbuild, dev
tsup --watch
很快 - 支持 tsconfig.paths 解析
- 由于发布 bundle 代码, 不存在运行时解析 tsconfig.paths
目前我的几个 cli 都是基于这个方案改造成了 esm
- yun-playlist-downloader
- handy-img
- …more