如何打一个既支持cjs,又支持esm的npm包?

死磕Node模块兼容性,ESM和CJS我全都要! 在Node版本13.2.0(2019年)之前,我们一般使用CJS(CommonJS)模式在代码中引入包,它的加载是同步的,在整个模块加载完成后,才会执行后续代码。而ESM(ECMAScript Modules)最早在2015年就被使用在浏览器中,在script标签中增加type="module"这个属性,然后引入模块进行使用。在Node 13.2版本后,Node也支持使用ESM进行导入模块的操作,那么如何对其二者进行一个兼容?请接着往下看。 阅读详情

模块化是一个老生常谈的问题了,打包工具层出不穷。

那么,如何利用这些打包工具去打出既支持cjs,又支持esm的npm包呢。

这篇文章不涉及概念,是一些打包实测。

demo repo: https://github.com/FrankKai/npm-bundle-demo

可以clone下来,本地构建测试。

  • tsc
  • rollup
  • webpack
  • esbuild

tsc

  • tsconfig.json
  • tsconfig-esm.json
  • package.json
cjs

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2015",
    "module": "commonjs",
    "outDir": "./dist/cjs",
    "esModuleInterop": true,
    "moduleResolution": "node"
  }
}
esm

tsconfig-esm.json

{
  "extends": "./tsconfig.json",

  "compilerOptions": {
    "target": "es2015",
    "module": "es2015",
    "outDir": "./dist/esm",
    "moduleResolution": "node"
  }
}
package.json
{
  "main": "./dist/cjs/index.js",
  "module": "./dist/esm/index.js",
  "scripts": {
    "build": "rm -rf dist && tsc -p tsconfig.json && tsc -p tsconfig-esm.json"
  },
}

rollup

  • rollup.config.js
  • package.json
rollup.config.js
export default [
  {
    input: "src/index.js",
    output: [
      { file: "dist/index.cjs.js", format: "cjs" },
      { file: "dist/index.esm.js", format: "es" },
    ],
  },
];
package.json
{
  "main": "dist/index.cjs.js",
  "module": "dist/index.esm.js",
  "scripts": {
    "build": "rollup -c",
  },
}

webpack

  • webpack.config.js
  • package.json
webpack.config.js
const path = require("path");

module.exports = {
  mode: 'none',
  entry: {
    "index.cjs": {
      import: './src/index.js',
      library: {
        type: 'commonjs2',
      },

    },
    "index.esm": {
      import: './src/index.js',
      library: {
        type: 'module',
      },
    },
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: "[name].js",
    clean: true,
  },
  experiments: {
    outputModule: true
  }
};
package.json
{
  "main": "dist/index.cjs.js",
  "module": "dist/index.esm.js",
  "scripts": {
    "build": "webpack",
  },
  "devDependencies": {
    "webpack": "^5.38.1",
    "webpack-cli": "^4.7.2"
  }
}

esbuild

  • package.json
{
  "main": "dist/index.cjs.js",
  "module": "dist/index.esm.js",
  "scripts": {
    "esbuild:cjs": "esbuild ./src/index.js --bundle --outfile=dist/index.cjs.js --format=cjs",
    "esbuild:esm": "esbuild ./src/index.js --bundle --outfile=dist/index.esm.js --format=esm",
    "build": "npm run esbuild:cjs && npm run esbuild:esm"
  },
  "devDependencies": {
    "esbuild": "^0.14.49"
  },
}
如何创建一个同时支持 CommonJS(CJS)和 ECMAScript 模块(ESM)的 npm 包? CJS 是 Node.js 默认的模块系统,而 ESM 是在浏览器和现代 JavaScript 运行时环境中广泛使用的模块系统。需要注意的是,为了使你的包能够在浏览器环境中正常工作,你可能还需要在构建过程中进行其他的优化和转换。通过以上步骤,你的 npm 包将同时支持 CJS 和 ESM 模块系统。用户可以根据他们使用的环境选择适当的模块导入方式来使用你的包。接下来,安装一些必要的依赖项来帮助你在构建过程中处理模块系统的差异。的文件夹,并将你的源代码文件(例如。的文件,并在其中编写你的代码。 阅读详情

相关推荐

BAPI创建委外采购订单

使用BAPI BAPI_PO_CREATE1创建委外采购订单,组件为手工输入时,有几个点需要注意: 1、已通过CS01创建过BOM的物料,创建时会自动带出components。如果要修改当前组件清单,可以通过设置pocomponents-change_id = 'E’来实现 lv_sline = lv_sline + 1. ls_pocomponents-po_item = l_ebelp + 10. ls_pocomponents-ITEM_NO = l

Buffalo_soldier的博客 3260

基于MCP协议的NPM智能分析引擎:为AI编程助手赋能深度依赖管理

在现代前端与Node.js开发中,依赖管理是工程实践的核心环节,涉及包选择、安全审计、版本兼容性及性能影响评估等多个维度。其原理在于通过自动化工具对NPM生态的元数据进行结构化查询与分析,将分散的包信息、漏洞数据库、捆绑包指标等整合为可操作的决策依据。这项技术的核心价值在于实现“安全左移”与“效率提升”,将依赖评估环节前置到开发工作流中,通过实时、多维度的分析,帮助开发者在引入依赖前识别风险、对比方案。典型的应用场景包括技术栈升级的路径规划、新包引入的尽职调查、日常开发中的即时兼容性检查等。本文聚焦的`al

weixin_30635053的博客 370

IAR使用教程:如何导入现有工程并成功编译

详细介绍如何在IAR中导入现有工程项目并完成编译配置,解决常见报错问题。通过清晰的操作指引,帮助开发者快速上手iar使用教程中的关键环节,提升开发效率。

weixin_42437253的博客 883

Module Error (from ./node_modules/html-loader/dist/cjs.js) webpack 配置时的坑

安装html-loader 后发现报错 ERROR in Error: Child compilation failed: Module Error (from ./node_modules/html-loader/dist/cjs.js): HtmlSourceError: Bad value for attribute "href" on element "link": Must be non-empty (From line 13, column 32; to line 13, col

weixin_36508680的博客 3349

保姆级教程:用PyBullet和Stable-Baselines3搞定你的第一个机器人强化学习项目

本文提供了一份详细的PyBullet和Stable-Baselines3教程,帮助开发者快速上手机器人强化学习项目。通过环境配置、自定义Gym环境构建、PPO算法参数优化及模型部署的全流程解析,读者将掌握从零开始训练四足机器人 locomotion 任务的完整技术方案。

weixin_26861329的博客 420

理想L9高通QAM8797座舱域控制器全拆解|全网独家复现 硬件架构升级、电源散热优化、多屏低延迟交互、车机系统赋能高端智能座舱落地

随着智能汽车向舱驾一体、全域智能化、多模交互方向迭代,传统单一功能座舱芯片已无法满足多屏高刷渲染、全车AI语音、车内视觉感知、高速车载通信的叠加算力需求。2026款全新理想L9作为旗舰级智能SUV,全面搭载高通新一代旗舰座舱域控制器QAM8797,搭配自研马赫M100 AI芯片、国产车规主控芯片,构建起高性能、高可靠、低延迟的车载中央计算平台。

getusushu的博客 378

错误解决 node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules

一、问题如图 意思是后面的文件里缺少 前者的引入 二、问题如图 解决办法也是将iconfont文件插入到vue文件里

qq_37766810的博客 4万+

CloudCompare 二次开发(17)——点云添加均匀分布的随机噪声

使用CloudCompare编程实现点云添加随机噪声。

点云侠的博客 840

./node_modules/cache-loader/dist/cjs.js??ref--13-0!./node_modules/thread-loader/dist/cjs.js!

npm run build打包报错

weixin_44331330的博客 1万+

知识图谱-KGE-语义匹配-双线性模型-2018:SimplE

【paper】 SimplE Embedding for Link Prediction in Knowledge Graphs 【简介】 本文是加拿大英属哥伦比亚大学的两位学者发表在 NIPS 2018 上的工作,文章提出了 SimplE(Simple Embedding)。这篇和前面一篇差不多,也是对 1927 年的 CP 进行改进(简化),传统CP为实体分配的两个向量是独立训练的,SimplE利用关系的逆在三元组打分函数中加上了一个对称项,使得每个实体的两个向量依赖学习,并且 SimplE 的复杂度随

u013250861的博客 958

在 SAP HANA 与 HANA Cloud 中,用 SQL DDL 创建数据库视图:从设计时工件到运行时对象的全链路实践

本文介绍了在SAP HANA中通过HDI容器使用DDL定义视图的方法。主要内容包括:1)采用.hdbview设计时工件存储视图定义,构建时自动转换为运行时视图,实现版本控制和权限隔离;2)开发前需准备HDI容器、MTA项目及配置.hdiconfig文件;3)详细说明.hdbview语法结构,重点讲解WITH READ ONLY和WITH STRUCTURED PRIVILEGE CHECK的使用场景;4)提供了从创建文件到构建验证的完整流程示例;5)强调跨容器访问时需通过.hdbgrants为#OO用户授予

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 273

vite源码阅读1:index.cjs

【代码】vite源码阅读1:index.cjs。

个人博客 566

置顶必读(2) | 《YOLOv11实战:从入门到深度优化》目录导航篇(持续更新中)

🏆 本文收录于 《YOLOv11实战:从入门到深度优化》 专栏。 本专栏系统梳理并持续复现全网各类 YOLOv11 / YOLO系列改进方案与实战案例,目前已覆盖 分类、检测、分割、追踪、关键点、OBB 检测 等多个方向。 内容坚持 持续更新 + 深度拆解 + 工程落地导向,不仅讲“怎么改”,更讲“为什么这样改、如何真正落地到项目中”。

**My Coding Family** 11万+

Deep-Live-Cam:单张照片本地实时换脸完整教程(免费开源)

Deep-Live-Cam 是一款免费的本地实时换脸工具:一张正脸照片即可替换摄像头或视频里的人脸,不经过任何在线服务。按本文步骤操作,你可以跑通摄像头实时换脸预览,并掌握高频命令行参数。 ## 效果速览 先给结果:选一张照片、选一个摄像头,预览里的人脸就被换成源照片上的脸;同一条流水线也适用于整段视频。首次加载模型约需 10–30 秒,无独显的纯 CPU 环境在 480p–720p 下也能勉

gitblog_00328的博客 775

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Vite 6 升级指南:CJS 和 ESM 的爱恨情仇

如果说 CJS 是 JavaScript 模块化的“老干部”,那么 ESM 就是新时代的“带头大哥”。Vite 6 的升级彻底向前迈了一步,把 CJS 甩在了身后,给前端开发带来了更快的启动、更好的兼容性和更清爽的代码。今天我们就来聊聊这俩模块规范的区别,以及如何在 Vite 6 的“强制迁移令”下,优雅地抛弃 CJS,投入 ESM 的怀抱。所以,与其挣扎着想办法让 CJS 继续活下去,不如早早投靠 ESM,跟上 Vite 6 的节奏,让你的项目跑得更快更顺畅!好消息是,这些改动让前端环境更清爽、更高效。

常备不懈 1593

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

详解ESM和CJS

ESM(ECMAScript Modules,ES 模块)和 CJS(CommonJS)是 JavaScript 中两种主流的模块系统。CJS:诞生于 ES6 之前(2009 年),是 Node.js 的默认模块系统,主要为服务器端(Node.js)设计,适用于同步加载场景(因为服务器文件存储在本地,同步加载开销低)。浏览器原生不支持 CJS,需通过 Webpack 等工具转译。

ningsheng的博客 949

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

npm-esm-vs-cjs 项目教程

npm-esm-vs-cjs 项目教程 项目介绍 npm-esm-vs-cjs 是一个开源项目,旨在收集和分析公共 npm 注册表中 ESM(ECMAScript 模块)和 CJS(CommonJS)的使用情况。该项目通过爬取高影响力 npm 包的最新发布版本,分析其 package.json 文件,生成关于 ESM 和 CJS 使用情况的统计数据。 项目快速启动 克隆项目 首先,克隆项目到本地:...

gitblog_00843的博客 871

从0到发布:以specificity为例的TypeScript ESM/CJS双格式npm包完整指南

这是一份面向初学者的实战教程。我们以开源项目 **specificity** —— 一个用于计算 CSS 选择器特异性(权重)的 JavaScript 模块 —— 为例,手把手带你搭建、测试并发布一个同时支持 ESM 与 CommonJS 双格式的 TypeScript npm 包,覆盖从工程配置到 npm publish 的全流程。 ## 为什么 npm 包要做 ESM / CJS 双格式?

gitblog_00013的博客 347

npm-esm-vs-cjs 使用指南

npm-esm-vs-cjs 使用指南 本指南将带你深入了解 npm-esm-vs-cjs 这一开源项目,它分析并记录了公共 npm 仓库中 ESM(ECMAScript 模块)与 CJS(CommonJS)模块的使用比例。这个项目对于关注 Node.js 生态系统从 CJS 向 ESM 转型的开发者尤其有用。 1. 项目目录结构及介绍 项目遵循简洁明了的组织结构,以下是一些关键目录和文件的说明:...

gitblog_00075的博客 455

Midway validation-* 包构建产物测试实战:从 test:dist 到捕获 ESM/CJS 互操作 Bug

本文以 Midway 开源仓库中 `openspec/changes/archive/2026-01-25-add-validation-dist-tests` 的实施方案为主线,完整还原为 `@midwayjs/validation-zod`、`@midwayjs/validation-zod4`、`@midwayjs/validation-joi`、`@midwayjs/validation-

gitblog_00468的博客 998

node-postgres 的 ESM/CJS 双模块导出兼容性测试实践:深入 pg-esm-test 内部测试包

node-postgres 采用 monorepo 架构,`pg` 主包及其周边库(`pg-pool`、`pg-cursor`、`pg-protocol`、`pg-native`、`pg-cloudflare` 等)需要同时支持 ESM(`import`)与 CommonJS(`require`)两种模块体系,而这正是 npm 生态中最容易踩坑的"双包"问题。`pg-esm-test` 就是 no

gitblog_00075的博客 898

Node.js 模块简史:cjs、打包工具和 esm

作者:@Marco Gonzalez原文:https://dev.to/marcogrcr/nodejs-a-brief-history-of-cjs-bundlers-and-esm-2nlb点击上方程序员成长指北,关注公众号 回复1,加入高级Node交流群背景Node.js 作为现代 Web 开发的核心技术之一,其模块系统经历了从 CommonJS(cjs)到 ECMAScript 模块(e...

程序员成长指北 458

NPM 包开发与优化全面指南

Hey, 我是Immerse系列文章首发于【Immerse】,更多内容请关注该网站转载说明:转载请注明原文出处及版权声明!UMD 是一种允许模块在多种环境(CommonJS、AMD、全局变量)中工作的模式。// AMD} else {// 浏览器全局变量});

Immerse的 Blog 1431

Node.js 模块系统:CJS 与 ESM 详解

Node.js模块系统差异与使用规范总结 Node.js支持CommonJS(CJS)和ESM两套模块系统,主要区别如下: CommonJS(CJS) 默认使用,文件后缀为.js或.cjs 语法:require()/module.exports 路径要求:本地文件必须带./前缀,后缀可省略 动态加载,运行时执行 ESM 需设置package.json中"type":"module"或使用.mjs后缀 语法:import/export 路径要求:必须带./前缀和完整后缀名(.js不能省略) 静态加载,支持tr

weixin_42174823的博客 274

使用 pkgroll 编译发布 tsx 项目中的 npm 包:从 tsconfig 到 dist 的完整构建指南

tsx 是一款让 Node.js 直接运行 TypeScript 文件的运行时工具,但它**并不负责**把 TypeScript 编译成可发布的 JavaScript 产物。本文以 tsx 官方文档的 Compilation 章节为主线,系统讲解如何用官方推荐的打包器 **pkgroll** 完成 npm 包的编译发布,覆盖入口声明(`exports`/`main`/`bin`)、双模块(CJS

gitblog_00191的博客 1082
上一篇: tsconfig.json的esModuleInterop使用场景是怎样的?
下一篇: 像特斯拉CEO马斯克一样,快速生成mock克隆数据
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

趁你还年轻233

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值