今天了解了一下RequireJS。之前很长一段时间都在纠结js的模块化问题,每个页面都写一大堆js代码,重复写着相似的逻辑。虽然对做的这些小应用来说算不上什么问题,但是人总得有点追求不是?而且随着使用了很多第三方组件,script标签长长的一列看着也非常的难受啊。

与js模块化加载这个话题相关的词汇有很多,在详细了解之前有所耳闻的有“AMD规范”、“CommonJS”、“SeaJS”。经过一番谷歌,大致了解了一下它们的意思:

  • AMD,全称“Asynchronous Module Definition”,就是所谓的异步模块定义,RequireJS就是遵守的就是AMD规范。
  • CommonJS,从介绍来看它是定义了一组普通应用程序常用的API,惊奇地发现NodJS居然就是CommonJS的一个实现。总之CommonJS貌似是一个很伟大的东西,并且看起来是致力于大致服务端js的生态环境。
  • SeaJS,阿里前端牛人玉伯(也叫射雕)搞出来的一个东西。尝试使用淘宝前端框架KISSY之后便加了QQ群,但是后来群公告便成了“SeaJS是未来!KISSY是个过客”。了解之下发现SeaJS也是用来实现js模块化加载的一个东西,他们将SeaJS对比的论调像极了RequireJS与CommonJS的对比:太大太复杂,并且试图兼顾服务端和浏览器端。

抱着对“国产”二字天然的戒心,我还是先去了解一下他们的对比对象RequireJS好了。Require只有一个核心js文件,推荐的用法是在页面中只引入这一个js文件,然后另设一个主入口文件,在入口文件中进行参数配置,加载其他依赖模块和干些别的事情。

require函数用来加载模块,首先是一个数组参数,元素是作为模块名的字符串;第二个参数是一个回调函数,当要加载的模块全部加载完成后执行这个回调函数,并且加载完成的模块会以在数组中的顺序作为参数传给这个回调函数。

相对应的define函数用来定义模块。参数与request相似,也是数组和回调函数。数组用来设置依赖模块,如果没有就可以省略。回调函数可以简单的返回一个作为模块的js对象,还可以是一个函数。不过return后面接一个对象或函数字面量怎么看都不大对劲。

对于没有按照规范定义的代码,可以用配置参数shim来处理。这点非常有用,毕竟多数第三方库都不是作为RequireJS模块编写的。另外shim这个词意思是“垫片”,联想到它的用途还是蛮形象的。

考虑一下用在项目中的实际可能。对于基于jquery的项目来说,jquery从1.7开始支持作为RequireJS模块加载,并且它们的功能都定义在jquery这个命名空间下,用shim参数配置一下它们和jquery的依赖性就可以了。自己写的那部分代码则可以按照规范定义成一系列模块,不过如何将以前随手写就的那种散沙一样的代码组织成模块可能是个不小的挑战。

另一个大量引入文件的重灾区是css。并且css还有个特点就是经常作为某个ui组件的一部分,如果能在加载ui组件的js代码时能将css一起引入就完美了。不过目前看来RequireJS还不支持直接引入css,官方问题列表中倒有一个专门的话题,原因是firefox中引入其他域名的css文件时有问题,导致检查文件何时加载完毕是不可靠的,为了避免替浏览器背黑锅所以RequireJS就干脆不提供这个功能。貌似SeaJS号称是支持加载css的,回头再去了解一下SeaJS,看看它是如何解决这个问题的。

总的来看RequireJS的基本理念还是蛮简洁的,当然要处理一些杂七杂八的细节问题会增加一些复杂度。不明白为啥有那么多别的规范并且争论不休。可能解决同样的问题不同人出于不同的考虑有会有不同的权衡,或者有时候干脆要解决的问题也是有差别的。

另外发现一个问题就是自己不知何时对“国产”二字产生的偏见。国外开源项目很多都是出于兴趣,为了证明自己可以做到某些事情;国内开源项目当然很多也是出于兴趣,但是老感觉动机不纯,虽然也是为了证明些什么,但很多是为了证明自己比别人强。国内不乏牛人,但开源社区相对不够活跃,很多项目都是一个人或少数几个人在做,毕竟精力有限。

拿之前项目中用到过的KISSY来说吧,吸引到我的是它官方网站清新活泼的风格,深入了解一下发现它规模小容易上手,同时提供的组件种类丰富风格统一。但真正用起来还是发现不少问题。由于大部分理念都是从YUI借鉴来的,虽然后来也提供了jquery风格的API,还是让熟悉jquery的用户各种不习惯。好容易有一个小项目我坚持边学边用稍微熟悉了一些,但让人伤心的是官方QQ群公告里居然说它只是个过客,只是过渡时期的产物的话,以后的项目中看来不用也罢。如此优秀的KISSY都有如此问题,国产开源项目的现状可窥一斑了。



blog comments powered by Disqus