打造最出色的模块加载框架:SeaJS Module Loader v0.3.0 预览版
?
http://www.uini.net/2011/01/load-modules-to-create-the-best-framework-seajs-module-loader-v0-3-0-preview.html
?
来看示例:
// math.jsMath = {};Math.add = function(n, m) { return n + m; };// increment.jsfunction increment(val) { return Math.add(val, 1); }// program.jsalert(increment(1));假设 math.js 是数学静态方法库,increment.js 是具体业务代码,program.js 是执行入口。在 html 页面,最直接的引入方式:
<script src="math.js"></script><script src="increment.js"></script><script src="program.js"></script>
在真实场景下,上面的方式有以下问题:
针对上面的问题,典型的解决方法有:
X.Math, X.Biz?等命名空间。YUI.add和?YUI.use我们重点分析 YUI3 的解决方案:
// math.jsYUI.add('math', function(Y) { Y.Math = {}; Y.Math.add = function(n, m) { return n + m; };});// increment.jsYUI.add('increment', function(Y) { var Math = Y.Math; Y.increment = function (val) { return Math.add(val, 1); }}, '1.0', { requires: ['math'] });// program.jsYUI.add('program', function(Y) { alert(Y.increment(1));}, '1.0', { requires: ['increment'] });页面中的引入方式如下:
<script src="yui-min.js"></script><script> YUI({ modules: { 'math': { fullpath: 'math.js' }, 'increment': { fullpath: 'increment.js', requires: ['math'] }, 'program': { fullpath: 'program.js', requires: ['increment'] } } }).use('program');</script>online demo:?math/yui3/test.html
YUI3 的解决方案已经很不错,但以下几点依旧有改进空间:
YUI({modules:{...}})?中的代码,也比较恼人。进一步考虑普适性和 DRY 原则,还可以分析出以下不足:
YUI().use('dd-drop', function(Y) { /*Y.DD*/ }), 这种不对应会加重使用者的记忆负担,不够直观。总之,在模块加载上,YUI3 很重,不光文件重,配置也重。在 CommonJS 时代,我们或许有更好的选择。
SeaJS 的灵感来自?CommonJS 规范。Modules/2.0 规范目前还在讨论中:CommonJS Moules/2.0. SeaJS 遵循了规范里的大部分规定。其核心理念有:
在 CommonJS Modules/2.0 里,我们这样写代码:
// math.jsmodule.declare([], function(require, exports) { exports.add = function(n, m) { return n + m; };});// increment.jsmodule.declare(['math'], function(require, exports) { var add = require('math').add; exports.increment = function(val) { return add(val, 1); }});// program.jsmodule.declare(['increment'], function(require) { var inc = require('increment').increment; alert(inc(1));});html 页面里的写法也很简单:
<script src="module.js"></script><script> module.provide(['increment'], function(require) { var inc = require('increment').increment; alert(inc(1)); });</script>或者更简明的写成:
<script src="module.js" data-main="program"></script>
online demo:?math/seajs/test.html
上面的示例,已经将 SeaJS Module Loader 的 API 都演示完了:
module.declare(id?, deps, factory)module.provide(ids, callback)require(id)表面上看起来, 和 YUI3 很类似。但从设计上分析,存在质的区别:
var xx = require('xx-id')?来获取,彻底脱离了对命名空间的依赖;从实现上看,SeaJS 还有以下优点:
require(id)?时才执行,这能节省初始 cpu 消耗,甚至整体消耗;更多功能可以看测试用例:Test Suite for module.js
目前 SeaJS 还在开发中,对于 packages 的支持、模块版本、时间戳、子模块等等,依旧还存在设计和摸索中,如果你有兴趣,非常欢迎 fork 以下代码:
seajs on github
?