前端模块化指南:CJS 与 ESM 的区别与混用

1. 核心概念

  • CJS (CommonJS) :Node.js 的原生模块系统。
    • 语法require() 导入,module.exports 导出。
    • 特点:同步加载,主要用于服务端。
  • ESM (ECMAScript Modules) :JavaScript 的官方标准模块系统。
    • 语法import 导入,export 导出。
    • 特点:静态分析,异步加载,现代浏览器和前端开发的标准。

2. 如何判断项目类型?

查看项目根目录下的 package.json 文件:

  • "type": "module" :项目为 ESM 模式。
    • .js 文件被视为 ESM,必须使用 import/export
    • 如需使用 CJS,文件后缀必须改为 .cjs
  • 未设置 type"type": "commonjs" :项目为 CJS 模式(默认)。
    • .js 文件被视为 CJS,必须使用 require/module.exports
    • 如需使用 ESM,文件后缀必须改为 .mjs

3. 为什么 Vue 2 项目是 CJS,却能用 import?

这是最容易混淆的地方。项目分为两个"世界":

A. Node.js 构建环境

  • 运行者:Node.js 进程。
  • 受影响文件 :根目录配置文件(如 vue.config.js)、构建脚本(如 build/index.js)。
  • 规则 :受 package.jsontype 控制。如果是默认 CJS 项目,这些文件必须使用 require

B. 浏览器运行环境

  • 运行者:用户的浏览器。
  • 中间人:Webpack / Vite(构建工具)。
  • 受影响文件src/ 目录下的所有源码(.vue, .js 等)。
  • 规则 :不受 Node.js type 控制。构建工具会读取 src 下的代码,将 import 翻译成浏览器可执行的代码。因此,src 下请尽情使用 import

4. 实战判断法则:哪些文件能用 import?

不需要死记硬背,遵循以下逻辑:

法则一:看位置

  • src/ 目录下 :✅ 能用 import
    • 这是前端源码,由 Webpack/Vite 处理,默认支持 ESM。
  • 根目录配置文件 (如 vue.config.js):❌ 不能用 import
    • 这是 Node.js 脚本,受 package.json 控制。默认 CJS 下必须用 require

法则二:看后缀

  • .mjs :强制视为 ESM,必须用 import
  • .cjs :强制视为 CJS,必须用 require
  • .js :看 package.jsontype 设置(默认是 CJS)。

法则三:看报错(兜底)

  • 如果报错 SyntaxError: Cannot use import statement outside a ES module
    • 说明该文件由 Node.js 直接运行且处于 CJS 模式。
    • 解决 :将 import 改回 require,或者将文件后缀改为 .mjs(并在 package.json 开启 ESM)。

5. 图片导入总结

类型 位置 引用方式 说明
本地图片 src/assets import img from '...' 推荐。Webpack 会处理路径和优化。
静态资源 public/ /filename.ext 绝对路径,原封不动复制到 dist。
网络图片 服务器 'http://...' 直接绑定字符串 URL。

一句话总结

在 Vue 2 / Webpack 项目中,src 里写 import,根目录配置写 require 。如果不确定,试着用 import,报错了就改回来。

相关推荐
flash俊杰1 分钟前
Electron 桌面应用的进程模型:为什么 fork Next.js standalone
前端
沙蒿同学11 分钟前
我把架构约定编译成了会变红的测试:Wails v2 + Go + Vue3 桌面脚手架实战
前端·后端·github
cpolar技术支持14 分钟前
本地 Playwright 测试报告怎么远程复盘?Trace Viewer 跑起来后,用 cpolar 分享失败现场
前端·自动化测试·测试工具·cpolar·playwright
wordbaby14 分钟前
企业级后台管理系统路由设计与最佳实践指南
前端
胡志辉的博客23 分钟前
【完全开源】IP 纯净度检测 可一键部署到自己的CF
前端·javascript·chrome·ip·chromium
Hilaku1 小时前
作为面试官,我最怕遇到什么样的候选人?
前端·javascript·程序员
TiDi1 小时前
Pinia优化重复请求
前端
web3d5202 小时前
01-用 Leafletjs 10 分钟搭一张水利一张图(Vue3 + Vite 实战)
前端·javascript
晚安日记wanna2 小时前
Vue2 的 defineProperty 差在哪四层追问筛掉九成候选人
前端·vue.js·面试
TiDi2 小时前
吸顶导航交互实现
前端