← [ BACK_TO_NOTES ]

TypeScript 中的 nodenext 与 bundler

对比 nodenext 与 bundler 两种模块解析思路,解释它们分别更接近 Node.js 还是现代 bundler,以及各自适用项目类型。

#dev #typescript #synthesis #growing

[!info] related notes

TypeScript 中的 nodenext 与 bundler

一句话定义

  • nodenext:尽量模拟现代 Node.js 自己的模块解析规则
  • bundler:尽量模拟 Vite / Webpack / Rollup / esbuild 等现代 bundler 的模块解析规则

核心机制 / 工作原理

nodenext

更接近真实 Node.js 运行时,尤其要处理:

  • CommonJS 与 ESM 并存
  • package.json type
  • exports / imports
  • 相对路径扩展名要求

bundler

更接近现代 bundler 开发体验,通常支持:

  • 无扩展名相对路径
  • exports / imports
  • node_modules
  • 更宽松的相对路径解析习惯

最小例子 / 最小场景

bundler

在很多 bundler 项目里,这样常见且可接受:

import { foo } from "./foo";

nodenext

如果当前文件会按 Node ESM 规则运行,更常需要写成:

import { foo } from "./foo.js";

即使源码文件实际是 foo.ts,TypeScript 也会通过扩展名替换机制理解它。

常见适用场景

更适合 nodenext

  • Node 后端
  • CLI
  • 直接 tsc 编译后交给 Node 跑的项目
  • 发布给别人使用的 npm library

更适合 bundler

  • Vite / Webpack / Rollup / esbuild 前端项目
  • TypeScript 只做类型检查,真正 emit 交给 bundler 的项目

边界与易混淆点

bundler 更宽松,不代表更适合发布库

TypeScript 官方提醒过:如果你要发布 npm library,bundler 可能会隐藏那些“不经过 bundler 的消费者”在 Node 环境里会踩到的兼容问题。

nodenext 不是“只适合 ESM”

它描述的是现代 Node 的双模块系统,不是“单纯只输出 ES modules”。

TypeScript 5.2 之后更强调 module 与 moduleResolution 要匹配

例如:

  • module: "nodenext" 通常就该搭配 moduleResolution: "nodenext"
  • module: "esnext" 常和 moduleResolution: "bundler" 一起出现

参考信息

学习检查

不看正文回答:

  1. nodenext 与 bundler 分别在模拟谁的模块解析规则?
  2. 为什么前端 Vite 项目通常更适合 bundler,直接由 Node 运行的后端/CLI 更常考虑 nodenext?
  3. 为什么源码是 foo.ts 时,Node ESM 场景仍可能要求导入路径写 ./foo.js?
  4. 为什么发布 npm library 时不能只因为本地 bundler 项目工作正常就认为解析边界正确?
  5. module 与 moduleResolution 为什么需要作为一组配置理解?
创建于 2026/5/15 更新于 2026/9/30
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本