【亲测好用】全套CommonJS的最佳解决方案
【亲测好用】全套 CommonJS 最佳解决方案
一句话定位:CommonJS(CJS)是 Node.js 传统模块化,require/module.exports;痛点集中在Node ESM
混合报错、浏览器无法直接运行、库发布双包陷阱、循环依赖、打包兼容,下面是完整落地方案,覆盖业务项目、库开发、打包、避坑全套。
一、先分清:什么时候继续用 CommonJS
✅ 推荐 CJS 场景
老 Node 后端项目、CLI 工具、脚本工程,历史代码量大,迁移 ESM 成本高
依赖大量老旧 npm 包,包本身只提供 CJS
简单脚本,需要__dirname/__filename,不想额外处理 ESM 兼容
❌ 不推荐 CJS 场景
前端 Web 应用(Vue/React):优先 ESM,Tree-Shaking 效果更好
新开发开源库:优先 ESM;如需兼容旧项目再做分发
核心原则:一个项目内部统一模块类型,不要随意混合;Node 中package.json写"type":"commonjs",.js默认 CJS;.cjs强制 CJS,不受 type 字段影响webpack
二、方案 1:Node 项目纯 CommonJS(稳定首选)
package.json
{
"name": "cjs-demo",
"version": "1.0.0",
"type": "commonjs",
"main": "./index.js"
}
基础写法(标准,规避坑)
// lib.js
// ✅推荐:module.exports一次性导出,不要混用exports.xxx
module.exports = {
hello: () => "hello cjs",
num: 100
}
// index.js
const lib = require('./lib.js')
console.log(lib.hello())
❌坑:exports = {} 直接覆盖无效,exports 只是 module.exports 的引用。
读取文件路径(CJS 天然支持)
const path = require('path')
const fullPath = path.join(__dirname, './data.json')
运行命令
node index.js
三、方案 2:CJS 项目引入 ESM 包(最常见报错场景)
Node CJS 项目require()导入 ESM 包,直接报错。两套解决办法:
方案 A(推荐,简单):动态 import (),异步
// CJS index.js
async function run() {
const esmPkg = await import('esm-only-package')
console.log(esmPkg.default)
}
run()
方案 B:工具 esm 加载器(老项目临时兼容)
npm install esm
入口文件:
require = require("esm")(module);
const pkg = require("esm-package");
缺点:仅用于旧脚本,生产服务不推荐,性能有损耗。
四、方案 3:把 CommonJS 打包到浏览器运行(浏览器无 require)
浏览器原生不支持require(),必须打包。3 套亲测方案:
✅轻量首选:esbuild(速度最快)
npm install -D esbuild
# 打包CJS源码输出浏览器可用bundle
esbuild src/index.js --bundle --outfile=dist/bundle.js --format=iife
✅大型项目:Webpack5 处理 CJS
// webpack.config.js
const path = require('path')
module.exports = {
entry: './src/index.js',
output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js' },
resolve: {
extensions: ['.js','.cjs'],
// node内置模块浏览器fallback
fallback: { path: require.resolve("path-browserify") }
}
}
✅库打包:Rollup + @rollup/plugin-commonjs
Rollup 默认 ESM,加载 CJS 依赖必须开启commonjs插件,解决第三方 CJS 包导入问题。
五、方案 4:开源库发布,同时支持 CJS & ESM(安全双包方案)
重点规避双包陷阱(dual package hazard):同一依赖同时加载两份实例,单例失效Node.js。 package.json 配置:
{
"main": "./dist/index.cjs",
"exports": {
".": {
"require": "./dist/index.cjs",
"import": "./dist/index.mjs"
}
}
}
源码建议:一套 TS 源码,构建同时输出 .cjs + .mjs(tshy /tsup 一键生成)
最佳实践:尽量避免默认导出,优先命名导出,减少 interop default 坑npm
六、高频问题全套解决方案(亲测踩坑清单)
1. require 找不到文件
CJS require 路径必须写./相对路径;require('lib')优先 node_modules
后缀可省略:.js/.cjs/.json自动识别
2. 循环依赖(CJS 经典坑)
CJS 是运行时加载,循环依赖会拿到未完成的 exports。解决办法:
重构代码,消除循环依赖(首选)
把导入放到函数内部,延迟 require
3. ESM 导入 CJS 包 default 导出异常
// ESM中导入CJS模块
import pkg from './cjs.cjs'
// 等价于 const { default: pkg } = require('./cjs.cjs')
CJS 导出整体挂载在default,解构要注意:
import { foo } from './cjs.cjs' // 可以,打包工具自动代理
4. __dirname /__filename 在 ESM 不存在
如果你混用 / 迁移到 ESM,这两个变量消失;CJS 天然自带,这也是很多老脚本保留 CJS 的原因。
5. CJS 无法 Tree-Shaking
CJS 动态 require,编译期不能分析依赖,打包只能做模块级剔除,无法精细删除无用代码。
结论:前端业务代码尽量 ESM;CJS 适合 Node 后端、CLI 脚本。
七、迁移路线:CJS → ESM(渐进方案,不想一次性大改)
项目 package.json 先不动type:commonjs,新增.mjs文件写新模块
新模块用 ESM,通过import()动态加载老 CJS 模块
全部代码改造完成后,统一改为"type":"module",文件后缀改成.js
八、选型总结(快速决策)
Node 后端 / CLI 脚本旧项目:保持 CommonJS,package.json type=commonjs
Node 项目必须引入 ESM-only 包:使用async import()
CJS 代码跑浏览器:esbuild 快速打包;大型项目 Webpack
开发 npm 工具库:TS 源码构建输出双格式 cjs/mjs,配置 exports 字段
前端 Web 项目:直接 ESM,不要 CJS
-
【亲测好用】全套CommonJS的最佳解决方案【亲测好用】全套 CommonJS 最佳解决方案一句话定位:CommonJS(CJS)是 Node.js 传统模块化,require/module.exports;痛点集中在Node ESM 混合报错、浏览器无法直接运行、库发布双包陷阱、循环依赖、打包兼容,下面是完整落地方案,覆盖业务项目、库开发、打包、避坑全套。一、...
-
【亲测好用】跨域备忘单的最佳解决方案这是一份针对前端/全栈开发者的跨域(CORS)备忘单,覆盖原理、排查、解决方案与代码模板,建议收藏备用。一、 核心原理速查同源策略三要素:协议、域名、端口必须完全一致,任一不同即跨域。关键认知:跨域是浏览器的安全限制,请求本身能到达后端,但浏览...
-
JS搭建教程避坑指南:踩过的坑都给你标好了“零基础原生搭建”到“现代工程化搭建”,再到“后端 Node.js 搭建”的完整教程。你可以根据自己的学习目标选择对应的路线:一、 原生基础搭建(适合初学者练手)如果你是刚开始学习,建议先从最基础的 HTML、CSS 和 JS 组合开始,这能帮你建立清晰的认知框架。创...
-
入门Ionic在实际项目中的应用技巧结合你之前关注的 Typecho 响应式方案,可以看出你对前端工程化和跨端适配有不错的敏感度。Ionic 的核心正是利用 Web 技术栈(HTML/CSS/JS)构建跨平台应用,这种“一次编写,多端部署”的思路,对你来说应该很容易上手。第一步:环境搭建与项目初始化Ionic 的开发高度...
-
【推荐收藏】前端测试框架推荐全套资源大合集前端测试框架的选型,核心在于匹配你的项目技术栈、测试层级(单元、集成、E2E)以及团队现有的开发习惯。结合目前的主流趋势,为你梳理了以下核心推荐:单元测试:Jest vs VitestJest:前端单元测试的“老牌标杆”。开箱即用,快照测试和 Mock 能力极强,生态最完...
-
2026年Angular还值得学吗最新趋势与最佳实践关于“Angular 还值得学吗”这个问题,答案并不是绝对的“是”或“否”,而是取决于你的职业规划和目标项目类型。简单来说:如果你想进大厂、做大型企业级项目,Angular 依然是一个极具竞争力的“硬通货”;但如果你是想快速接单、做个人项目或初创公司,它可...