node教程,模块文件后缀选择cjs还是mjs?模块类型对比
发布于 作者:苏南大叔 来源:程序如此灵动~nodejs
内部的两大阵营,真心的令人头晕。默认是commonjs
类型的,使用require
加载。但是可以通过.mjs
或者type:"module"
来修改解释方法为es module
,使用import
进行加载。
苏南大叔的程序如此灵动博客,记录苏南大叔和计算机代码的故事。本文描述:类库代码如何兼容两种主流模式,既可以使用import
也可以使用require
。测试环境:node@16.14.2
。
个人感觉,这个就是javascript
世界里面新的精神内耗,纯粹的内耗。
基本知识
本文是基于下面这篇文章的,可以先阅读下面这篇文章:
https://newsn.net/say/node-export-import.html
虽然默认情况下,.js
文件会被解释成commonjs
的。但是,可以通过package.json
里面的type
强制修改成为module
。那么,这些.js
文件就又会被强制解释为es module
,虽然代码没有改变,但是却各种报错了。
所以,这里苏南大叔的建议就是:不管package.json
里面的设置,commonjs
的模块,就修改成.cjs
。es module
的模块,就修改成.mjs
。如果要选择.js
后缀,就要接受package.json
中的type
的强制设定。
被引用模块
两种写法,commonjs
和es module
。
commonjs
,sunan.cjs
:
let who = "sunan大叔";
function hola() { who = "苏南大叔"; }
module.exports = { who, hola } // 通吃,可以require也可以import
es module
,sunan2.mjs
:
let who = "sunan大叔";
function hola() { who = "苏南大叔"; }
export default { who, hola } // 只能import
模块调用
上面的两种模块,其实在.cjs
或者.mjs
里面都可以调用,只不过就是写法的不同罢了。
index.cjs
const sunan = require("./sunan.cjs");
sunan.hola();
console.log(sunan.who);
// const sunan2 = require("./sunan2.mjs")
(async () => {
const sunan2_ = await import("./sunan2.mjs");
const sunan2 = sunan2_.default;
sunan2.hola();
console.log(sunan2.who);
})();
不能直接import
,但是可以动态import
。参考文章:
index.mjs
import sunan from "./sunan.cjs";
import sunan2 from "./sunan2.mjs";
sunan.hola();
console.log(sunan.who);
sunan2.hola();
console.log(sunan2.who);
题外话
关于node
(前端)模块化的概念,先后出现了requirejs
(AMD)/seajs
(CMD)/commonjs
,以及目前最流行的es module
。其中,前两者AMD
和CMD
主要用于浏览器端的js
代码模块化,目前事实上项目已死,但是,它们的思想还是一直经典流传的。如果要向它们的标准进行兼容,则代码判断标准是是否存在define
函数。而commonjs
目前还在大量使用中,但是已经出现了被es module
所取代的趋势。
下面是一段兼容的代码,但是无关本文的commonjs
或者es module
,下面的这段代码,可以理解为在浏览器端做的代码兼容。
; (function (name, definition) {
var hasDefine = typeof define === 'function';
var hasExports = typeof module !== 'undefined' && module.exports;
if (hasDefine) {
// 可能使用了 requirejs或者seajs框架的浏览器环境
// AMD环境或CMD环境,amd = requirejs, cmd = seajs,目前日落西山
define(definition);
} else if (hasExports) {
// 定义为普通Node模块,commonjs 或者 esmodule 都可以对接
module.exports = definition();
} else {
// 没有使用 requirejs或者seajs框架的浏览器环境
// 将模块的执行结果挂在window变量中,在浏览器中this指向window对象,第一个参数就是用在这里的。
this[name] = definition();
}
})('hola', function () {
let who = "sunan大叔";
function hola() { who = "苏南大叔"; }
return { who, hola }
});
这段代码中,可以看到,如果判断为node
环境的话,就使用module.exports = definition()
导出模块,也就是本文中的commonjs
的导出方式,也就是说可以使用require()
也可以使用import()
导入模块。
结束语
在这里需要特殊说明的是:对比上一篇文章中的运行结果,本文中的所有运行结果,都没有修改who
变量,输出都是原版的sunan大叔
字样。
https://newsn.net/tag/node/
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。