前端模块规范AMD/UMD/CommonJs

37 篇文章 3 订阅
16 篇文章 0 订阅

.babelrc文件中的:module设置为false,为什么会要设置成false?

解释:使ES6模块语法转换到另一个模块类型(默认启用“commonjs”)。 设置为假则不变换模块。或者传入(“amd”、“umd”,“systemjs”、“commonjs”)。

什么是模块?

Javascript的组件生态在最近几年的发展很给力,我们的可选性更加广泛了。这本是一件好事,但是当多个第三方Javascript在一起混合使用的时候,我们可能会遇到一个很尴尬的问题,那就是不是所有的组件都能在一起很愉快的玩耍的。

为了解决这个问题,两种竞争关系的前端模块规范(AMD和CommonJS)问世了。他们规定开发者们采用一种约定好的模式来写代码,以避免污染整个生态系统。

AMD规范--通过define(['加载的模块依赖','',''], 加载完依赖的回调函数)

AMD规范,全称”Asynchronous Module Definition”,称为异步模块加载规范。一般应用在浏览器端。流行的浏览器端异步加载库RequireJS中文网站)实现的就是AMD规范。

下面是使用AMD规范定义一个名为foo模块的方式,此模块依赖jquery,

//    filename: foo.js
define(['jquery'], function ($) {
    //    methods
    function myFunc(){};

    //    exposed public methods
    return myFunc;
});

AMD讲究的是前置执行。稍微复杂的例子如下,foo模块有多个依赖及方法暴漏,

//    filename: foo.js
define(['jquery', 'underscore'], function ($, _) {
    //    methods
    function a(){};    //    private because it's not returned (see below)
    function b(){};    //    public because it's returned
    function c(){};    //    public because it's returned

    //    exposed public methods
    return {
        b: b,
        c: c
    }
});

define是AMD规范用来声明模块的接口,示例中的第一个参数是一个数组,表示当前模块的依赖。第二个参数是一个回调函数,表示此模块的执行体。只有当依赖数组中的所有依赖模块都是可用的时,AMD模块加载器(比如RequireJS)才会去执行回调函数并返回此模块的暴露接口。

注意,回调函数中参数的顺序与依赖数组中的依赖顺序一致。(即:jquery->$underscore->_

当然,在这里我可以将回调函数的参数名称改成任何我们想用的可用变量名,这并不会对模块的声明造成任何影响。

除此之外,你不能在模块声明的外部使用$或者_,因为他们只在模块的回调函数体中才有定义。

关于AMD规定声明模块的更多内容,请参考这里

CMD规范---通过require('加载依赖’)

CMD规范,全称”Common Module Definition”,称为通用模块加载规范。一般也是用在浏览器端。浏览器端异步加载库Sea.js实现的就是CMD规范。

下面是使用AMD规范定义一个名为foo模块的方式,此模块依赖jquery,

define(function (require, exports, module) {
    // load dependence
    var $ = require('jquery');
    
    //    methods
    function myFunc(){};

    //    exposed public methods
    return myFunc;
})

CMD规范倾向依赖就近,稍微复杂一点例子

define(function (requie, exports, module) {
    // 依赖可以就近书写
    var a = require('./a');
    a.test();
    
    // ...
    // 软依赖
    if (status) {
        var b = requie('./b');
        b.test();
    }
});

关于AMD和CMD的区别,可参考这篇文章,AMD/CMD与前端规范

CommonJS规范---require('加载模块')--module.exports = 暴露的公共方法名称

根据CommonJS规范,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在一个文件定义的变量(还包括函数和类),都是私有的,对其他文件是不可见的。

如果你在Node.js平台上写过东西,你应该会比较熟悉CommonJS规范。与前面的AMD及CMD规范不一样的是,CommonJS规范一般应用于服务端(Node.js平台),而且CommonJS加载模块采用的是同步方式(这跟他适用的场景有关系)。同时,得力于Browserify这样的第三方工具,我们可以在浏览器端使用采用CommonJS规范的js文件。

下面是使用CommonJS规范声明一个名为foo模块的方式,同时依赖jquery模块,

//    filename: foo.js
//    dependencies
var $ = require('jquery');

//    methods
function myFunc(){};

//    exposed public method (single)
module.exports = myFunc;

稍微复杂一点的示例如下,拥有多个依赖以及抛出多个接口,

//    filename: foo.js
var $ = require('jquery');
var _ = require('underscore');

//    methods
function a(){};    //    private because it's omitted from module.exports (see below)
function b(){};    //    public because it's defined in module.exports
function c(){};    //    public because it's defined in module.exports

//    exposed public methods
module.exports = {
    b: b,
    c: c
};

UMD规范--支持AMD和CommonJS规范

因为AMD,CommonJS规范是两种不一致的规范,虽然他们应用的场景也不太一致,但是人们仍然是期望有一种统一的规范来支持这两种规范。于是,UMD(Universal Module Definition,称之为通用模块规范)规范诞生了。

客观来说,这个UMD规范看起来的确没有AMD和CommonJS规范简约。但是它支持AMD和CommonJS规范,同时还支持古老的全局模块模式。

我们来看个示例,

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        // Node, CommonJS-like
        module.exports = factory(require('jquery'));
    } else {
        // Browser globals (root is window)
        root.returnExports = factory(root.jQuery);
    }
}(this, function ($) {
    //    methods
    function myFunc(){};

    //    exposed public method
    return myFunc;
}));

个人觉得UMD规范更像一个语法糖。应用UMD规范的js文件其实就是一个立即执行函数。函数有两个参数,第一个参数是当前运行时环境,第二个参数是模块的定义体。在执行UMD规范时,会优先判断是当前环境是否支持AMD环境,然后再检验是否支持CommonJS环境,否则认为当前环境为浏览器环境(window)。当然具体的判断顺序其实是可以调换的。

下面是一个更加复杂的示例,

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery', 'underscore'], factory);
    } else if (typeof exports === 'object') {
        // Node, CommonJS-like
        module.exports = factory(require('jquery'), require('underscore'));
    } else {
        // Browser globals (root is window)
        root.returnExports = factory(root.jQuery, root._);
    }
}(this, function ($, _) {
    //    methods
    function a(){};    //    private because it's not returned (see below)
    function b(){};    //    public because it's returned
    function c(){};    //    public because it's returned

    //    exposed public methods
    return {
        b: b,
        c: c
    }
}));

Tips: 如果你写了一个小工具库,你想让它及支持AMD规范,又想让他支持CommonJS规范,那么采用UMD规范对你的代码进行包装吧,就像这样

转载自: 前端模块规范AMD/UMD/CommonJs - 绿色袋子 - 博客园

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: CommonJSAMD/CMD是两种不同的模块规范,而ES6则是JavaScript的新标准,也包含了模块化的支持。 CommonJS主要用于服务器端的模块化,其特点是同步加载模块模块输出的是一个对象,可以通过require()方法加载模块AMD/CMD则主要用于浏览器端的模块化,其特点是异步加载模块模块输出的是一个函数,可以通过define()方法定义模块。 ES6的模块化则是JavaScript的新标准,其特点是静态加载模块模块输出的是一个变量,可以通过import和export语句加载和定义模块。 总的来说,CommonJSAMD/CMD是旧的模块规范,而ES6则是新的标准,具有更好的性能和可读性。 ### 回答2: CommonJS是一个模块规范,旨在使JavaScript在服务器端上运行。它在Node.js上得到广泛应用,主要是用于模块管理和代码复用。它定义了模块如何定义以及如何导出和导入模块AMD和CMD是两个常用的模块规范,旨在更好地管理浏览器端的模块AMD和CMD规范都优化了服务器端的加载速度,提高了代码复用性。 ES6是一个新版的JavaScript规范,它增加了许多新的语言特性和语法糖,使得JavaScript更具有可读性和可维护性。ES6规范中引入了模块的概念,通过import和export可以轻松管理模块,并且JS引擎会进行编译优化以提高性能。 CommonJSAMD/CMD的主要区别在于模块的加载方式。CommonJS采用同步加载方式,即导入模块时会等待所有依赖模块都加载完毕后再执行导入操作。这会造成一定的阻塞,但是可以保证依赖关系正确。而AMD/CMD采用异步加载方式,即采用回调函数的方式导入模块,不会造成阻塞,但是需要手动管理依赖关系。 ES6模块的最大优点在于静态编译。在使用ES6模块时,浏览器可以在代码加载时对模块进行静态分析,从而明确哪些模块需要导入和导出,它们的依赖关系以及导入的值。这是在CommonJSAMD/CMD等模块规范中无法做到的。ES6模块的缺点是目前还不是所有的浏览器都支持。 ### 回答3: CommonJSAMD,CMD和ES6是JavaScript使用的模块系统。它们都试图将代码组织为可重用的模块,但它们在一些方面不同。 CommonJS是一个使用Node.js的模块系统,它允许在服务器端和客户端共享模块CommonJS模块是同步加载的,这意味着当模块被请求时,它会立即加载模块,并立即执行模块的代码。 AMD(异步模块定义)是在浏览器环境中使用的模块系统,它允许异步加载模块。当一个模块被请求时,AMD并不会像CommonJS那样立即加载它,而是等待其他模块完成加载。然后,当模块被加载和运行时,AMD会运行任何模块和依赖项的回调函数。 CMD(通用模块定义)是一个应用于浏览器和服务器端的模块系统,它的特点是就近依赖,在需要时才进行依赖的加载。CMD模块是通过define函数来定义的。在调用define时,会传递一个回调函数,该回调函数可以使用require来访问其他模块。 ES6模块是JavaScript的原生模块系统,它允许在JavaScript中定义模块。ES6模块是静态的,这意味着每个模块都是在编译时确定的。ES6模块支持默认导出和命名导出。 在总体上,CommonJS适合于服务器端,AMD和CMD适合于浏览器端,而ES6则是一个全面的模块系统,适用于任何环境。不同的模块系统在实现上有所不同,选择哪种类型的模块系统需要根据具体情况进行判断。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值