随着前端代码的业务逻辑越来越多,模块化成为了必然的趋势,要是具体说道模块化的意义,我觉得有以下几点:
- 提高代码的复用率。
- 提高可维护性。
- 解决团队开放中的全局变量污染及命名冲突。
- 依赖关系的管理。
1.JS模块化历程
1.最初的模块化手段。
随着前端代码量的增多,开发人员在进行前端代码开发时很多问题也就跟着暴露了出来:
- 全局代码的灾难
- 函数命名冲突
- 依赖关系不好管理
于是,为了缓解上述的问题,开发人员想出来了一些应对办法
item1:
var page=function(){
...
return{
add:function(){
},
say:function(){
...
}
}
}()
为了减少全局变量的污染,使用自执行函数来包装代码,函数内部的变量相对于全局是隐藏的,达到了封装的目的。但是仍然存在page之类的全局变量,并且随着模块的增多,全局变量还是会越来越多。
item2:
为了缓解全局变量造成的命名冲突,有人就想到了利用多级命名空间来进行管理,就像下面酱紫:
app.model.add=xx;
app.model2.page2.save=xxx;
这样进行处理,在调用时无论是从性能上面还是从可读性上,都是相当的恶心。
item3:
(function($){
$.say=function(){..};
})(window)
利用这种自执行匿名函数的形式,将依赖模块作为参数传入,最后再将自身模块暴露给参数,这样JQuery形式的封装方法虽然增加了令化性,但是依赖模块还是要外部提供,还是会增加全局变量。
2.commonJS
随着nodejs的诞生,commenJS规范走进了我们的视野,作为第一个模块化的规范,一出世便受到了广泛的推广。该规范主要对模块化进行了以下的约定:
- 每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。
- 每个模块内部,都有一个module对象,代表当前模块。
- 定义全局函数require,通过传入模块标识来引入其他模块,执行的结果即为别的模块暴漏出来的API
- 模块通过变量exports来向往暴漏API,exports只能是一个对象,暴漏的API须作为此对象的属性。
但由于CommonJS规范起源于服务端,所以造成他对于模块的加载采用同步的方式,因为是直接从磁盘进行读取文件,其中的消耗时间也可忽略。但是,对于浏览器端来说,一个文件的加载意味着一个HTTP请求,这期间的时间消耗是我们不可忽略的。其二,不同于服务器端,在浏览器端,没有function包裹的代码就会暴露在全局中。综上导致commonjs规范无法直接用于客户端。
3.AMD规范
于是,为了适应浏览器端的特性,AMD规范出现。AMD的思想正如其名,异步加载所需的模块,然后在回调函数中执行主逻辑。它是requirejs在推广过程中的模块化产出。
AMD推崇的是依赖前置,被依赖的模块需要被提前罗列出来并会被提前下载并执行,后来requirejs做了改进,可以不用罗列依赖模块,允许在回调函数中就近使用require引入并下载执行模块。
从模块化机制上,我们也看出了requirejs几点的不足:
- 倘若采用将依赖提前引入的办法引入模块,每个模块在被提前加载后都会在执行一遍,这样的机制有时候就会显得无意义且消耗性能。
- 倘若在回调函数中在使用前用require引入模块,实时的下载执行模块同样也会影响用户的体验。
4.CMD
CMD是seajs在推广过程中的规范化产出,seajs是另一种前端模块化工具,他的出现缓解了requirejs的几个痛点。
CMD推崇依赖就近,定义时无需罗列依赖数组,在需要用到时用require引入执行就好。他的机制时这样的,它会调用factory函数的toString方法,对函数的内容进行正则匹配,通过匹配到的require语句来分析依赖,进行依赖的提前下载,不会提前执行。
并且,CMD也支持懒加载,require.async可以在需要用到的时候再下载模块。
5.webpack
webpack是一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX)、coffee、样式(含less/sass)、图片等都作为模块来使用和处理。
其优势主要可以归类为如下几个:
webpack 是以 commonJS 的形式来书写脚本的,但对 AMD/CMD 的支持也很全面,方便旧项目进行代码迁移。
能被模块化的不仅仅是 JS 了。Loader加载器可以将其他资源整合到JS文件中,通过这种方式,可以将所有的源文件形成一个模块。
开发便捷,能替代部分 grunt/gulp 的工作,比如打包、压缩混淆、图片转base64等。
扩展性强,插件机制完善。有着各种健全的加载器(loader),可以引入各种需要编译的模块。
有同步和异步两种不同的加载方式
相比于requirejs/seajs,webpack显然更加灵活和强大,只要正确配置后,无论是在处理依赖关系,同步异步,还是优化方面,webpack都会十分聪明的帮你处理好。