Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CommonJs, AMD/RequireJs,CMD/seajs, UMD, webpack #32

Open
Seasons123 opened this issue Jun 21, 2017 · 4 comments
Open

CommonJs, AMD/RequireJs,CMD/seajs, UMD, webpack #32

Seasons123 opened this issue Jun 21, 2017 · 4 comments

Comments

@Seasons123
Copy link
Owner

Seasons123 commented Jun 21, 2017

JavaSript模块化

在了解AMD,CMD规范前,还是需要先来简单地了解下什么是模块化,模块化开发?
模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题进行系统性的
分解以之处理。模块化是一种处理复杂系统分解为代码结构更合理,可维护性更高的可管理的模块的方
式。可以想象一个巨大的系统代码,被整合优化分割成逻辑性很强的模块时,对于软件是一种何等意义的
存在。对于软件行业来说:解耦软件系统的复杂性,使得不管多么大的系统,也可以将管理,开发,维护
变得“有理可循”。
还有一些对于模块化一些专业的定义为:模块化是软件系统的属性,这个系统被分解为一组高内聚,低
耦合的模块。那么在理想状态下我们只需要完成自己部分的核心业务逻辑代码,其他方面的依赖可以通过
直接加载被人已经写好模块进行使用即可。
首先,既然是模块化设计,那么作为一个模块化系统所必须的能力:

1. 定义封装的模块。
2. 定义新模块对其他模块的依赖。
3. 可对其他模块的引入支持。

好了,思想有了,那么总要有点什么来建立一个模块化的规范制度吧,不然各式各样的模块加载方式只
会将局搅得更为混乱。那么在JavaScript中出现了一些非传统模块开发方式的规范 CommonJS的模块规
范,AMD(Asynchronous Module Definition),CMD(Common Module Definition)等。
http://blog.chinaunix.net/uid-26672038-id-4112229.html

@Seasons123 Seasons123 changed the title mst-CMD,AMD,UMD,commonjs,requirejs,seajs mst-关于模块化:CMD,AMD,UMD,commonjs,requirejs,seajs Jun 22, 2017
@Seasons123 Seasons123 changed the title mst-关于模块化:CMD,AMD,UMD,commonjs,requirejs,seajs mst-关于模块化:CMD,AMD,UMD,commonjs,requirejs,seajs,webpack Jun 22, 2017
@Seasons123
Copy link
Owner Author

Seasons123 commented Jun 22, 2017

commonjs

commonjs起初是服务端模块的规范,nodejs就是采用这个规范。CommonJs原来是叫ServerJs,从名字可以看出是专攻服务端的,为了统一前后端而改名CommonJs。它的规范是一个单独的文件就是一个模块。加载模块使用require方法,该方法读取文件并执行,最后导出一个exports对象。commonjs是同步加载模块,加载完成后执行操作。服务端require一个模块,直接就从硬盘或者内存中读取了,消耗的时间可以忽略,就没有必要采用异步方式的来加载。但是如果我们考虑到浏览器端的话,就肯定知道,同步加载,阻塞页面的渲染,造成页面白屏,或者卡死等现象,对于用户体验肯定是不友好的。另外,资源的加载方式与服务端完全不同,在浏览器端,需要从服务端来下载这个文件,然后运行里面的代码才能得到API,需要花费一个http请求,也就是说,require后面的一行代码,需要资源请求完成才能执行。由于浏览器端是以插入<script>标签的形式来加载资源的(ajax方式不行,有跨域问题),没办法让代码同步执行,所以像commonjs那样的写法会直接报错。所以就有了AMD,CMD.

AMD

即Asynchronous Module Definition的缩写,字面意思”异步模块定义”,就是一种规范。依赖前置(依赖在使用之前都必须提前加载)。requirejs可以简单理解为AMD规范的一种实现。下面介绍。
AMD写模块的api如下:
define(id,dependencies,factory);
(1)id
string类型,一般表示模块名称,或者说标识,是一个可选参数。如果该参数不存在的话。如果没有提供
该参数,模块的名字应该默认为模块加载器请求的指定脚本的名字。如果提供了该参数,模块名必是“顶级”的和绝对的(不允许相对名字)。
模块名的格式

模块名用唯一标识定义,它们同样在依赖数组中使用。AMD的模块命名规范是Commonjs模块命名规范的
超集。
模块名是由一个或多个单词以正斜杠为分隔符拼接成的字符串
单词须为驼峰形式,或者”.”,”..”
模块名不允许使用文件扩展名的形式,如”.js”
模块名可以为”相对的”或者”顶级的”。如果首字符为”.”或者”..”则为”相对的”模块名
顶级的模块名从根命名空间的概念模块解析
相对的模块名从”require”书写和调用的模块解析

(2) dependencies
数组类型。是定义中模块所依赖模块的一个数组。依赖模块必须根据模块的工厂方法优先级执行,并且执
行的结果应该按照数组中的位置顺序以参数的形式传入(定义中模块的)工厂方法中。依赖的模块名如果是
相对的,应该解析为相对定义中的模块。相对名解析为相对于模块的名字,并非相对于寻找该模块的名字
和路径。该参数也是可选参数,如果没有这个参数,它默认为[“require”, “exports”, “module”]。然而,如
果工厂方法的形参个数小于3,加载器会选择以函数指定的参数个数调用工厂方法
(3)factory
值的类型多选。是模块初始化要执行的函数或者对象。如果是函数的话,它应该只被执行一次。如果是对
象,此对象应该为模块的输出值。如果工厂方法返回一个值(对象,函数,或任意强制类型转换为true的
值),应该被设置为模块的输出值。以上引用https://github.com/amdjs/amdjs-api/wiki/AMD-
(%E4%B8%AD%E6%96%87%E7%89%88),原文链接markdown语法限制会跳错,没办法了,只能换成短连
接了。

UMD

即Universal Module Definition,应该算是AMD和commonjs的一个糅合。
其原理:先判断是否支持nodejs的模块(exports)是否存在,如果存在就是用nodejs模块模式,然后再判断
是否支持AMD(define是否存在),如果存在就使用AMD方式加载模块.

CMD

CMD 即Common Module Definition通用模块定义,CMD规范是国内发展出来的,就像AMD有个
requireJS,CMD有个浏览器的实现SeaJS(作者是国内大牛淘宝前端布道者玉伯),SeaJS要解决的问题和
requireJS一样,只不过在模块定义方式和
模块加载(可以说运行、解析)时机上有所不同

语法:Sea.js 推崇一个模块一个文件,遵循统一的写法
define:define(id?, deps?, factory)

因为CMD推崇:一个文件一个模块,所以经常就用文件名作为模块id
CMD推崇依赖就近,所以一般不在define的参数中写依赖,在factory中写
factory有三个参数:function(require, exports, module)

require是 factory 函数的第一个参数
require(id) 是一个方法,接受 模块标识 作为唯一参数,用来获取其他模块提供的接口
exports 是一个对象,用来向外提供模块接口
module 是一个对象,上面存储了与当前模块相关联的一些属性和方法

demo

// 定义模块  myModule.js
define(function(require, exports, module) {
  var $ = require('jquery.js')
  $('div').addClass('active');
});

// 加载模块
seajs.use(['myModule.js'], function(my){

});

AMD,CMD 区别 🥇

关于这两个的区别网上可以搜出一堆文章,简单总结一下
最明显的区别就是在模块定义时对依赖的处理不同

AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块
CMD推崇就近依赖,只有在用到某个模块的时候再去require

这种区别各有优劣,只是语法上的差距,而且requireJS和SeaJS都支持对方的写法

AMD和CMD最大的区别是对依赖模块的执行时机处理不同,注意不是加载的时机或者方式不同
很多人说requireJS是异步加载模块,SeaJS是同步加载模块,这么理解实际上是不准确的,其实加载模
块都是异步的,只不过AMD依赖前置,js可以方便知道依赖模块是谁,立即加载,而CMD就近依赖,需要
使用把模块变为字符串解析一遍才知道依赖了哪些模块
,这也是很多人诟病CMD的一点,牺牲性能来带
来开发的便利性,实际上解析模块用的时间短到可以忽略。
为什么我们说两个的区别是依赖模块执行时机不同,为什么很多人认为ADM是异步的,CMD是同步的
(除了名字的原因。。。)
同样都是异步加载模块
(1)AMD在加载模块完成后就会执行该模块,所有模块都加载执行完后会进入
require的回调函数,执行主逻辑,这样的效果就是依赖模块的执行顺序和书写顺序不一定一致,看网络速
度,哪个先下载下来,哪个先执行,但是主逻辑一定在所有依赖加载完成后才执行。
(2)CMD加载完某个依赖模块后并不执行,只是下载而已,在所有依赖模块加载完成后进入主逻辑,遇
到require语句的时候才执行对应的模块,这样模块的执行顺序和书写顺序是完全一致的。
这也是很多人说AMD用户体验好,因为没有延迟,依赖模块提前执行了,CMD性能好,因为只有用户需
要的时候才执行的原因。http://www.cnblogs.com/dolphinX/p/4381855.html

requirejs seajs

这两个分别是ADM,CMD的实现方案,肯定有异同。
(requirejs的应用示例:静态文件服务器devServer.js)。
相同之处:
两者都是模块加载器,倡导js模块化开发的理念。
不同之处:
(1)定位有差异。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载
器。Sea.js 则专注于 Web 浏览器端,同时通过 Node 扩展的方式可以很方便跑在 Node 环境中。
(2)遵循的规范不同。RequireJS 遵循 AMD(异步模块定义)规范,Sea.js 遵循 CMD (通用模块定义)规
范。规范的不同,导致了两者 API 不同。Sea.js 更贴近 CommonJS Modules/1.1 和 Node Modules 规范。
(3)推广理念有差异。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采
纳。Sea.js 不强推,采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。
(4)对开发调试的支持有差异。Sea.js 非常关注代码的开发调试,有 nocache、debug 等用于调试的插件。
RequireJS 无这方面的明显支持。
(5)插件机制不同。RequireJS 采取的是在源码中预留接口的形式,插件类型比较单一。Sea.js 采取的是通
用事件机制,插件类型更丰富。
引用seajs/seajs#277

什么是Webpack?

事实上它是一个打包工具,而不是像RequireJS或SeaJS这样的模块加载器,通过使用Webpack,能够像
Node.js一样处理依赖关系,然后解析出模块之间的依赖,将代码打包。(如该项目中使用的模块化和打
包工具webpack的配置文件webpack.config.js)。
webpak不仅支持打包,而且支持AMD 和 CommonJS 方式来做模块化开发,所以打算尝试一下webpack
来实现模块化。

@Seasons123
Copy link
Owner Author

扩展阅读:

AMD规范文档 https://github.com/amdjs/amdjs-api/wiki/AMD
amdjs 的 require 接口文档 https://github.com/amdjs/amdjs-api/wiki/require
amdjs 的接口文档 https://github.com/amdjs/amdjs-api/wiki
RequireJS官网接口文档 http://www.requirejs.org/docs/api.html

模块系统 seajs/seajs#240
前端模块化开发的价值 seajs/seajs#547
前端模块化开发那点历史 seajs/seajs#588
CMD 模块定义规范 seajs/seajs#242
SeaJS API快速参考 seajs/seajs#266
从 CommonJS 到 Sea.js seajs/seajs#269

RequireJS和AMD规范 http://javascript.ruanyifeng.com/tool/requirejs.html
CommonJS规范 http://javascript.ruanyifeng.com/nodejs/commonjs.html
Javascript模块化编程 http://www.ruanyifeng.com/blog/2012/10/javascript_module.html
Javascript模块化编程 http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html

知乎 AMD 和 CMD 的区别有哪些? http://www.zhihu.com/question/20351507

JavaScript模块化开发 - CommonJS规范 http://www.feeldesignstudio.com/2013/09/javascript-module-pattern-commonjs
JavaScript模块化开发 - AMD规范 http://www.feeldesignstudio.com/2013/09/javascript-module-pattern-amd

模块化设计 http://baike.baidu.com/view/189730.htm
模块化 http://baike.baidu.com/view/182267.htm

@Seasons123
Copy link
Owner Author

阮老师的相关文集:
Javascript模块化编程(一):模块的写法
http://www.ruanyifeng.com/blog/2012/10/javascript_module.html

Javascript模块化编程(二):AMD规范
http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html

Javascript模块化编程(三):require.js的用法
http://www.ruanyifeng.com/blog/2012/11/require_js.html

@Seasons123
Copy link
Owner Author

Seasons123 commented Jun 22, 2017

关于各个模块规范的老底吕师兄写过一篇也很好:
👍 💯 js模块化历程http://www.cnblogs.com/lvdabao/p/js-modules-develop.html 🥇

@Seasons123 Seasons123 changed the title mst-关于模块化:CMD,AMD,UMD,commonjs,requirejs,seajs,webpack mst-关于模块化:Commonjs, AMD, UMD, CMD, Requirejs, seajs, webpack Jun 22, 2017
@Seasons123 Seasons123 changed the title mst-关于模块化:Commonjs, AMD, UMD, CMD, Requirejs, seajs, webpack Commonjs, AMD, UMD, CMD, Requirejs, seajs, webpack Jun 22, 2017
@Seasons123 Seasons123 changed the title Commonjs, AMD, UMD, CMD, Requirejs, seajs, webpack mst-关于模块化:CommonJs, AMD/RequireJs,CMD/seajs, UMD, webpack Jun 22, 2017
@Seasons123 Seasons123 changed the title mst-关于模块化:CommonJs, AMD/RequireJs,CMD/seajs, UMD, webpack CommonJs, AMD/RequireJs,CMD/seajs, UMD, webpack Jun 22, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant