没有模块化之前,我们是怎么开发的
刚刚从业那会,公司是没用模块化的,那代码是怎么组织的呢?首先有一个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
表示未登录,一直都这么用倒是也习惯了,新来一个同学,感觉非常不爽,就覆盖了,也命名个变量isLogin
,true
表示已登录,false
表示未登录,结果可想而知。 - 业务分层过于抽象。新来一个业务,我感觉应该放到
roombase.js
里面合适,他感觉放到room.js
里面合适,别人可能感觉放到common.js
里面合适,每个人理解不一样,放的位置也不一样,也没办法认定谁对谁错,反正最终都挂到window
下面,都能访问。这玩意就像代码规范,单靠一个说明文档,靠自觉,永远也统一不了,必须得强制,比如现在就是ESLint
。 - 代码越来越冗余。比如
common.js
里面有一个方法要满足一个业务,但是这个common.js
10个页面都引入,你敢改吗?万一你改了,当前页面好使了,其他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
的配置,请用力点击我
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。