没有模块化之前,我们是怎么开发的

刚刚从业那会,公司是没用模块化的,那代码是怎么组织的呢?首先有一个common.js,这里面放的是一些公用的东西,比如:用户的登录注册、工具类、经常用到的全局变量、还有一些常用的函数;还有一个head.js,这里面放的是一些网站头部的一些东西,比如显示用户头像、Hover菜单栏的效果等等;还有一个roombase.js,因为有不同的房间,不同房间之前还有一些公用的东西,这些公用的东西就会放到这里面;剩下的功能呢,就放到一个叫room.js,这里面放的是整个系统的全部业务逻辑,所有点击事件、Hover事件、弹窗、播放等等功能。于是,我们引用的时候,就会是这样

<script src="common.js"></script>
<script src="head.js"></script>
<script src="roombase.js"></script>
<script src="room.js"></script>

因为是逐层依赖,所以引用的顺序也是这样的。

这样的结构会出现哪些问题?

刚开始接手的时候,感觉不出问题,随着业务的开发,问题也就越来越明显了

  • 对于一个HTTP请求来讲,要经过很多步骤(域名解析、http的三次握手四次告别、远程服务器下载文件。。。)才能下载一个文件,这样文件越多,消耗的无关时间就越多,页面要等所有js文件加载、渲染完成,才能显示出来。这样文件越多,页面加载时间就越长。
  • 人来人往,并不是所有的人对整个系统的业务代码都熟悉,这样就出现一个问题,当某一个变量或者自己找不到时,就会自己实现一个,而且这些变量或者函数,都是全局的,这样时间长了以后,就是会出现很多莫名其妙的东西,而且所有的变量都绑在window上,导致window的变量越来越多
  • 因为是全局变量嘛,稍不留神,就有可能被覆盖的风险,比如:之前有一个变量叫isLogin,也不知道这个变量是谁起的,false表示已登录,true表示未登录,一直都这么用倒是也习惯了,新来一个同学,感觉非常不爽,就覆盖了,也命名个变量isLogintrue表示已登录,false表示未登录,结果可想而知。
  • 业务分层过于抽象。新来一个业务,我感觉应该放到roombase.js里面合适,他感觉放到room.js里面合适,别人可能感觉放到common.js里面合适,每个人理解不一样,放的位置也不一样,也没办法认定谁对谁错,反正最终都挂到window下面,都能访问。这玩意就像代码规范,单靠一个说明文档,靠自觉,永远也统一不了,必须得强制,比如现在就是ESLint
  • 代码越来越冗余。比如common.js里面有一个方法要满足一个业务,但是这个common.js10个页面都引入,你敢改吗?万一你改了,当前页面好使了,其他9个页面报错了,不但不记功,反而会被骂一顿。对于业务维护来说,风险小才是王道,那可咋办?当然是拷贝出来一份了,然后在新方法里面改。比如有一个checkLogin的方法,改了万一出问题怎么办,于是我拷贝一份,改个名,叫checkUserLogin,新业务调用这个方法,这样即保证新业务顺利上线,又能保持老业务正常运行。哈哈,是不是该为了机智点个赞呢。这样时间越来越长,相同的代码也越来越多,也就越冗余。
  • 不利于协作开发。平时开发的各项功能,90%都在room.js里面做,我们组有8个人,8个人同时修改一个js文件,用膝盖想想都知道有啥问题吧。

关于模块化的一点想法

对于模块化,我还是想说明一下,模块化重要的是思想,而不是实现。所以不管是requirejs还是seajs都是对模块化思想的实现,说白了就是模块化实现的工具,对于工具来说,能满足你的需求,就是好工具,没有太大的必要进行纠结到底选哪个。两者使用范围都非常广泛,技术上都比较成熟,肯定都能很好的满足你需求。我们选用的是requirejs,关于requirejs的语法,请参见官网。

模块化的一些好处

模块化之后,解决了上面提到的这些问题

  • 更加细分,login相关可以拆成一个模块,user相关可以拆成一个模块,websocket也可以拆成一个模块,用的时候['user', 'login', 'websocket']这样更灵活,耦合性越低
  • 多人开发多业务,效率更高
  • 作用域确定,不会再出现相互覆盖的情况
  • 使用gulp可以把所有文件进行合并,这样页面只要引用一个js文件即可,加载时间会变短

好像还有问题

使用模块化之后,还有一个比较难解决的问题:js文件中有大量的DOM操作。因为我们用jQuery,不可避免的会出现这样的问题,这种情况有一个比较专业的名词叫:数据和显示不分离。文件里面会处处的出现这样的代码:$('.user').eq(0).append('<span class="logo"></span>')。这样写没问题,但对于我们经常改版的网站来说,简直了。一次改版,80%以上的代码要重写你怕不怕,而且还非常担心哪块漏改了。而且这样的模块,复用基本是零。你想啊,一块功能,HTML里面有一部分,js里面拼接一部分,css样式在别外一个文件里面,想想看,是不是复用的难度非常大?

模块化解决方案

其实比较好的解决上面的问题,就是使用vue的单模板文件的形式,一个.vue文件,里面即有js、html、css,而且数据和显示是分离的,能直接复用,这样才是一个真正的模块。具体怎么使用,请参见Vue的官网,介绍详细;生产环境的webpack+vue的配置,请用力点击我


会说话的鱼
2.9k 声望219 粉丝