前端模块规范AMD/UMD/CommonJs

前端模块规范AMD/UMD/CommonJs

.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,

12345678

// filename: foo.jsdefine(['jquery'], function ($) { // methods function myFunc(){}; // exposed public methods return myFunc;});

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

12345678910111213

// filename: foo.jsdefine(['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,

12345678910

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

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

123456789101112

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模块,

123456789

// filename: foo.js// dependenciesvar $ = require('jquery');// methodsfunction myFunc(){};// exposed public method (single)module.exports = myFunc;

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

1234567891011121314

// filename: foo.jsvar $ = require('jquery');var _ = require('underscore');// methodsfunction a(){}; // private because it's omitted from module.exports (see below)function b(){}; // public because it's defined in module.exportsfunction c(){}; // public because it's defined in module.exports// exposed public methodsmodule.exports = { b: b, c: c};

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

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

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

我们来看个示例,

123456789101112131415161718

(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)。当然具体的判断顺序其实是可以调换的。

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

1234567891011121314151617181920212223

(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规范对你的代码进行包装吧,就像这样。

转载自:http://blog.gejiawen.com/2015/11/03/what-is-amd-cmd-commonjs-umd/

感谢

相关数据流

舞钢市盛誊电子商务有限公司
假的365不让提款怎么办

舞钢市盛誊电子商务有限公司

⌚ 12-02 👁️‍🗨️ 1388
苹果不能和什么一起吃/同吃
假的365不让提款怎么办

苹果不能和什么一起吃/同吃

⌚ 10-21 👁️‍🗨️ 1478
报名培训健身教练费用需要多少,清波健身教练培训告诉你
365bet最快线路监测中心

报名培训健身教练费用需要多少,清波健身教练培训告诉你

⌚ 12-05 👁️‍🗨️ 5473