ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ES6基础——前端模块化:CommonJS、AMD、CMD、ES6模块

2021-04-10 17:34:13  阅读:179  来源: 互联网

标签:ES6 CommonJS require CMD js 模块 加载


在使用JavaScript开发大型项目时,模块开发是一个必须考虑的问题,流行的js模块化规范有CommonJS、AMD、CMD和ES6模块,通常一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数。

         一、CommonJS

二、AMD、require.js

三、CMD、Sea.js

四、ES6模块

五、CommonJS与ES6模块的不同

1. CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。

2. CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

3. CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。


一、CommonJS

在前端浏览器中并不支持该规范,主要用于服务器端,Node.js是CommonJS规范的主要实践者。我们用 module.exports 定义当前模块对外输出的接口(不推荐直接用exports),用 require 加载模块。代码如下:

//定义模块 math.js
const num = 0;
function add(a, b) {
    return a + b;
}
module.exports = {
    add:add,
    num:num
}
//加载模块,参数包含路径,可省略.js
const math = require('/math');
math.add(2, 5);

//引用核心模块时,不需要带路径
const http = require('http');

CommonJS采用同步的方式加载模块,在服务器端,模块文件都存在本地磁盘,读取非常快,因此也不需要异步加载。但在浏览器端的话,则需要浏览器端发起请求到服务端,然后等待服务端返回模块才可以使用,因此应该采用异步加载。

二、AMD、require.js

AMD规范采用异步的方式加载模块,模块的加载不影响它后面语句的执行,主要用于浏览器。所有依赖这个模块的语句都定义在了回调函数中,等到加载完成后,这个回调函数才会运行。require.js实现了AMD规范,用 require.config() 指定引用路径等,用 define() 定义模块,用 require() 加载模块。

//定义 math.js模块
define(function () {
    var num = 0;
    var add = function (x, y) {
        return x + y;
    };
    return {
        add: add,
        num:num
    };
});
//网页中引入文件 require.js 和入口文件 main.js,main.js中配置require.config()
<script src="js/require.js" data-main="js/main"></script>
//入口文件main.js中指定各模块路径和引用名
require.config({
    baseUrl:"js/lib",
    paths: {
        "jquery":"jquery.min", //实际路径 js/lib/jquery.min.js
        "math":
    }
});
//执行基本操作
require(["jquery","math"], function($,_){
   //... 
});

三、CMD、Sea.js

CMD规范采用异步的方式加载模块,sea.js实现了AMD规范,CMD与AMD其实很相似,不同点在于:

  • AMD推崇依赖前置,提前执行,AMD加载完模块后就会执行该模块,所有模块加载执行完后会进入require的回调函数,执行主逻辑,这样会导致依赖模块的执行顺序和书写顺序可能不一致,但主逻辑一定是在所有依赖加载执行后才会执行。因此说AMD用户体验好。
  • CMD推崇依赖就近,延迟执行,CMD加载完某个模块后并不会立即执行,所有模块加载完后进入主逻辑,遇到require语句才执行对应模块,这样模块的执行顺序和书写顺序是一致的。因此说CMD性能好。

四、ES6模块

ES6的Module旨在成为浏览器和服务器通用的模块解决方案,它结合了CommonJS和AMD的优点,语法简洁且支持异步加载,用 export 规定模块的对外接口,用 import 用于加载引用模块。

//定义模块 math.js
const num = 0;
function add(a, b) {
    return a + b;
}
export{ num, add };
<script type="module" src="./foo.js"></script>  //等同于defer属性,渲染完再执行,按顺序加载
<script type="module" src="./foo.js" defer></script>
<script type="module" src="./foo.js" async></script>//打开async属性,下载完就执行,不能保证加载顺序
//加载引用模块
import {num, add} from './math';
function test(x) {
    x.textContent = add(99 + num);
}

//整体加载引用模块
import * as obj from './math';
function test(x) {
    x.textContent = obj.add(99 + obj.num);
}

ES6的模块不是对象,import命令会在编译时就引入模块代码,而不是在代码运行时加载,所以无法实现条件加载。

五、CommonJS与ES6模块的不同

1. CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。

CommonJS 一旦输出一个值,模块内部的变化就影响不到这个值。而对于ES6模块,JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。

2. CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。

3. CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。

 

参考资料:

1. 前端模块化:CommonJS,AMD,CMD,ES6

2.(新手总结)前端模块化,AMD,CMD 面试总结

3. Module 的语法-阮一峰

 

 

 

标签:ES6,CommonJS,require,CMD,js,模块,加载
来源: https://blog.csdn.net/huaf_liu/article/details/115560878

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有