JavaScript模块化无唯一主流方案:浏览器端优先ES Module(需type="module"和.js后缀),Node.js v14+默认支持但需配置"type":"module"或.mjs,CommonJS仍广泛用于工具链动态加载,混用时存在兼容限制。

JavaScript 模块化开发没有“唯一主流方案”,只有不同场景下更合适的选择:浏览器端优先用 ES Module(原生支持、静态分析强),Node.js 从 v14+ 起也默认支持 ES Module,但仍有大量旧项目依赖 CommonJS;构建工具链中 Rollup 偏爱 ESM 输出,Webpack 则两者都兼容但默认处理 CommonJS 更成熟。
浏览器里直接用 import/export 就行,但要注意 .js 后缀和 type="module"
现代浏览器(Chrome 61+、Firefox 60+、Safari 11.1+)原生支持 ES Module,但必须满足两个硬性条件:
-
标签要加type="module"属性,否则会忽略import/export -
import路径必须是完整 URL 或带后缀的相对路径,比如import { foo } from './utils.js'—— 缺少.js会报404,不支持 Node 风格的自动解析 - 顶层
this是undefined,且模块作用域天然严格模式,无法用var声明全局变量
示例:
Node.js 里用 ES Module 要注意 package.json 的 "type" 字段
Node.js 默认把 .js 文件当 CommonJS 处理。启用 ES Module 有两种方式:
- 在
package.json中声明"type": "module",此后所有.js文件按 ESM 解析(包括require()会报错) - 或用
.mjs扩展名,无需改配置,Node 会强制按 ESM 加载 -
import路径不能省略扩展名(./utils不行,得写./utils.js或./utils.mjs),也不能用 Node 内置模块简写(import fs from 'fs'会失败,得用import * as fs from 'fs')
CommonJS 还没淘汰,尤其在 require() 动态加载和工具脚本里很常见
CommonJS(module.exports/require())仍是很多 Node 工具链的底层选择,比如 webpack.config.js、jest.config.js 默认是 CJS 模块,因为支持动态路径拼接和运行时条件判断:
KesionCMS是漳州科兴信息技术有限公司开发的一套万能建站产品,是CMS行业最流行的网站建设解决方案之一。最新版X1.0把主系统及一些辅助系统模块化开发,前后台UI采用HTML5全新架构,方便随时删除(隐藏)安装所需要的模块。应广大用户群体建议,此次版本改动所有涉及编辑器和视频播放的模块,全部采用百度编辑器(ueditor)及ckplayer视频播放器,改进后的视频(flv,mp4等格式视频)
const env = process.env.NODE_ENV;
const config = require(`./webpack.${env}.js`); // ✅ CommonJS 支持而 ES Module 的 import 必须是静态字符串,上面这种写法会报 Cannot use import statement outside a module 错误。另外,CJS 模块的 require.resolve() 和 require.cache 在插件开发中仍不可替代。
混用 ESM 和 CommonJS 时,__dirname、__filename 和 require 不可用
一旦用了 type="module" 或 .mjs,Node 就禁用 __dirname、__filename 和全局 require。想获取当前目录需改用:
import { fileURLToPath } from 'url';const __filename = fileURLToPath(import.meta.url);const __dirname = path.dirname(__filename);
想在 ESM 中加载 CJS 模块(如 lodash),可以用 import _ from 'lodash'(Node 自动适配),但反过来——在 CJS 里 require() 一个 ESM 文件——会直接报错:ERR_REQUIRE_ESM。这时只能靠构建工具(如 esbuild)提前转译,或改用 dynamic import()(返回 Promise)。
真正容易被忽略的是:模块解析规则在不同环境间不一致——浏览器不认 node_modules 自动查找,Node 的 exports 字段又可能屏蔽 ESM 入口,而 Webpack/Vite 的别名配置又各自为政。选方案前,先确认你的运行时环境、依赖包的导出方式(看它的 package.json 中 exports 或 main/module 字段),比盲目套教程更重要。










