來源於:阿賢博客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 的語法
來源於:阿賢博客