Node项目中 CommonJs语法 和ES6 Module的语法 ,两个不同语法的文件可以互相导入吗?-灵析社区

JayCoder

## 现象 1. 项目A:ESM 模块文件中导入 CommonJS 模块文件。运行项目没报错 > [https://stackblitz.com/edit/stackblitz-starters-> pescaa?file=p...](https://link.segmentfault.com/?enc=RHytx6FgBECDeSI%2BFFJYcg%3D%3D.FwAhcWkSYjSEHFSmmROFh0nI%2BJYMQ8XytSI%2BTBP1AFjtg5ThAADP06beugy20c8oo6YZ4cXamLvmBlfBcNaUp47h05Ak4BqFCqGvclFr3zY%3D) 2. 项目B:CommonJS 模块文件中导入 ESM 模块文件,运行项目报错 > [https://stackblitz.com/edit/stackblitz-starters-> hujdvx?file=p...](https://link.segmentfault.com/?enc=l6kDrWL9PrrmkGHxb2u30A%3D%3D.ENTBu%2F1WIHZEwPVoi6QcculOTJW2NtB1VIHpmUKk%2B14krlDFuNfbc9NNU%2Fx4%2Fd3mQahHSfm0ytV339MsXZkuFm62zm3Zh5%2FIoBsLjrFDIS0%3D) * * * ## 关于 在 [https://nodejs.org/api/packages.html](https://link.segmentfault.com/?enc=7f%2FmvoF1zwRfL6LbpU2j%2Bg%3D%3D.OW%2FWtT78QiuUJC4R7vLgarYtF9jXCBAMQCiZ4Cug%2F0y9aCuzujHUMQxAtl3IggOn) 中有这样一段内容: ![image.png](https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250105/a6312514ee41c86bdc99e09ae0bfce95.png) 如果以模块的形式导入会使用模块自己的 package.json. 如果以路径的形式化导入会使用被导入文件就近的 package.json. 我的这个理解对不对? * * * ## 问题 我一时也不知道该怎么表述这个问题了。大概就是 ESM 和 CommonJS 互相导入的问题吧。 1. 项目是 ESM,那么项目的某些文件中能不能用 CommonJS、然后在 ESM 中导入 CommonJS?或者项目是 CommonJS,项目的某些文件是 ESM,CommonJS 中能不能导入 ESM? 2. import 本地项目的某一个文件,为什么会使用导入文件附近的 package.json?被导入文件附近的 pacakge.josn 有什么影响? ![image.png](https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250105/511a518c45b9ea4f9806e37295904ef9.png) 3. 如果是导入模块,是不是一般模块的 package.json 中都会指明使用 CommonJS 语法会导入哪个文件、使用 ESM 语法会导入哪个文件? =============================================== ## 对于以上的问题 [@然后去远足](/u/rhqyz) 已经给出了准确的回答。 ### 补充两个问题 另外就是 在 [https://nodejs.org/api/packages.html](https://link.segmentfault.com/?enc=SlQbPIzEMDeq79xIBp3nRw%3D%3D.xV9FLgoehlZwMen8DBRqF%2F5NY2y%2Fkqj4WCY67LILHv3K5lea5sN1T%2FcQhUWbKIPs) 的开头部分 ES 模块和CommonJS模块的对比中提到了, ES可以 loader commonjs, commonjs不能loader es ![image.png](https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250105/7524305cc1ea9c82730fb64c6ad8f2a7.png) ![image.png](https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250105/865ddf70521b382ac46a67d0eb7967ab.png) 补充问题: #### 1.至于为什么 commonjs 不能loader es,我不确定,chatgpt的回复 ![image.png](https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250105/3402e899c992fa04248fe44ea8d30387.png) [@然后去远足](/u/rhqyz) 求大佬再帮忙解释一下。 #### 2.让chatgpt给个示例, 他给出的示例中 提到的输出顺序 也搞不懂为什么 顺序不确定。 ![image.png](https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250105/2874f8d826039055752c889af4d44072.png) ![image.png](https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250105/42482817ff364339e8f9c7eeb07200a2.png) 按照我的理解: commonjs的require是同步的,es的import也是同步的。 所以main.js 中 require('./commonjsModule.js'); commonjsModule.js中 require('./es6Module.mjs'); 所以 es6Module.mjs 不是应该先被加载并执行内部的代码吗?

阅读量:444

点赞量:18

问AI
A1: 可以混用,但最好不要这么做。 ESM 里引入 CommonJS 的话就正常 "import" 就好了,没什么特殊的。 CommonJS 里引入 ESM 稍微有点儿特殊,需要用 "dynamic import" 而不是 "require()": - let bModule = require('./pathA/pathB/b.js'); - console.log('bModule', bModule); + import('./pathA/pathB/b.js').then((bModule) => { + console.log('bModule', bModule); + }); *** A2: ".mjs"、".cjs" 文件分别以何种方式加载这没什么争议,有问题的是 ".js" 这种文件。 因为模块加载器需要提前知道一个 ".js" 到底是 CommonJS 还是 ESM 的、好来决定用哪种方式去加载,但显然通过文件名本身是没办法知道的,所以变成了通过 package.json 来区分。优先会找你导入的那个模块同级目录下的 package.json、如果没有那就向上一级目录找、还没有就再向上 …… 直到项目根目录为止,此时也就是跟你项目本身的设置保持一致了。 *** A3: 如果是只支持一种模块方案的,那就在 "package.json" 里配置 "type" 这个字段来标明。不标明默认就是 CommonJS,毕竟要跟以前的 Node 项目兼容 —— 老项目肯定都是只支持 CommonJS 的。 如果两种都支持,Node v14 之后 "package.json" 有了 "exports" 这个新的配置,你可以通知配置 CommonJS 和 ESM 两种模块的指向。新一点的库一般都是这种方式了,你会发现它的项目结构里同时有 "es" 和 "lib" 两个子目录,其实就分别代表 ESM 和 CommonJS,然后 "exports" 里会分别指向这两个目录。 当然了,开发的时候都是按一种方式去开发,最后通过 Webpack、Rollup 之类的构建工具转译成两种模块方案;而不是写两遍代码。