es modules(esm)在ssr中导入的关键是运行环境支持与模块解析方式:node.js需v12.20.0+并满足.mjs扩展名、"type": "module"或--input-type=module任一条件,ssr框架如next.js、nuxt、remix对esm有差异化支持,需注意服务端执行约束、第三方库兼容性及构建产物模块格式一致性。

ES Modules(ESM)在服务端渲染(SSR)中导入,关键在于运行环境支持和模块解析方式。Node.js 从 v12.20.0+ 默认支持 ESM,但 SSR 框架(如 Next.js、Nuxt、Remix)对 ESM 的处理逻辑各有差异,不能直接照搬浏览器写法。
确认运行时是否启用 ESM
Node.js 中启用 ESM 需满足以下任一条件:
- 文件扩展名为 .mjs(优先级最高)
- package.json 中声明 "type": "module"
- 启动时加参数 --input-type=module(仅适用于 inline 脚本)
⚠️ 注意:一旦启用 ESM,CommonJS(require)不能混用于同一文件;若需动态加载 CJS 模块,要用 import() 动态导入或 createRequire 兼容。
SSR 框架中的 ESM 导入实践
主流框架已逐步支持 ESM,但导入位置和时机有约束:
-
Next.js(v13+ App Router):默认使用 ESM,
page.tsx、layout.tsx等可直接import,但getServerSideProps已弃用,改用generateStaticParams或组件内async server components;服务端代码必须运行在server环境(通过"use server"或server-only包校验) -
Nuxt 3:全栈基于 ESM,
server/api/和server/utils/下的文件天然为服务端执行,可自由importESM 包(包括本地模块和纯 ESM 第三方库,如zod、drizzle-orm) -
Remix:路由文件(
route.tsx)默认为 ESM;loader/action 函数中可同步import,但注意:动态import()在 loader 中会触发流式响应,需确保返回的是 Promise 并正确 await
第三方 ESM 库的兼容处理
部分 npm 包只发布 ESM(无 CommonJS 入口),在 SSR 中可能报错 ERR_REQUIRE_ESM。解决方法:
- 检查包是否有
exports字段且包含"import"入口;若有,直接import即可 - 若包未提供
exports但含type: "module",确保你的项目也启用 ESM(避免混合模块系统) - 遇到
__dirname或require.resolve报错?改用 ESM 原生替代:import { fileURLToPath } from 'url';<br> import { dirname } from 'path';<br> const __filename = fileURLToName(import.meta.url);<br> const __dirname = dirname(__filename);
构建与打包时的注意事项
即使源码用 ESM,SSR 构建产物仍可能转为 CommonJS(如某些 Webpack 配置)。要确保:
- 构建工具(Vite、esbuild、SWC)输出目标设为
nodeX.Y且保留type: "module" - 生成的入口文件(如
.next/server/pages/xxx.js)头部不被注入require相关代码 - 使用
node --conditions development启动时,确保package.json的exports正确匹配条件(如"development"、"production")
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











