前段时间一直想用单页开发技术写一个本身的我的网站(使用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