cjs、esm、umd模块有何不同
cjs (commonjs)
commonjs 是 Node 中的模块规范,通过 require 及 exports 进行导入导出 (进一步延伸的话,module.exports 属于 commonjs2)
同时,webpack 也对 cjs 模块和 esm 模块都得以解析,因此 cjs 模块可以运行在 node 环境及 webpack 环境下的,但不能在浏览器中直接使用。但如果你写前端项目在 webpack 中,也可以理解为它在浏览器和 Node 都支持。
比如,著名的全球下载量前十 10 的模块 ms 只支持 commonjs,但并不影响它在前端项目中使用(通过 webpack),但是你想通过 cdn 的方式直接在浏览器中引入,估计就会出问题了
// sum.js
exports.sum = (x, y) => x + y;
// index.js
const { sum } = require("./sum.js");
由于 cjs 为动态加载,可直接 require 一个变量
require(`./${a}`);
esm (es module)
esm 是 tc39 对于 ESMAScript 的模块话规范,正因是语言层规范,因此在 Node 及 浏览器中均会支持
。
它使用 import/export(export default) 进行模块导入导出.
// sum.js
export const sum = (x, y) => x + y;
// index.js
import { sum } from "./sum";
esm 为静态导入,正因如此,可在编译期进行 Tree Shaking
,减少 js 体积。
如果需要动态导入,tc39 为动态加载模块定义了 API: import(module) 。可将以下代码粘贴到控制台执行
const ms = await import("https://cdn.skypack.dev/ms@latest");
ms.default(1000);
esm 是未来的趋势,目前一些 CDN 厂商,前端构建工具均致力于 cjs 模块向 esm 的转化,比如 skypack、 snowpack、vite
等。
目前,在浏览器与 node.js 中均原生支持 esm。
两者不同点在于:
cjs 模块输出的是一个值的拷贝,esm 输出的是值的引用
cjs 模块是运行时加载,esm 是编译时加载
对于 cjs 模块来说,一旦值被导出,它不会在模块外部发生变化,但如果是可变类型的值(对象、数组),其内部的属性或元素是可以被修改的。esm 模块中导出了一个变量,其他模块引入这个模块后得到的是一个绑定到该变量的引用。如果在导入模块的过程中,该变量的值发生了改变,那么其他模块中的引用也会随之改变。注意模块的独立性,例如在模块内部修改了变量的值,也不会影响到导出的值(假如再a.js中导出变量n,函数fn改变了n的值,后面b.js引用a.js,并调用fn。此时在b.js中n是不会有变化的)。
amd (Asynchronous Module Definition)
AMD是一种JavaScript模块化的概念和规范。它提出了一种异步加载和定义模块的方式,旨在解决前端开发中模块依赖管理和加载顺序的问题。
AMD的核心观念:
异步加载:AMD鼓励使用异步方式加载模块。在传统的同步加载方式中,所有脚本文件都需要先加载完毕,才能执行后续的代码逻辑。而使用异步加载可以在不阻塞页面加载的情况下,按需加载模块,提高应用的性能和用户体验。
模块定义:AMD规范中,模块的定义通过
define
函数来实现。define
函数接受三个参数:模块名称、依赖数组和工厂函数。模块名称是一个可选参数,可以用于在其他地方引用该模块。依赖数组包含了当前模块所依赖的其他模块。工厂函数则用于定义模块的具体功能,并返回一个模块实例。依赖管理:AMD规范明确了模块之间的依赖关系,并通过依赖数组来声明这些依赖关系。在加载模块时,AMD加载器(如Require.js)会自动解析模块的依赖关系,并按照正确的顺序进行加载和执行。
模块加载:AMD提供了
require
函数用于加载和使用模块。require
函数接受两个参数:依赖数组和回调函数。在所有依赖模块都加载完成后,AMD加载器会调用回调函数并将模块实例传递给该回调函数,供开发者使用。
<!DOCTYPE html>
<html>
<head>
<title>require.js</title>
<style>
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script>
<script>
// Configure RequireJS
require.config({
baseUrl: 'js', // Set the base URL for module loading
paths: {
// Define module paths
'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min',
'lodash': 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min'
}
});
// Define and use modules
define('totalModule', ['jquery', 'lodash'], function ($, _) {
var moduleA = {
$,
_
};
return moduleA;
});
// Load and use modules
require(['totalModule'], function (m) {
m.$('#app').html('11');
});
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
umd
一种兼容 cjs 与 amd 的模块,既可以在 node/webpack 环境中被 require 引用,也可以在浏览器中直接用 CDN 被 script.src 引入。
(function (root, factory) {
if (typeof define === "function" && define.amd) {
// AMD
define(["jquery"], factory);
} else if (typeof exports === "object") {
// CommonJS
module.exports = factory(require("jquery"));
} else {
// 全局变量
root.returnExports = factory(root.jQuery);
}
})(this, function ($) {
// ...
});
这三种模块方案大致如此,部分 npm package 也会同时打包出 commonjs/esm/umd
三种模块化格式,供不同需求的业务使用,比如 antd。
- 感谢你赐予我前进的力量
本网站的原创文章部分资源内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系博主邮箱:zzyo.yj@outlook.com 进行删除处理
本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向博主举报
声明:版权所有,违者必究 | 如未注明,均为原创 | 本网站采用CC BY-NC-SA 4.0 协议进行授权
转载:转载请注明原文链接 - Lycoris