モジュール化とは、複雑な問題や一連の混合問題を解決するときに、問題が分類思考に従って体系的に分解され、処理されることを意味します。モジュール化は、複雑なシステムを、より合理的なコード構造と高い保守性を備えた管理可能なモジュールに分解する方法です。巨大なシステム コードが統合され、最適化され、高度に論理的なモジュールに分割されることがソフトウェアにとってどれほど意味があるかは想像できるでしょう。ソフトウェア業界の場合: 分離されたソフトウェア システムの複雑さにより、システムがどれほど大きくても、管理、開発、メンテナンスが「合理的」になります。
モジュール性の専門的な定義もいくつかあります。モジュール性はソフトウェア システムの属性であり、このシステムは結合性が高く、結合性が低いモジュールのセットに分解されます。したがって、理想的な世界では、独自のコア ビジネス ロジック コードの一部を完成させるだけでよく、他の依存関係は、他の人が書いたモジュールを直接ロードすることで使用できます。
1. AMD
AMD には、define(id?,dependency?,factory);
というインターフェイスが 1 つだけあります。
モジュールを宣言するときにすべての依存関係 (dep) を指定し、次のようにそれらを仮パラメータとしてファクトリに渡す必要があります。
依存関係がない場合は、次のように単純なモジュールを定義するだけです
define(function(){ var exports = {}; exports.method = function(){...}; return exports; });
ここに、物事をまとめている定義があります。なぜ、Node 実装に定義キーワードが含まれていないのでしょうか?実際、これは単に Node による暗黙的なパッケージ化です。
RequireJS は AMD 仕様を実装します
2.CMD
Yu おじさんは、彼が提案した CMD 仕様に準拠した seajs を作成しました。これは、AMD よりもわずかに強力で、より使いやすいと感じます。
3. AMD と CMD の違い
CMD は、モジュールを定義するときに依存モジュールをすぐに作成する必要がなく、逆に、AMD では依存モジュールを作成する必要がある場合に便利です。モジュールを定義し、仮パラメータのメソッドがファクトリに導入されます
//AMD モード定義モジュール
define(['dep1','dep2'],function(dep1,dep2){ //内部只能使用制定的模块 return function(){}; });
//CMD
define(function(require,exports,module){ //此处如果需要某XX模块,可以引入 var xx=require('XX'); });
SEAJS には use 関数もあります。これには、
などのすべての依存モジュールを最初に導入する必要があります。
//SEAJS.Use方式 seajs.use(['dep1','dep2'],function(dep1,dep2){ //这里实现事务 });
四、插件支持
但全球有两种比较流行的 JavaScript 模块化体系,一个是 Node 实现的 CommonJS,另外一个是 AMD。很多类库都同时支持 AMD 和 CommonJS,但是不支持 CMD。或许国内有很多 CMD 模块,但并没有在世界上流行起来。
现在比较火的 React 及周边类库,就是直接使用 CommonJS 的模块体系,使用 npm 管理模块,使用 Browserify 打包输出模块。
不久的将来 ES6 中新的模块化标准,可能就都得遵循新的标准了,什么AMD、CMD可能到时也不会怎么用了。
但是目前来说,前端开发没有用模块化编程就真的out的了,而目前的模块化编程,本人还是建议用SEAJS,虽然很多插件需要追加或修改一小块代码才能支持。但改过一次就能反复使用,也不会影响其它标准的支持。总体还算是比较方便实用的。
单独解释AMD 与 CMD 区别到底在哪里?
看了以上 AMD,requireJS 与 CMD, seaJS的简单介绍会有点感觉模糊,总感觉较为相似。因为像 requireJS 其并不是只是纯粹的AMD固有思想,其也是有CMD规范的思想,只不过是推荐 AMD规范方式而已, seaJS也是一样。
下面是玉伯对于 AMD 与 CMD 区别的解释:
AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
类似的还有 CommonJS Modules/2.0 规范,是 BravoJS 在推广过程中对模块定义的规范化产出还有不少??
这些规范的目的都是为了 JavaScript 的模块化开发,特别是在浏览器端的。
目前这些规范的实现都能达成浏览器端模块化开发的目的。
区别:
1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible.
2. CMD 推崇依赖就近,AMD 推崇依赖前置。看代码:
// CMD
define(function(require, exports, module) { var a = require('./a') a.doSomething() // 此处略去 100 行 var b = require('./b') // 依赖可以就近书写 b.doSomething() // ... })
// AMD 默认推荐的是
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好 a.doSomething() // 此处略去 100 行 b.doSomething() // ... })
虽然 AMD 也支持 CMD 的写法,同时还支持将 require 作为依赖项传递,但 RequireJS 的作者默认是最喜欢上面的写法,也是官方文档里默认的模块定义写法。
3. AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,没有全局 require,而是根据模块系统的完备性,提供 seajs.use 来实现模块系统的加载启动。
CMD 里,每个 API 都简单纯粹。
4. 还有一些细节差异,具体看这个规范的定义就好,就不多说了。