ES module in Node.ts
动机
- 尊重标准
- 10 Things I Regret About Node.js — Ryan Dahl
- #7: Require without the extension
理想状态
- 所有项目保持一致,
"import/extensions": ["error", "always"]
- 例:
scripts/build.js 使用 native ES module tsc ts-node
- 例:
api/server.ts 使用 ES module + tsc
- 原则上,不首先使用奇技淫巧,不首先制造轮子
- 原则上,不使用
.cjs/.mjs (滑稽)
- 最好能:
import {sum} from './math.ts'
- 也行吧:
import {sum} from './math' transpile to import {sum} from './math.js'
心路历程
- 工具链支持 import
.ts (Webpack/Rollup/esbuild/metro/ESLint)
- tsc 不支持
- 最多让你写
.js
- tsc:
An import path cannot end with a '.ts' extension. Consider importing './sum' instead (TS2691)
- ✅ 那就 import js,恶心就恶心点
import type {FooType} from './types.js' // types.d.ts 🤮
- ❌ 不完美
- 其他工具解析带扩展的引用,依据的是 文件是否存在,也就不能
import 不存在的 math.js(源文件为 math.ts)
metro
ts-node
vite // esbuild, rollup
- 也许可以 hack,但是违背了第一原则
- 也就不可能达成:所有项目保持一致
其他可能
- ttypescript/tsc-silent/... // 缺乏维护,无 IDE 支持
- @ts-ignore // 无法接受,每个 import 上面都得加
- 不写扩展名,看看 tsc (
"module": "esnext") 会不会帮我们加上 // 没有+不会有:"it is not our goal" 🐂
- 不写扩展名,use ncc/Rollup/esbuild as node bundler // 仍然需要 tsc 做约束,况且我已经用了 nft
结论
- 选用 渐进式恶心
- 纯 Node.ts,
import .js
- Next.js/Vite/React-Native,省略扩展
- ES module 标准推进太慢浪费时间
- ES module 采纳率堪忧
- 大部分常用项目都会提供 esm 文件,并采用
"module" 申明 entry point 供 bundler 选用
- 但 Node.js 实际上并不 respect top-level
"module" 字段
- 你得用
"type": "module" (或许还得用 conditional exports)
- 由于 Node.js 可以混用 CommonJS/ES module,社区可能也就没动力采纳(又不是不能用)
- 将进入漫长的半殖民地半封建社会
- long live Compile to JS
- Deno 👀