zoukankan      html  css  js  c++  java
  • 对CommonJS、AMD、CMD简单粗暴的理解

      对于大型Web应用或者项目,动辄上万行的代码,给开发和后期维护带来了不小的麻烦。因此,需要有一种规范化的模块管理机制,帮助开发者集中处理模块的定义与调用关系。

      在ES6正式出台前,已经有不少人致力于推出适合Web开发的模块化管理标准,CommonJS、AMD和CMD就是其中的成功代表。

      以下为我查阅资料后,对三者最直观的理解:

    CommonJS

      通常被应用于服务器,实现代表:NodeJS。NodeJS相信大家都不陌生,它的出现成功将Javascript应用到了服务器端,使得前段开发者也能较为省力得转向后端开发,而无需学习一门新语言。

      在服务器端,模块的加载和执行都在本地完成,因此,CommonJS并不要求模块加载的异步化。

    模块定义与加载

    • 对于CommonJS,模块以文件为单位存在,模块实现全部位于该文件内部
    • 在文件末尾,需要把将要导出的方法添加到module.exports对象上
    • 随后在其他文件(模块)中,可以使用require()方法加载需要的模块,该方法要求一个参数:可以是一个模块名(此时加载的是默认提供的模块),或者是一个URL。如果是URL,其可以是相对路径或绝对路径,或者是一个指定的路径(由Node自行解析并寻找)。关于文件的后缀名,默认为“.js”,因此参数中可以省略后缀名;而如果指定的模块未发现,则会继续寻找以“.json”和“.node”为后缀的文件(其中以“.node”为后缀的文件将会以编译后的二进制文件格式解析)。

    AMD

      AMD(异步模块加载)和CMD通常用于浏览器端,它们与CommonJS最明显的不同就是异步加载。AMD的实现代表是require.js,它也是require.js在推广过程中的附加产物。

    模块定义与加载

    • AMD模块不一定以文件为单位,小模块集群也是允许的;但基本上在开发过程中,还是应当以文件的形式进行管理
    • 模块的定义由define()方法确定,该方法接受两个参数:
      • 一是当前模块的依赖模块,以数组形式传递
      • 二是当前模块的实现,以回调形式传递。一中的依赖通过参数传给回调。在回调末尾,以对象的形式返回需要公开的方法组。
    • 模块的配置使用require.config()方法,它接受一个对象类型的参数,该对象需要配置一些属性:baseUrl,paths,shim等
      • baseUrl:所有模块查找的根路径;未设置时默认是使用require.js的HTML文件所在目录。或者可以使用data-main属性在加载require.js的标签中定义根路径。
      • callback:当前依赖全部加载完成后的回调函数
      • config:将Application级别的配置信息传递给模块时使用。传递时使用module.config()方法。
        requirejs.config({
        config: {
        'bar': {
        	size:'large'
        },
        'baz': {
        	color: 'blue'
                }
            }
        });
        //bar.js直接使用module模块
        define(function (require, exports, module) {
            var size = module.config().size;
        });
        //baz.js使用了一个依赖数组,并要求一个特殊的依赖“module”
        define(['module'], function(module) {
            var color = module.config().color;
        });

        当“some/newmodule”调用了“require('foo')”,它将获取到foo1.2.js文件;而当“some/oldmodule”调用“`require('foo')”时它将获取到foo1.0.js。

      • exports:模块的输出
      • init:模块的初始化工作
      • paths:模块文件的路径。当paths中以/开头、或以.js结尾、或包含协议时(如http://...),其路径不在根路径下。
      • shim:需要未用define()方法定义的模块时使用。值为一组模块对象,每个对象分别有一些属性:deps,exports,init等。值得注意的是,shim只是定义了模块的依赖关系,仍然需要通过define+require的方式调用。
        • deps:模块的依赖数组
        • exports:模块的输出
      • map:对于给定的模块前缀,使用一个不同的模块ID来加载该模块。可以使用*号作为默认配置,且该配置可以被更具体的配置覆盖。
        requirejs.config({
        	map: {
        	    'some/newmodule': {
        	        'foo': 'foo1.2'
        	    },
        	    'some/oldmodule': {
        	        'foo': 'foo1.0'
        	    }
        	}
        });	
      • 更多参数请戳 参考链接

     CMD

      CMD(通用模块加载)是sea.js在推广过程中的产出,它与AMD主要有以下几点区别(来自seajs的官方阐述):

    • 定位有差异。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。Sea.js 则专注于 Web 浏览器端,同时通过 Node 扩展的方式可以很方便跑在 Node 环境中。
    • 遵循的规范不同。RequireJS 遵循 AMD(异步模块定义)规范,Sea.js 遵循 CMD (通用模块定义)规范。规范的不同,导致了两者 API 不同。Sea.js 更贴近 CommonJS Modules/1.1 和 Node Modules 规范。
    • 推广理念有差异。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。Sea.js 不强推,采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。
    • 对开发调试的支持有差异。Sea.js 非常关注代码的开发调试,有 nocache、debug 等用于调试的插件。RequireJS 无这方面的明显支持。
    • 插件机制不同。RequireJS 采取的是在源码中预留接口的形式,插件类型比较单一。Sea.js 采取的是通用事件机制,插件类型更丰富。
    • AMD提倡依赖前置,也就是在一开始就定义加载。而CMD则推崇依赖就近,即就在使用到模块的代码前面进行依赖加载。这里就需要注意了,使用requirejs会按照模块的依赖顺序进行加载,即模块不会按照代码里的顺序进行加载,可能造成意外地结果。

      这形成了两种截然不同的加载方式:“预加载”和“懒加载”。AMD提前将所有模块的所有依赖加载完成后,才开始执行主流程;而CMD是遇到一个依赖开始加载,完成后执行当前流程,遇到下一个依赖再次去加载,然后再执行下一步。当然,同一模块的依赖之间仍然是异步加载的。

    模块定义与加载

      流程与AMD类似,不再赘述,只简单介绍seajs的API。

    • cache:查看当前模块系统中的模块信息
    • config:配置模块参数,参数列表:
      • alias:模块别名
      • base:根路径
      • paths:模块文件所在路径
      • vars:变量配置。比如需要在运行时确定模块路径的情况:
        seajs.config({
            // 变量配置
            vars: {
                'locale': 'zh-cn'
            }
        });
        define(function(require, exports, module) {
          var lang = require('./i18n/{locale}.js');
             //=> 加载的是 path/to/i18n/zh-cn.js
        });

        使用变量需要用花括号包围,如例中的{locale}。

    • data:查看 seajs 所有配置以及一些内部变量的值,可用于插件开发。当加载遇到问题时,也可用于调试。
    • resolve:利用模块系统的内部机制对传入的字符串参数进行路径解析。
    • use:加载模块。seajs.use(id/url/urlArray, callback)
  • 相关阅读:
    jQuery之$().each和$.each的区别(转)
    js获取非行间样式--有bug,忧伤
    js之数组方法
    js之检测对象类型
    for-in枚举对象属性
    jq 处理select 下拉框
    阿里大鱼短信发送服务应用实例(PHP SDK)
    php RSA 非对称加解密实例
    JS HTML table 生成 Excel文件
    php RSA 加解密实例
  • 原文地址:https://www.cnblogs.com/cjc917/p/7492569.html
Copyright © 2011-2022 走看看