seajs引入基础javascript库的做法

968 views
Skip to first unread message

alex bian

unread,
Jul 20, 2012, 5:41:20 AM7/20/12
to se...@googlegroups.com
使用场景是这样的:比如说我有若干个基础库要用到工程中,如:绘图,设备扩展支持 等等。

但是这个基础库不同于jquery,可以用一个全局变量就访问其所有的对象和方法,而是有很多个模块化好的对象存在于作用域中,而且情况还会更多。

而我不希望通过seajs.use去加载再在里面的callback去实现,也不希望去用require赋值的方式现实加载到全局对象和作用域中,如:var ss = require('xxx');

希望大家能讨论一下其他的方法,谢谢!

alex bian

unread,
Jul 20, 2012, 5:49:52 AM7/20/12
to se...@googlegroups.com
而且如果要使用require就必须对要引入的文件 使用CMD标准封装,不知道这样做会不会引起其他的问题?

在 2012年7月20日星期五UTC+8下午5时41分20秒,alex bian写道:

Eddy Wang

unread,
Jul 20, 2012, 6:01:08 AM7/20/12
to se...@googlegroups.com
我最近也有类似的需求。
一般情况下我会框架使用CMD标准进行封装。如果必须要使用到全局变量时,我就直接require该框架文件。貌似没有遇到问题。但是不知这种方式会不会引起一些问题


2012/7/20 alex bian <alex...@gmail.com>

Eddy Wang

unread,
Jul 20, 2012, 9:13:40 AM7/20/12
to se...@googlegroups.com
突然想到,如果直接使用require未define的js,应该是不会有太大问题的。

因为seajs在require时只是将js加载下来,然后插入到页面中,浏览器就开始执行js。

如果js中含有define,那么seajs就进行模块的注册,如果没有define,浏览器就执行js了。但这里有个问题,就是seajs没有对这个js进行注册,所以seajs.cache中是不会有该js的信息,所以在第二次require该模块时,seajs还是会重新加载该就是js。当然如果真的希望所应用的js是全局的,也就没必要在require第2次了。

不知理解的对否。

2012/7/20 Eddy Wang <son...@gmail.com>

Frank Wang

unread,
Jul 20, 2012, 10:59:23 AM7/20/12
to se...@googlegroups.com
这个其实很简单,直接 require 就好

比如要加载未封装的 jquery,直接:


require('jquery')

$.xxx  // 直接调用就好


这时 seajs 从模块加载器降级为文件加载器,中间会做去重的,不会重新下载文件,不会有问题。



2012/7/20 Eddy Wang <son...@gmail.com>



--
王保平 / 玉伯(射雕)
送人玫瑰手有余香

Frank Wang

unread,
Jul 20, 2012, 11:01:05 AM7/20/12
to se...@googlegroups.com

非 define 的模块,seajs.cache 也会注册的,只是 module.exports 为 null

这时要调用,需要自己知道通过哪个全局变量去拿,比如未封装的 jquery,可以:

require('jquery')

$.xxx // 自己通过全局 $ 去拿到 jquery 的引用


2012/7/20 Eddy Wang <son...@gmail.com>

honingwon

unread,
Jul 20, 2012, 11:10:57 AM7/20/12
to seajs
确实,如果require的是未封装模块,此时的seajs降级为像LABjs的文件加载器。
 
如果所有的文件都是未封装的模块,用LABjs好了。
 
另外,seajs调用未封装的模块,像玉伯说的,seajs会注册模块,状态码为1,module.exports 为 undefined。
 
还有个有意思的现象,如果seajs再去调用这个模块,状态码变成4,module.exports 为空对象。
 
1.2的seajs版本。
 
2012-07-20

honingwon

发件人:Frank Wang
发送时间:2012-07-20 22:59
主题:Re: seajs引入基础javascript库的做法
收件人:"seajs"<se...@googlegroups.com>
抄送:
Message has been deleted

alex bian

unread,
Jul 21, 2012, 7:04:39 AM7/21/12
to se...@googlegroups.com
额,我试验的结果是状态码为2,“再次调用”你指的是什么情况? 

在 2012年7月20日星期五UTC+8下午5时41分20秒,alex bian写道:

王鸿源

unread,
Jul 21, 2012, 7:06:49 AM7/21/12
to se...@googlegroups.com

seajs.use,或require

Frank Wang

unread,
Jul 24, 2012, 10:01:39 PM7/24/12
to se...@googlegroups.com
 最新的 1.3-dev 修正了下状态变化,如果是普通文件,无论调用前还是调用后, 状态码 status 都是 2,表示 fetched,无任何其他处理。

比如 a.js 和 b.js 如果是普通文件:

a.js:
----------
A = 'a'
----------

b.js:
----------
B = 'b'
----------

那么在 seajs 里可以:

seajs.use(['./a', './b'], function() {
    alert(A)
    alert(B)
})

需要自己通过全局变量 A 和 B 去拿到 a.js 和 b.js 的接口,不能通过参数去拿。

类似的,也可以在模块里调用:

main.js:
----------------
define(function(require, exports) {
  require('./a')
  require('./b')

   alert(A)
   alert(B)
})
---------------


作为文件加载器时,seajs 没有处理普通文件的依赖关系,这一块很纠结要不要在 seajs 里面提供类似
LABjs 的等待功能,比如:

seajs.use('./a').wait().use('./b', function() { .... })

通过 wait 来保障 a.js 始终会在 b.js 之前加载。

大家有什么建议吗?


On Friday, July 20, 2012 11:10:57 PM UTC+8, 王鸿源honingwon wrote:
确实,如果require的是未封装模块,此时的seajs降级为像LABjs的文件加载器。
 
如果所有的文件都是未封装的模块,用LABjs好了。
 
另外,seajs调用未封装的模块,像玉伯说的,seajs会注册模块,状态码为1,module.exports 为 undefined。
 
还有个有意思的现象,如果seajs再去调用这个模块,状态码变成4,module.exports 为空对象。
 
1.2的seajs版本。
 
2012-07-20

honingwon

发件人:Frank Wang
发送时间:2012-07-20 22:59
主题:Re: seajs引入基础javascript库的做法
收件人:"seajs"<seajs@googlegroups.com>

honingwon

unread,
Jul 24, 2012, 10:36:52 PM7/24/12
to seajs
功能的丰富,我觉得关键要看SeaJS的定位以及SeaJS社区的呼声。
 
SeaJS专一的模块加载功能、简单易用的API以及轻量级的体积,是我个人最赞赏的。
 
我觉得,如果一个模块系统中,有着大量的普通文件,那它就不再是一个模块系统,而且模块化的优势在这个系统中就体现不出来了。那么使用SeaJS就是大材小用,还不如用5.36K的LABjs。
 
如果一个模块系统中的普通文件的数量很少,而且有依赖关系,那么,用户只要做一点点的牺牲,把那些少量的普通文件模块化。只要简单地用define包装一下,并用require写下依赖关系。这只需要几秒的时间。
 
2012-07-25

honingwon

发件人:Frank Wang
发送时间:2012-07-25 10:01
主题:Re: Re: seajs引入基础javascript库的做法
收件人:"seajs"<se...@googlegroups.com>
抄送:
 

alex bian

unread,
Jul 24, 2012, 11:02:40 PM7/24/12
to se...@googlegroups.com
依赖这一块我觉得可以让用户自己去控制,况且感觉在use的回调里面有点蹩脚。

还有回调的返回值怎么传递?它里面的this是指向谁?

在 2012年7月25日星期三UTC+8上午10时01分39秒,Frank Wang写道:

honingwon

unread,
Jul 24, 2012, 11:11:58 PM7/24/12
to seajs
对于追求团队协作效率以及性能优化的开发团队来说,SeaJS的确是一个很棒的选择。SeaJS users证明了这一点。
 
其实,我希望他们能够在享受开源的SeaJS的同时,多为SeaJS社区贡献一些,比如一些模块或者使用经验。
 
alipay有一个非常优秀的基于CMD的开源库,或者叫模块系统,arale2.0,我个人非常喜欢也非常期待。
 
 
2012-07-25

honingwon

发件人:Frank Wang
发送时间:2012-07-25 10:01
主题:Re: Re: seajs引入基础javascript库的做法
收件人:"seajs"<se...@googlegroups.com>
抄送:
 

honingwon

unread,
Jul 25, 2012, 12:26:41 AM7/25/12
to seajs
如果一个模块系统中有少量的普通文件,我想,应该用包容的态度来对待他们,不应该用怪异的眼光来看他们。如果这些普通文件职责单一,也应该把他们当做模块成员。在基于SeaJS的模块系统里,我觉得,把他们描述成“非CMD模块”更合适。对于“非CMD模块”,我建议使用前做一些简单处理。有两种处理方式。
 
第一种方式,使用define注册模块,使用require表明模块依赖。尽量不要污染全局变量,使用module.exports导出模块值。
 
第二种方式,如果不想使用deifine和require来封装模块,那么做一些完善这些非CMD模块模块信息的工作。
 
SeaJS在加载普通的文件之前,会假想它是一个CMD模块,生成一些模块信息并保存起来。加载完毕之后,其实,我们还是可以去调用模块的接口SeaJS不会报错,也不会给予警告(其实,我建议在debug模式下,给予一些警告),不过我们得到的,肯定是空的东西。但是,我觉得,这些不完整模块信息对我们来说还是有用的:我们可以修改它,使模块信息变得完整。这样,我们就可以
在别的模块中正常地调用这个模块的接口。SeaJS提供了modify方法来实现这样的功能。
 
具体的实现细节,玉伯在这个帖子里已经提到了https://github.com/seajs/seajs/issues/286
 
对于在文件加载执行之后引入的全局变量,我觉得,在赋给module.exports,之后可以删除掉,以保证全局变量不被污染。
 
其实你现在得到的模块,模块信息已经比较完整了。
 
还有,使用这种方式,没办法处理模块依赖。
 
做了这些处理之后,我觉得这个SeaJS模块世界会变得更美好:
 
1、代码不会变得怪异。你可以像调用一般模块一样来调用“非CMD模块”。
2、代码的可维护性增强了。当你的一个“非CMD模块”被换成相应的功能一样的标准CMD模块时,不需要改动所有依赖这个模块的代码。
 
最后,对已经使用SeaJS并且希望一直使用下去而不是随便玩玩的用户,我想说:
 
向前端模块化开发靠拢,近一点,再近一点。
 
 
2012-07-25

honingwon

发件人:alex bian
发送时间:2012-07-25 11:02
主题:Re: Re: seajs引入基础javascript库的做法
收件人:"seajs"<se...@googlegroups.com>
抄送:
 

Frank Wang

unread,
Jul 25, 2012, 4:29:01 AM7/25/12
to se...@googlegroups.com
很同意 honingwon 的观点

对于非 CMD 模块的文件,除了 seajs.modify, 还可以用代理模块的方式来包装:

比如 a.js 是一个非CMD模块
我们可以增加一个代理模块:

a.js:
-----------
A = { name: 'a' }
-----------

a-m.js:
---------
define(function(require, exports, module) {
   require('./a')
   module.exports = A
})
---------


然后其他地方就可以用 require('./a-m') 来调用 a 文件了。



2012/7/25 honingwon <honi...@gmail.com>

乐小明

unread,
Mar 2, 2013, 3:33:01 AM3/2/13
to se...@googlegroups.com

使用代理方式会影响效率吧?
另外,没看懂这段示例,能否再说明白点。

a.js
--------------
A = { name: 'a' }
-------------------
这段是啥意思,怎么进行命名的?

我在github上seajs issues中也没搜到代理模块方式。
在 2012年7月25日星期三UTC+8下午4时29分01秒,Frank Wang写道:
很同意 honingwon 的观点



2012/7/25 honingwon <honi...@gmail.com>
收件人:"seajs"<se...@googlegroups.com>
抄送:
 
依赖这一块我觉得可以让用户自己去控制,况且感觉在use的回调里面有点蹩脚。

收件人:"seajs"<se...@googlegroups.com>

乐小明

unread,
Mar 2, 2013, 3:35:43 AM3/2/13
to se...@googlegroups.com

使用代理方式会影响效率吧?
另外,没看懂这段示例,能否再说明白点。

a.js
--------------
A = { name: 'a' }
-------------------
这段是啥意思,怎么进行命名的?

我在github上seajs issues中也没搜到代理模块方式。
在 2012年7月25日星期三UTC+8下午4时29分01秒,Frank Wang写道:
很同意 honingwon 的观点



2012/7/25 honingwon <honi...@gmail.com>
收件人:"seajs"<se...@googlegroups.com>
抄送:
 
依赖这一块我觉得可以让用户自己去控制,况且感觉在use的回调里面有点蹩脚。

收件人:"seajs"<se...@googlegroups.com>

Chris Chen

unread,
Mar 2, 2013, 4:04:42 AM3/2/13
to se...@googlegroups.com

这段只是普通的js,代理就是用define封装一下全局变量在其他地方的使用该代理模块就完全兼容CMD了

--
You received this message because you are subscribed to the Google Groups "seajs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to seajs+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Frank Wang

unread,
Mar 2, 2013, 9:59:03 AM3/2/13
to seajs
对,代理模式就是另写一个模块,比如对于 jquery-1.9.2.js ,可以再定义一个:

jquery.js,里面内容是

define('jquery', function(require) {
  require(''path/to/jquery-1.9.2.js'')

  return jQuery.noConflict()
})


然后其他模块中,加载 jquery.js 即可



2013/3/2 Chris Chen <me.ch...@gmail.com>
Reply all
Reply to author
Forward
0 new messages