前端模块化(一):模块化那些事儿
前端这几年发展太快了,我学习的速度都跟不上这速度了。在JavaScript发展初期就是为了实现简单的页面交互逻辑,随着前端的业务逻辑越复杂,代码也越来越多,JavaScript极其简单的代码组织规范不足以驾驭如此庞大规模的代码,于是一些问题就暴漏了出来。
1、命名冲突
我们平时做的项目的时候,都是会将一些通用的、底层的功能抽象出来,独立成一个函数以提高代码的可复用性,比如这样子
function floatAdd(a,b) { // …… };
完了之后,放在public.js里面,让其他有需要的同事调用就可以了。
不久之后,项目需求越来越多,新项目也一个接一个,换了个人来接手这个项目。新来的小哥开开心心的写完新需求功能提交给测试,测试过来说,这地方不对啊。小哥就懵逼了,我没动过这里啊,为啥就出错了呢?经过一番排查,原来小哥也定义了一个floatAdd函数,把上面的给覆盖了导致之前用过floatAdd函数的地方都出错了。此时小哥的内心是奔溃的,因为他很多文件很多地方都有用到他自己定义的floatAdd函数,得挨个文件挨个地方的改。
为了降低冲突的概览,大家开会讨论后,决定把自己写的公共函数封装在一个对象中,看下面的代码:
var myModule = {}; myModule.floatAdd = function(a,b){ // …… }
但是,公司这么多研发人员,总有那么一个会跟你的想法一样,起了一个跟你一样的对象名,所以命名空间依然有可能会冲突。那么为了继续降低冲突概率,只好拉长命名空间,比如
project.tools.moduleA.floatAdd = xxx;
Yahoo的YUI早期就是这么做的,调用的时候还得这么写:
project.tools.moduleA.floatAdd();
平时任务这么多,还得记住这么长的名字,记起来困难,一点也不优雅啊。所以这种方式并没有被很多人采用,YUI后来也不用这种方式了。
2、文件依赖
项目中有个日期操作的功能,刚刚好不久前在开源社区看到一个合适的插件,然后就运用到当前项目中了。使用的时候引入插件,如下
<script type="text/javascript" src="js/lib/date.js"></script> <script type="text/javascript" src="js/b.js"></script>
看着没毛病是吧,然而报错了。跑去看了一下文档,原来这个插件是基于jQuery的,而页面中没有引入jQuery.js ,赶紧在插件date之前引入jQuery,还特地在插件隔壁备注了是依赖jQuery的,如下
<script type="text/javascript" src="js/lib/jQuery.js"></script> <script type="text/javascript" src="js/lib/date.js"></script><!—依赖jQuery--> <script type="text/javascript" src="js/b.js"></script>
过了一段时间,取消了这个功能,得把这些没有必要的js文件去掉引用,直接把插件date跟依赖文件jQuery删了。刷新页面,报错了。一番排查,发现原来另一个小哥写的那部分功能有用到jQuery,赶紧又引用回来了。引用顺序不能错,也不能漏写某个,在多人开发的时候是很难协调。后期优化重构都得小心翼翼,生怕一个不小心改了不该改的,删了不该删的。相信不少人都有碰到过上面的这种事,改来改去心好累啊,心疼自己。
命名冲突和文件依赖,是前端开发过程中的两个经典问题。在这个无模块的时代,大牛们也尝试过了诸多方法,比如用函数来包装代码、java风格的命名空间,但并未解决根本问题。为了解决这些问题,js模块化被提上了日程,开始了一段艰辛的历程。
本文由一些历史问题,抛出Js模块化这个概念,接下的文章将逐步讲述js模块化的演进。