代码改变世界

浅谈前端模块化

2016-10-20 14:44  紫日残月  阅读(347)  评论(0编辑  收藏  举报

 

引言:

前段时间在做项目的模块化打包以及懒加载,因为新入职接收的是一个比较成熟的项目,在整理工作中发现代码质量参差不齐,给模块化打包挖了许多坑,所以今天想着来整理下在工作踩到的坑,以便在以后的工作避免再次入坑.

问题:

我们都知道,在ES6之前前端是没有模块化的概念的,所有的前端脚本在加载后浏览器自动解析执行,这样会引发一个很恶心的问题-变量覆盖.也就是说所有的顶级变量都会挂在window对象下,那么一个很尴尬的问题就是后引入的文件中的同名变量会覆盖前面引入的变量,这个问题还极其不好调试;再一个就是前端开发的规模越来越大,js也由原来的页面动态辅助逐渐发展到能够独挡一面,这就给前端工作提出了新的挑战,我们要怎么合理的搭建前端框架,才能使代码不至于随着项目的发展臃肿,怎样合理规划,才能使得我们的代码优雅?

我想每个前端人员都在想,要是js能像后端类似java的语言一样有个明确的命名空间和import该多好.

解决方案:

我们都知道ES6有了module和import,但现在ES6规范还未大规模铺开,所以我们还是需要一些其它方法来实现前端的模块化(终于说到正文了…),这里要说的就是前端大名鼎鼎的AMD(Asynchronous Module Definition)和CMD(Common Module Definition)规范,分别由RequireJS 和Sea.js推进,这里我们不讨论二者的差异有缺,直说它的概念.

本质上来讲两种规范都是在做模块定义(废话),一般情况下,它把一个脚本文件抽象成一个独立的模块,对各个脚本文件做了一层简单的封装,使得各个模块通过对外暴露的”接口”完成相互之间的调用,而内部的实现在完全隐藏起来,虽然本质上也是把一个文件内的所有对象挂在一个顶级变量下,但由这些规范来为我们指定顶级变量名(也可以自定义,但是不建议这么做).模块之间的相互依赖实现了一种类似于”依赖注入”的方式,从而实现了前端的命名空间和”import”.

当然AMD和CMD的好处不只是上面提到的这些,比如他们都可以实现模块(文件)的懒加载,功能划分更加明确,体现了单一职责原则.降低耦合度等等,但是最主要的思想大概就是这些了.

作为这两个规范的标准实现者,RequireJs和Sea.js也基本是目前比较主流的前端模块化工具了,虽然有类似于AngularJs这样的框架做了一部分功能的实现,但是二者仍然是目前市场是主流的模块化工具.

 

怎么避免入坑:

说一千道一万,最终还是要落地,我们可以从以下几方面入手来实践前端的模块化:

  1. 明确需求;

具体来说就是要知道我们要做什么,要实现什么需求.任何框架或者技术都不是万能的,都有其擅长的地方和不足的地方,我们应该在重发了解需求的情况去选取适合自己项目的框架

  1. 职责分明/单一职责;

一般来说,一个模块(脚本文件)应该有明确的职责的,并且最好是单一的职责,这就需要我们在开发过程中合理划分需求和业务,使得每个模块/脚本都只负责做一件事,可以由多个模块组合完成一个大的业务,也可以调用其他模块暴露的”接口”完成公共的业务(需求)

  1. 懒加载

也叫按需加载,这个不解释

参考:

requirejs与seajs的异同 : https://github.com/seajs/seajs/issues/277

http://blog.chinaunix.net/uid-26672038-id-4112229.html

http://www.requirejs.cn/

http://seajs.org/docs/