amd specification to commonjs specification

The purpose is that the specification of components can be unified when installing external components in the project framework.

Due to the lack of overall documentation in the early development, the details have not been remembered clearly. First paste the code address: https://github.com/tianmiyingzi/feather2-command-install

Knowledge points to know: AMD specification, CMD specification, Comonjs specification, UMD specification, etc.


The following are the research knowledge points:

Javascript modular programming

Q: Why modular?

A: Improve code reuse.

Q: How about modularization?

Answer: The modular experience process: simply put functions together → object writing → immediate function writing → enlargement mode → Loose augmentation → input global variables

1. " Polluted " global variables, there is no guarantee that there will be no variable name conflicts with other modules, and there is no direct relationship between module members

2. Expose all module members, the internal state can be rewritten externally

3. "Wide enlargement mode" means that the parameter of " immediate execution function " can be an empty object

Keywords:

" Immediately execute the function " ( Immediately-InvokedFunction Expression , IIFE


CommonJS specification

CommonJS is primarily a specification for server-side modules, and Node.js adopts this specification.

Each module is a separate scope, that is, variables defined within the module cannot be read by other modules unless they are defined as properties of the global object.

 Concept (Origin) :

The API defined by the official JavaScript standard is for building browser-based applications. However, there is no standard library for a wider range of applications.

The CommonJS API fills this gap by defining APIs used by many common applications (mainly non-browser applications). Its ultimate goal is to provide a standard library like Python, Ruby and Java. This way, developers can use the CommonJS API to write applications that can then run on different JavaScript interpreters and different host environments.

On CommonJS compatible systems, you can develop JavaScript applications using:
Server-side JavaScript applications
Command-line
tools GUI applications
Hybrid applications (e.g. Titanium or Adobe AIR)

content:

1. In a module, there is a free variable "require", which is a function.

The "require" function accepts a module identifier.

"require" returns the API exported by the external module.

If there is a dependency cycle, the external module may not be executed when it is required by its transitive dependencies ; in this case, the object returned by "require" must contain at least this external module The output that has been prepared before calling the require function (which will enter the current module execution environment). (Translator: If it is difficult to understand, see the example below .)

If the requested module cannot be returned, then "require" must throw an error.

2. In a module, there will be a free variable named "exports", which is an object, and the module can add its own API to it during execution.

3. The module must use the "exports" object as the only representation of the output.

 

AMD Specifications

框架是RequireJS

//    filename: foo.js

define(['jquery', 'underscore'], function($, _) {

    //   methods

    function a(){};   //    private because it's not returned (seebelow)

    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 -> _ 

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

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

 

CMD规范

CMD是国内玉伯大神在开发SeaJS的时候提出来的,属于CommonJS的一种规范

 

UMD规范

umd是AMD和CommonJS的糅合

AMD 浏览器第一的原则发展 异步加载模块。

CommonJS 模块以服务器第一原则发展,选择同步加载,它的模块无需包装(unwrapped modules)。

这迫使人们又想出另一个更通用的模式UMD (Universal Module Definition)。希望解决跨平台的解决方案。

UMD先判断是否支持Node.js的模块(exports)是否存在,存在则使用Node.js模块模式。

在判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块。

(function (window, factory) {

    if (typeof exports === 'object') {

      module.exports = factory();

    } else if (typeof define === 'function' && define.amd) {

     define(factory);

    } else {

    window.eventUtil = factory();

    }

})(this, function () {

    //module ...

});

 

CommonJS与AMD比较

CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。

AMD规范则是非同步加载模块,允许指定回调函数。

由于Node.js主要用于服务器编程,模块文件一般都已经存在于本地硬盘,所以加载起来比较快,不用考虑非同步加载的方式,所以CommonJS规范比较适用。但是,如果是浏览器环境,要从服务器端加载模块,这时就必须采用非同步模式,因此浏览器端一般采用AMD规范

 

AMD与CMD比较

1、二者都是异步模块定义(AsynchronuousModule Definition)的一个实现;
2、AMD和CMD都是CommonJS的一种规范的实现定义,RequireJS和SeaJS是对应的实践;
3、AMD和CMD的区别:

1.CMD推崇依赖就近,AMD推崇依赖前置:CMD相当于按需加载,定义一个模块的时候不需要立即制定依赖模块,在需要的时候require就可以了,比较方便;而AMD则相反,定义模块的时候需要制定依赖模块,并以形参的方式引入factory中。

2.对于依赖的模块AMD是提前执行,CMD是延迟执行。不过RequireJS从2.0开始,也改成可以延迟执行(根据写法不同,处理方式不通过)。 

3. AMDapi默认是一个当多个用,CMD严格的区分推崇职责单一。例如:AMDrequire分全局的和局部的。CMD里面没有全局的require,提供 seajs.use()来实现模块系统的加载启动。CMD里每个API都简单纯粹。

区别看下边例子:

//AMD方式定义模块

define(['dep1','dep2'],function(dep1,dep2){

     //内部只能使用制定的模块

      return function(){};

});

//CMD

define(function(require,exports,module){

   //此处如果需要某XX模块,可以引入

   var xx=require('XX');

});

4、JavaScript语言是弱结构性的,通过CommonJS定义一些规范,CMD和AMD得定义模块的方式对代码进行管理,使得更易维护;此外,NodeJS的诞生,对模块的规范定义,和包(npm)的概念的引入,让JS管理不再困难!

 

CommonJS依赖闭环解释

因为node.js完全实现了CommonJS Modules/1.0规范,那么我们用其来解释CommonJS Modules/1.0中的依赖闭环问题。看如下代码:

a.js

console.log('a starting');

exports.done = false;

var b = require('./b.js');

console.log('in a, b.done = %j', b.done);

exports.done = true;

console.log('a done');

b.js

console.log('bstarting');

exports.done= false;

var a =require('./a.js');

console.log('inb, a.done = %j', a.done);

exports.done= true;

console.log('bdone');

main.js

console.log('main starting');

var a = require('./a.js');

var b = require('./b.js');

console.log('in main, a.done=%j,b.done=%j', a.done, b.done);

 

当main.js加载a.js的时候,a.js加载b.js,同时,b.js想要加载a.js,这时候就产生了依赖闭环的问题,为了避免无限循环,需要打破这个闭环。根据CommonJS Modules/1.0规范中的说明「在这种情况下,”require”返回的对象必须至少包含此外部模块在调用require函数(会进入当前模块执行环境)之前就已经准备完毕的输出。」,有些绕,让我们从依赖闭环产生的地方跟踪,b.js需要require a.js,这里b.js做为当前模块,a.js相对于b.js来说是外部模块,那么a.js的输出应该是在其require b.js之前(即「进入当前模块执行环境」)就应该返回,执行过程如下:

a.js

console.log('a starting');

exports.done = false;

// 只执行到这里,然后exports返回给调用模块(b.js),以下被丢弃

var b = require('./b.js');

console.log('in a, b.done = %j', b.done);

exports.done = true;

console.log('a done');

 

然后b.js继续执行完成。以下是执行结果:

$ node main.js

main starting

a starting

b starting

in b, a.done = false

b done

in a, b.done = true

a done

in main, a.done=true, b.done=true

 

注意,虽然main.js同时require了a.js和b.js,但是根据node.js的模块缓存策略,模块只执行一次。



以下是调研工具笔记:

1.amd-to-common

Github地址:https://github.com/Willyham/amd-to-common

很单一

不管位置,只寻找第一个defined定义,并分析转化。第一个defined前后的内容会自动过滤。

2. recast-to-cjs

http://skookum.com/blog/converting-a-project-from-amd-to-cjs-with-recast

Github地址:https://github.com/Skookum/recast-to-cjs

涵盖的形式较多。

没有运行起来


这两个主要是看思路的,思路和都和上面差不多

3. 基于browserify的插件unamd

https://www.npmjs.com/package/unamd

4. 基于browserify的插件browserify-ftw

https://github.com/thlorenz/browserify-ftw/blob/master/examples/RyanFitzer-RequireJs-Jquery.md#initializing-the-npm-package-and-installing-dependencies

 

这个是转成UMD或者混合形式

5. uRequire

https://github.com/anodynos/uRequire

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1.amd-to-common

Github地址:https://github.com/Willyham/amd-to-common

 

很单一

不管位置,只寻找第一个defined定义,并分析转化。第一个defined前后的内容会自动过滤。

 

2. recast-to-cjs

http://skookum.com/blog/converting-a-project-from-amd-to-cjs-with-recast

Github地址:https://github.com/Skookum/recast-to-cjs

涵盖的形式较多。

没有运行起来

 

 

 

这两个主要是看思路的,思路和都和上面差不多

 

3. 基于browserify的插件unamd

https://www.npmjs.com/package/unamd

 

4. 基于browserify的插件browserify-ftw

https://github.com/thlorenz/browserify-ftw/blob/master/examples/RyanFitzer-RequireJs-Jquery.md#initializing-the-npm-package-and-installing-dependencies

 

这个是转成UMD或者混合形式

5. uRequire

https://github.com/anodynos/uRequire

 

 

 

 

 

 

 

 

工具调研

1.amd-to-common

Github地址:https://github.com/Willyham/amd-to-common

 

很单一,只能完成单一形式的转化。

不管位置,只寻找第一个defined定义,并分析转化。第一个defined前后的内容会自动过滤。

 

2. recast-to-cjs

http://skookum.com/blog/converting-a-project-from-amd-to-cjs-with-recast

Github地址:https://github.com/Skookum/recast-to-cjs

涵盖的形式较多。

没有运行起来

 

3. 基于browserify的插件unamd

https://www.npmjs.com/package/unamd

 

4. 基于browserify的插件browserify-ftw

https://github.com/thlorenz/browserify-ftw/blob/master/examples/RyanFitzer-RequireJs-Jquery.md#initializing-the-npm-package-and-installing-dependencies

 

 

5. uRequire

https://github.com/anodynos/uRequire

 a tool for javascript module formatconversion - AMD/Requirejs --> commonjs/nodejs and back (plus more).

 

 

 

 

// with a list of dependencies

define(['react'], function(React) {

 // optional return value which is the module itself;

 return React.createClass({});

});

 

// with a variable listing dependencies.This is not recommended.

var DEPENDENCIES = ['react'];

define(DEPENDENCIES, function(React) {

 return React.createClass({});

});

 

// with no dependencies

require(function() {

 return {};

});

 



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325690805&siteId=291194637