• AMD
  • CMD
  • ES6模块化
  • 各个模块化规范对比理解

一、AMD

在上一篇js模块化入门与commonjs解析与应用中详细的解析了关于commonjs模块化规范,commonjs采用的用同步加载方式,这导致它并不是浏览器理想的模块化规范。因为浏览器需要到服务器加载文件,请求事件远远大于本机读取的时间,如果文件较多,网络迟缓就会导致页面瘫痪,所以浏览器更希望能够实现异步加载的方式。

AMD规范则是异步加载模块,用于指定回调函数。等模块加载完成以后即可调用回调函数。AMD规范得意的产出就是require.js。

https://requirejs.org/

先通过示例来感受以下AMD规范实现的requirejs的应用:

1.1定义工作区间文件结构

 cmd//工作区间
modules-->依赖模块
m1.js-->模块1
m2.js-->模块2
demo.html-->结构文本
demo.js-->js主入口文件
require.js-->CMD模块化工具

1.2.1依赖模块代码(m1):

 define(function (){
var name = 'm1-amd';
function getName(){
return name;
}
return {getName};//{getName}同等与{getName:getName}
})

1.2.2依赖模块代码(m2):

 define(['m1'],function(m1){
var msg = 'm2-amd';
function show(){
console.log(msg,m1.getName());
}
return {show};
})

1.3JS主入口文件:

 (function (){
require.config({
paths:{
m2:'./modules/m2',
m1:'./modules/m1'
}
});
require(['m2','jquery'],function(m2,$){
m2.show();
});
})();

1.4在结构文本中引入AMD规范模块化处理工具require.js,并将主入口文件通过自定义属性data-main='主入口文件路径'的方式引入工具中进行处理:

<script src="./require.js" data-main="./demo.js"></script>

AMD的基本规范的全称“Asynchronous Module Definition”的缩写,意思是“异步加载模块”。它采用异步方式加载模块,模块的加载不影响后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成后,这个回调函数才会运行。

AMD规范实际上是requirejs项目在推广过程中形成的一个产物,先来看看requirejs的基本使用:

  requirejs模块定义:define(id?,dependencies?,factory);==>id:可选参数,用来定义模块的标识,如果没有提供该参数,模块标识就取脚本文件名(去掉扩展名)。==>dependencies:用来传入当前模块依赖的模块名称数组。==>factory:工厂方法,模块初始化要执行的函数或对象,如果是函数,它只被执行一次。如果是对象,此对象应该为模块的输出值。

  requirejs模块主入口(模块加载):require.config({paths:{foo:'路径'}});==>faths:配置所有依赖模块的路径。在路径配置代码的下方,再通过require(dependencies?,factory)定义主入口文件的依赖关系和回调函数。

在requirejs中还可以实现依赖其他库和插件,有些插件和库定义了requirejs的标准接口,比如jQuery,但是有些没有标准接口,requirejs官方都给出解决方案,可以参考这篇博客:https://www.cnblogs.com/goloving/p/7711104.html。例如我在示例中也测试了jQuery的使用:

 (function (){
require.config({
paths:{
m2:'./modules/m2',
m1:'./modules/m1',
jquery:'./jquery-2.0.3'
}
});
require(['m2','jquery'],function(m2,$){
m2.show();
$('body').css('backgroundColor','#000');
});
})();

关于requirejs更多API可以查看官网的API示例:https://requirejs.org/docs/api.html

二、CMD

在上面一节介绍了AMD规范以及规范实现的requirejs的基本使用,其中提到了AMD相对于Commonjs的优势在于异步加载模块,但是我没由说明这个异步加载在什么时候触发,到了CMD这里有必要提一下了,AMD规范很重要的一个思想就是依赖前置,意思就是在模块执行前将所有依赖的模块先全部加载到本地。而CMD的加载方式也是异步加载,但是触发加载的时间是在需要某个依赖模块时再去加载,也有人将CMD说成是同步的,这种同步并不是表现在资源加载上,而是触发加载的指令与代码执行是同步的,资源加载还是异步加载模式。

关于Commonjs、AMD、CMD、ES6模块化的异同在最后会由详细的对比分析。

2.1.先来看CMD的基本应用:https://www.zhangxinxu.com/sp/seajs/

2.1.1.定义工作区间文件结构

CMD//工作区间
-->modules//依赖模块
-->m1.js
-->m2.js
-->m3.js
-->m4.js
dome.html//结构文本
demo.js//JS主入入口文件
sea.js//模块化工具

2.1.2.m1模块代码

 define(function(require,exports,module){
var msg = 'm1';
function foo(){
console.log(msg);
}
module.exports = {
foo:foo
}
})

2.1.3.m2模块代码

 define(function(require,exports,module){
var msg = 'm2';
function bar(){
console.log(msg);
}
module.exports = bar;
})

2.1.4.m3模块代码

 define(function(require,exports,module){
var msg = 'm3';
function foo(){
console.log(msg);
}
exports.foo = foo;
})

2.1.5.m4模块代码

 define(function(require,exports,module){
var msg = 'm4';
// 同步加载
var m2 = require('./m2');
m2();
// 异步加载
require.async('./m3',function(m3){
m3.foo();
});
function fun(){
console.log(msg);
}
exports.fun = fun;
})

2.1.6.JS主入口文件demo代码

 define(function(require,exports,module){
var m1 = require('./modules/m1');
m1.foo();
var m4 = require('./modules/m4');
m4.fun();
})

2.1.7.结构文本demo.html引入模块化处理工具sea.js,使用seajs工具对象方法user找到主入口文件并解析执行==>seajs.use('主入口文件路径'):

 <script src="./sea.js"></script>
<script>
seajs.use('./demo.js');
</script>

最后代码打印结果:

这里值得我们关注的是m4打印在m3的前面,这就是CMD依赖就近原则产生的,在执行队列中异步请求需要等主线程执行完成以后才会调用执行,所以m3作为异步加载模块,在这个代码结构中要最后执行。

值得我们注意的seajs也有同步加载模式直接使用require('模块路径')获取模块,异步模块加载方式需要使用require.async('模块路径',function(模块名称){回调执行内容})。

三、ES6模块化

ES6自带模块化,可以使用import关键字引入模块,通过export关键字到处模块,功能较之前几个方案更为强大,但是由于ES6目前无法在浏览器中执行,所以,需要通过babel将不支持的import编译为当前收到广泛支持的require。

 //  引入默认变量及方法和模块导入的m1 m2变量或方法
import theDefault,{m1,m2} from 'lib';
// 引入默认变量及方法
import theDefault from 'lib';
// 引入模块导出的m1 m2变量或方法
import {m1,m2} from 'lib';
// 引入模块导出的m1并且将m1重命名myName m2变量或者方法
import * as myLib from 'lib';
// 只将lib加载进来 没有用来lib中暴露的接口
import 'lib'; // 暴露变量
export var a = '123';
// 暴露函数
export function myFun(){ }
// 默认暴露变量函数等
export default a = '123';
export function myFun(){}

关于ES6的模块化会在ES6的相关博客中来详细解析,这里只做一些基本介绍。

四、各个模块化规范对比理解

1.什么是模块化?

答:模块化是指将一个复杂的系统分解为多个模块,方便编码。

2.为什么要用模块化?

答:降低复杂性,降低代码耦合度,部署方便,提高效率。

3.模块化的好处?

答:3.1.避免命名冲突,减少变量空间污染;

  3.2.更好的分离代码,按序加载;

  3.3.更高复用性;

  3.4.更高可维护性;

4.Webpack支持性:

AMD、ES Modules(推荐使用)、CommonJS因为webpack是基于nodeJS的,所以有必要了解学习。

5.AMD、CMD、CommonJS模块规范的对比分析:

  AMD、CMD可以使用插件引入的方式实现JS代码模块化管理,CommonJS不兼容浏览器需要Browserify工具在nodejs环境下转换成浏览器可执行的JS文件。

  Commonjs采用同步加载,会在一定程度上增加页面载入时间,如果在这个过程中出现某个模块错误,会导致页面加载失败。

  AMD、CMD采用异步加载,两者的区别就是AMD采用前置预加载模式,CMD采用就近原则加载模式。AMD的体验更好,CMD的性能更优,但是CMD需要考虑异步队列的执行顺序问题,所以这里的更好和更优要相对而言。

  (后续深入研究后再来补充)

js模块化AMD、CMD、ES6的更多相关文章

  1. js模块化AMD/CMD

    JavaSript模块化 在了解AMD,CMD规范前,还是需要先来简单地了解下什么是模块化,模块化开发?     模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题进行系统 ...

  2. 前端模块化方案全解(CommonJS/AMD/CMD/ES6)

    模块化的开发方式可以提高代码复用率,方便进行代码的管理.通常一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数.目前流行的js模块化规范有CommonJS.AMD.CMD以及ES6的模块 ...

  3. 前端模块化小总结—commonJs,AMD,CMD, ES6 的Module

    随着前端快速发展,需要使用javascript处理越来越多的事情,不在局限页面的交互,项目的需求越来越多,更多的逻辑需要在前端完成,这时需要一种新的模式 --模块化编程 模块化的理解:模块化是一种处理 ...

  4. (转) 前端模块化:CommonJS,AMD,CMD,ES6

    模块化的开发方式可以提高代码复用率,方便进行代码的管理.通常一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数.目前流行的js模块化规范有CommonJS.AMD.CMD以及ES6的模块 ...

  5. es6的模块化--AMD/CMD/commonJS/ES6

    , ); ); }) , )); }); , )); ; export { firstName, lastName, year }; // es6引用 import { firstName, last ...

  6. JavaSript模块化 && AMD CMD 详解.....

    模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题进行系统性的分解以之处理.模块化是一种处理复杂系统分解为代码结构更合理,可维护性更高的可管理的模块的方式.可以想象一个巨大 ...

  7. JS模块化规范CMD之SeaJS

    1. 在接触规范之前,我们用模块化来封装代码大多为如下: ;(function (形参模块名, 依赖项, 依赖项) { // 通过 形参模块名 修改模块 window.模块名 = 形参模块名 })(w ...

  8. JS 模块化- 04 CMD 规范与 Sea JS

    1 CMD 规范介绍 CMD: Common Module Definition, 通用模块定义.与 AMD 规范类似,也是用于浏览器端,异步加载模块,一个文件就是一个模块,当模块使用时才会加载执行. ...

  9. js模块化规范—CMD规范

    CMD规范说明 专门用于浏览器端, 模块的加载是异步的 ,模块使用时才会加载执行,github地址 CMD基本语法 定义暴露模块 //定义有依赖的模块 define(function(require, ...

随机推荐

  1. 【WIP_S9】图论算法

    创建: 2018/06/01 图的概念 有向边 有向图 无向边 无向图 点的次数: 点连接的边的数量 闭路: 起点和重点一样 连接图: 任意两点之间都可到达 无闭路有向图: 没有闭路的有向图 森林: ...

  2. POJ2752【KMP-next数组含义】

    题意: 给一个字符串,求满足既是这个字符串的前缀,又是这个字符串的后缀,从小到大输出长度 思路: 细讲next数组含义博文:点我 首先要满足前缀的呀. KMP的next数组干的是子串最长后缀. 所以从 ...

  3. UGUI技术之LayoutGroup布局实现详解

    继续学习unity4.6,unity的LayoutGroup分为三种, Horizontal Layout Group(水平布局)Vertical Layout Group(垂直布局)Grid Lay ...

  4. [Xcode 实际操作]九、实用进阶-(2)遍历设备(输出系统)上的所有字体

    目录:[Swift]Xcode实际操作 在实际工作中,经常需要调整界面元素的字体种类. 本文将演示输出系统提供的所有字体,方便检索和使用. 在项目导航区,打开视图控制器的代码文件[ViewContro ...

  5. Java 工程师面试题和笔试题整理(一)

    根据自己之前收集的还有一部分自己面试的整理出来,希望能帮到面试的兄弟(2017). 海科融通 笔试题 1.有一个字符串,如果要在其中查找一个子串,都有哪些方式,写出你认为最好的一个. 2.写出线程都有 ...

  6. queue模块

    queue队列 :使用import queue,用法与进程Queue一样 queue is especially useful in threaded programming when informa ...

  7. bzoj 1494 生成树计数

    坑了好多天的题,终于补上了 首先发现 \(i\) 这个点和 \(i-k\) 之前的点没有边,所以 \(i-k\) 之前的点肯定联通,只要处理中间 \(k\) 个点的联通状态就好了.我们用最小表示法,\ ...

  8. Influxdb 时序数据库 centos 安装

    Influxdb 环境搭建 操作系统:CentOS 7 X64 SSH工具:PuTTY 操作系统安装,请参照官网文档进行:https://www.centos.org/ 使用PuTTY 通过ssh连接 ...

  9. 牛客网Java刷题知识点之同步方法和同步代码块的区别(用synchronized关键字修饰)

    不多说,直接上干货! 扩展博客 牛客网Java刷题知识点之多线程同步的实现方法有哪些 为何要使用同步?      java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查 ...

  10. #82. 【UR #7】水题生成器

    链接:http://uoj.ac/problem/82 今天是世界水日,著名的水题资源专家蝈蝈大臣向世界宣布了他的一项新发明 —— 水题生成器. 每道题目都有一个正整数的难度值.水题生成器虽然强大但是 ...