来源于:阿贤博客javascript
今天给你们写一篇关于前端模块化开发知识点。
前端模块化开发那点历史
php
模块化:html
模块化系统所必须的能力:前端
好了,思想有了,那么总要有点什么来创建一个模块化的规范制度吧,否则各式各样的模块加载方式只会将局搅得更为混乱。那么在JavaScript中出现了一些非传统模块开发方式的规范 CommonJS的模块规范,AMD(Asynchronous Module Definition),CMD(Common Module Definition)等。java
为了创建一个模块化的规范制度、模块加载方式。在JavaScript中出现了一些非传统模块开发方式的规范 CommonJS的模块规范,AMD(Asynchronous Module Definition)、CMD(Common Module Definition)、ES6模块诞生了。
AMD(Asynchronous Module Definition)异步模块定义,全部的模块将被异步加载,模块加载不影响后面语句运行。全部依赖这个模块的语句,都定义在一个回调函数中,等到加载完成以后,这个回调函数才会运行。
AMD规范定义了一个自由变量或者说是全局变量 define 的函数。node
AMD规范jquery
define("alpha", [ "require", "exports", "beta" ], function( require, exports, beta ){ export.verb = function(){ return beta.verb(); // or: return require("beta").verb(); } });
define(["alpha"], function( alpha ){ return { verb : function(){ return alpha.verb() + 1 ; } } });
define( { add : function( x, y ){ return x + y ; } } );
require API
在 AMD 规范中的 require 函数与通常的 CommonJS中的 require 不一样。因为动态检测依赖关系使加载异步,对于基于回调的 require 需求强烈。git
局部的 require 须要在AMD模式中的 define 工厂函数中传入 require。es6
define( ['require'], function( require ){ // ... } ); or: define( function( require, exports, module ){ // ... } );
局部的 require 须要其余特定的 API 来实现。
github
全局的 require 函数是惟一全局做用域下的变量,像 define同样。全局的 require 并非规范要求的,可是若是实现全局的 require函数,那么其须要具备与局部 require 函数 同样的如下的限定:<br /> 1. 模块标识视为绝对的,而不是相对的对应另外一个模块标识。<br /> 2. 只有在异步状况下,require的回调方式才被用来做为交互操做使用。由于他不可能在同步的状况下经过 require(String) 从顶层加载模块。<br /> 依赖相关的API会开始模块加载。若是须要有互操做的多个加载器,那么全局的 reqiure 应该被加载顶层模块来代替。
require(String) define( function( require ){ var a = require('a'); // 加载模块a } ); require(Array, Function) define( function( require ){ require( ['a', 'b'], function( a,b ){ // 加载模块a b 使用 // 依赖 a b 模块的运行代码 } ); } ); require.toUrl( Url ) define( function( require ){ var temp = require.toUrl('./temp/a.html'); // 加载页面 } );
官网
API
API 中文
RequireJS 是一个前端的模块化管理的工具库,遵循AMD规范,它的做者就是AMD规范的创始人 James Burke。
页面顶层<script>标签含有一个特殊的属性data-main,require.js使用它来启动脚本加载过程,而baseUrl通常设置到与该属性相一致的目录。下列示例中展现了baseUrl的设置:
<script data-main="scripts/main.js" src="scripts/require.js"></script>
defined用于定义模块,RequireJS要求每一个模块均放在独立的文件之中。按照是否有依赖其余模块的状况分为独立模块和非独立模块。
define({ method1: function(){}, method2: function(){} }); //等价于 define(function(){ return{ method1: function(){}, method2: function(){} } });
define([ 'module1', 'module2' ], function(m1, m2){ //代码... }); //等价于 define( function( require ){ var m1 = require( 'module1' ), m2 = require( 'module2' ); //代码... });
define 和 require 这两个定义模块,调用模块的方法合称为AMD模式,定义模块清晰,不会污染全局变量,清楚的显示依赖关系。AMD模式能够用于浏览器环境而且容许非同步加载模块,也能够按需动态加载模块。
/*** **** require方法调用模块 **** 在加载 foo 与 bar 两个模块以后执行回调函数实现具体过程。 ***/ require( ['foo', 'bar'], function( foo, bar ){ foo.func(); bar.func(); } ); /*** **** 在define定义模块内部进行require调用模块 ***/ define( function( require ){ var m1 = require( 'module1' ), m2 = require( 'module2' ); //代码... });
在CMD中,一个模块就是一个文件,格式为:
[CMD模块定义规范]( https://github.com/seajs/seaj...)
全局函数define,用来定义模块。
参数 factory 能够是一个函数,也能够为对象或者字符串。
当 factory 为对象、字符串时,表示模块的接口就是该对象、字符串。
define({ "foo": "bar" });
define('this is {{data}}.');
//表示模块的构造方法,执行构造方法即可以获得模块向外提供的接口。 define( function(require, exports, module) { // 模块代码 });
define也能够接受两个以上的参数,字符串id为模块标识,数组deps为模块依赖:
define( 'module', ['module1', 'module2'], function( require, exports, module ){ // 模块代码 } );
其与 AMD 规范用法不一样。
require 是 factory 的第一个参数。
require( id );
接受模块标识做为惟一的参数,用来获取其余模块提供的接口:
define(function( require, exports ){ var a = require('./a'); a.doSomething(); });
require是同步往下执行的,须要的异步加载模块可使用 require.async 来进行加载:
define( function(require, exports, module) { require.async('.a', function(a){ a.doSomething(); }); });
可使用模块内部的路径机制来返回模块路径,不会加载模块。
define(function( require, exports ){ exports.foo = 'bar'; // 向外提供的属性 exports.do = function(){}; // 向外提供的方法 }); //使用 return 直接向外提供接口。 define(function( require, exports ){ return{ foo : 'bar', // 向外提供的属性 do : function(){} // 向外提供的方法 } }); //简化为直接对象字面量的形式: define({ foo : 'bar', // 向外提供的属性 do : function(){} // 向外提供的方法 });
module.id 为模块的惟一标识。
module.uri 根据模块系统的路径解析规则获得模块的绝对路径。
module.dependencies 表示模块的依赖。
module.exports 当前模块对外提供的接口。
官网( http://seajs.org/)已经关闭。
其define 与 require 使用方式基本就是CMD规范中的示例。
sea.js 核心特征:
兼容 Chrome 3+,Firefox 2+,Safari 3.2+,Opera 10+,IE 5.5+。
用来在页面中加载一个或者多个模块
// 加载一个模块 seajs.use('./a'); // 加载模块,加载完成时执行回调 seajs.use('./a',function(a){ a.doSomething(); }); // 加载多个模块执行回调 seajs.use(['./a','./b'],function(a , b){ a.doSomething(); b.doSomething(); });
玉伯对于 AMD 与 CMD 区别的解释:
AMD 是 RequireJS 在推广过程当中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程当中对模块定义的规范化产出。
相似的还有 CommonJS Modules/2.0 规范,是 BravoJS 在推广过程当中对模块定义的规范化产出
// 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 的做者默认是最喜欢上面的写法,也是官方文档里默认的模块定义写法。
另外,SeaJS 和 RequireJS 的差别
UMD
AMD、CMD、UMD 模块
既然CommonJs和AMD风格同样流行,彷佛缺乏一个统一的规范。因此人们产生了这样的需求,但愿有支持两种风格的“通用”模式,因而通用模块规范(UMD)诞生了。
(function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD define(['jquery'], factory); } else if (typeof exports === 'object') { // Node, CommonJS之类的 module.exports = factory(require('jquery')); } else { // 浏览器全局变量(root 即 window) root.returnExports = factory(root.jQuery); } }(this, function ($) { // 方法 function myFunc(){}; // 暴露公共方法 return myFunc; })); //复杂、依赖了多个组件而且暴露多个方法 (function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD define(['jquery', 'underscore'], factory); } else if (typeof exports === 'object') { // Node, CommonJS之类的 module.exports = factory(require('jquery'), require('underscore')); } else { // 浏览器全局变量(root 即 window) root.returnExports = factory(root.jQuery, root._); } }(this, function ($, _) { // 方法 function a(){}; // 私有方法,由于它没被返回 (见下面) function b(){}; // 公共方法,由于被返回了 function c(){}; // 公共方法,由于被返回了 // 暴露公共方法 return { b: b, c: c } }));
ES6
Module 的语法
ES6 模块的设计思想,是尽可能的静态化,使得编译时就能肯定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时肯定这些东西。好比,CommonJS 模块就是对象,输入时必须查找对象属性。
// ES6模块 import { stat, exists, readFile } from 'fs';
上面代码的实质是从fs模块加载3个方法,其余方法不加载。这种加载称为“编译时加载”或者静态加载,即 ES6 能够在编译时就完成模块加载。
AMD规范文档
amdjs 的 require 接口文档
amdjs 的接口文档
RequireJS官网接口文档
模块系统
前端模块化开发的价值
前端模块化开发那点历史
CMD 模块定义规范
SeaJS API快速参考
从 CommonJS 到 Sea.js
RequireJS和AMD规范
CommonJS规范
JavaScript模块化开发 - CommonJS规范
JavaScript模块化开发 - AMD规范
Javascript模块化编程1
Javascript模块化编程2
知乎 AMD 和 CMD 的区别有哪些?
与 RequireJS 的异同
模块化设计
模块化
ES6
Module 的语法
来源于:阿贤博客