ES module in Node.ts

@hehe

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 👀