官网的介绍:
Sea.js 追求简单、自然的代码书写和组织方式,具有以下核心特性:

  • 简单友好的模块定义规范:Sea.js 遵循 CMD 规范,可以像 Node.js 一般书写模块代码。
  • 自然直观的代码组织方式:依赖的自动加载、配置的简洁清晰,可以让我们更多地享受编码的乐趣。

Sea.js 还提供常用插件,非常有助于开发调试和性能优化,并具有丰富的可扩展接口。

社区说:

SeaJS 的理念的是 海纳百川、有容乃大,推崇开放与自由

下载 https://github.com/seajs/seajs/releases

CMD模块规范

在 Sea.js 中,所有 JavaScript 模块都遵循 CMD(Common Module Definition) 模块定义规范。该规范明确了模块的基本书写格式和基本交互规则

在 CMD 规范中,一个模块就是一个文件。代码的书写格式如下:

1
2
3
define(function(require, exports, module){
doSomething...
});

define 的参数有多种类型,可以是字符串、对象、函数等;还有 define 也可以传入多个参数:

1
2
3
4
// define(id?, deps?, factory)
define('hello',['jquery'], function(require, exports, module){
doSomething...
});

字符串 id 表示模块标识,数组 deps 是模块依赖,上面的写法是省略 id, deps 参数的写法,因此前两个参数是可以省略的。

注意:带 id, deps 参数的 define 用法不属于 CMD 规范,而属于 Modules/Transport 规范。

require, exportsmodule 三个参数的用法在下面 sea.js 的 API 中有所介绍。

常用API

seajs.config

用来对 Sea.js 进行配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
seajs.config({

// 设置路径,方便跨目录调用
paths: {
'arale': 'https://a.alipayobjects.com/arale',
'jquery': 'https://a.alipayobjects.com/jquery'
},

// 设置别名,方便调用
alias: {
'class': 'arale/class/1.0.0/class',
'jquery': 'jquery/jquery/1.10.1/jquery'
}

});

seajs.use

用来在页面中加载一个或多个模块。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 加载一个模块
seajs.use('./a');

// 加载一个模块,在加载完成时,执行回调
seajs.use('./a', function(a) {
a.doSomething();
});

// 加载多个模块,在加载完成时,执行回调
seajs.use(['./a', './b'], function(a, b) {
a.doSomething();
b.doSomething();
});

define

用来定义模块。Sea.js 推崇一个模块一个文件,遵循统一的写法:

1
2
3
4
5
define(function(require, exports, module) {

// 模块代码

});

require, exportsmodule 三个参数可酌情省略,具体用法如下。

require

require 用来获取指定模块的接口。

1
2
3
4
5
6
7
8
define(function(require) {

// 获取模块 a 的接口
var a = require('./a');

// 调用模块 a 的方法
a.doSomething();
});

注意,require 只接受字符串直接量作为参数,

require.async

用来在模块内部异步加载一个或多个模块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
define(function(require) {

// 异步加载一个模块,在加载完成时,执行回调
require.async('./b', function(b) {
b.doSomething();
});

// 异步加载多个模块,在加载完成时,执行回调
require.async(['./c', './d'], function(c, d) {
c.doSomething();
d.doSomething();
});

});

exports

用来在模块内部对外提供接口。

1
2
3
4
5
6
7
8
9
define(function(require, exports) {

// 对外提供 foo 属性
exports.foo = 'bar';

// 对外提供 doSomething 方法
exports.doSomething = function() {};

});

module.exports

与 exports 类似,用来在模块内部对外提供接口。

1
2
3
4
5
6
7
8
9
define(function(require, exports, module) {

// 对外提供接口
module.exports = {
name: 'a',
doSomething: function() {};
};

});

总结

sea.js的优点

1,通过exports暴露接口。不需要命名空间,不需要全局变量。

2,通过require引入依赖。让依赖内置,开发者只关心当前模块的依赖,其他事情Seajs都会自动处理好。 其他好处: 1,模块的版本管理。通过别名配置,配合构建工具,可以比较轻松地实现模块的版本管理。 2,提高可以维护性。

3,前端性能优化。通过异步加载模块,对性能非常有益。

4,跨环境共享模块。 随着Dojo,YUI3,Node.js推广和流行,前端模块化才开始深入人心。 一类是大教堂模式。如Dojo,YUI3,KISSY等。所有组件都是颗粒化、模块化的,各组件之间层层分级、环环相扣。 一类是集市模式。如 jQuery、RequireJS、Sea.js、OzJS 等。所有组件彼此独立、职责单一,各组件通过组合松耦合在一起,协同完成开发。

sea.js缺点

1.文档很烂,官网只有一个很简单的例子,玉伯开了用Github issues 做文档的坏头,导致有的文档issue 里说的东西已经过时了,给人误导。

2.打包痛苦,配置起来极其复杂,而且一变再变,早期的transport/concat组件简直了,bug挺多。而且这个打包跟spm的关系到底是啥?!!

3.sea.js文件路径,模块路径,spm路径,打包路径,相对路径,绝对路径,html入口文件路径,这些关系在sea.js初期的时候开发团队没有理清楚,现在我也不知道seajs3和spm3搞清楚没。

4.每个小版本大版本都有很大变化,从seajs1到2到3,每次变化都挺大的,有些配置莫名其妙地就没了,也没有一个统一的文档来记录。

摘自知乎LABjs、RequireJS、SeaJS 哪个最好用?为什么? 鲁小夫的回答。

ddAnswer

更多文章请关注微信公众号: zhiheng博客