前段時間一直想用單頁開發技術寫一個本身的我的網站(使用es2015),寫了一部分以後,發現單頁應用由於只有一個頁面,因此第一次加載index.html時就要下載全部js文件,而且爲了好管理各個部分的狀態,須要劃分頁面的各個功能區爲各個模塊,es2015自己是不支持一些模塊規範的(好比AMD、CMD、CommonJs等),因此只能這樣模擬實現:javascript
// global var spa = (function(){...})(); // module blog spa.blog = (function(){ ... return { do1: do1, do2: do2, }; })(); // module model spa.model = (function(){...})(); // module shell spa.model = (function(){...})();
而且各個模塊之間又存在一些依賴關係,在index.html裏面寫script標籤來載入模塊時須要寫不少個,同時也要根據依賴關係來肯定書寫順序,頁面邏輯混亂,以下:html
<script type="text/javascript" src="/javascripts/spa.utils.js"></script> <script type="text/javascript" src="/javascripts/spa.model.js"></script> <script type="text/javascript" src="/javascripts/spa.mock.js"></script> <script type="text/javascript" src="/javascripts/spa.chat.js"></script> <script type="text/javascript" src="/javascripts/spa.blog.js"></script> <script type="text/javascript" src="/javascripts/spa.action.js"></script> <script type="text/javascript" src="/javascripts/spa.shell.js"></script>
以前用過RequireJs(一個流行的JavaScript模塊加載器),它是用同構js的架構來寫的,因此node.js環境下也能使用。我想本身能夠嘗試一下寫一個低配版的js模塊加載器 requireJs-nojsja 來應付一下我這個單頁網站,固然只是大體模仿了主要功能。java
requirejs.config({ baseUrl: '/javascripts', // 配置根目錄 paths: { moduleA: 'a.js', moduleB: 'b.js', moduleC: 'c.js', }, shim: { // 配置不遵循amd規範的模塊 moduleC: { exports: 'log', deps: ['moduleA'] } }, });
define(name, ['moduleA', 'moduleB'], function(a, b){ ... return { do: function() { a.doSomething(); b.doAnother(); } }; });
// 引用模塊 require(['moduleA', 'moduleB'], function(a, b) { a.doSomething(); b.doAnother(); });
/* 記錄模塊訪問地址和模塊的依賴等信息 */ Require.config({ baseUrl: '/javascripts/', paths: { 'moduleA': './moduleA.js', // 相對於當前目錄 'moduleB': '/javascripts/moduleB.js', // 不使用baseUrl 'moduleC': 'moduleC.js', 'moduleD': { url: 'moduleD.js', deps: ['moduleE', 'moduleF'], }, ... }, shim: { 'moduleH': { url: 'moduleH.js', exports: 'log', }, } });
(1) config配置模塊信息時並不會觸發網絡請求
(2) 在index.js主入口文件裏使用require方法引用多個模塊時,根據config配置文件構造一下全部模塊的依賴分析樹。按深度優先或是廣度優先來遍歷這個依賴樹,將全部依賴按照依賴順序放進一個數組,最後進行數組去重處理,由於會出現依賴重複的狀況node
var dependsTree = new Tree('dependsTree'); var dependsArray = []; var dependsFlag = {}; // 解決循環依賴 // 建立樹 setDepends(depends, dependsTree); // 獲得依賴數組 sortDepends(dependsArray, dependsTree); // 數據去重 arrayFilter(dependsArray); return dependsArray;
(3) 建立XHR對象異步下載數組裏面的全部js文件,按照依賴順序挨個解析js代碼,解析完成後觸發回調函數,回調函數裏傳入各個模塊的引用git
// ajax下載代碼文件 Utils.request(url, 'get', null, function(responseText){ // 暫時保存 _temp[module_name] = responseText; }); // 文件下載完成後eval解析代碼 array.map(function(jsText){ ... eval(jsText); ... }); // 調用回調函數 callback.apply(null, [dep1, dep2, dep3]);
詳細說明: github README.mdgithub