前不久有个网友问我在前端使用requireJs和seajs的问题,我当时问他你们公司以前有没有自己编写的javascript库,或者javascript框架,他的回答是什么都没有,他只是听说像requirejs和seajs是新东西新技术,很有价值所以想用它。
这位网友的问题引起了我对javascript模块加载技术的思考,上篇文章我给出了自己写的一个javascript库的基本结构,其实写这篇文章的一个起因就是因为我想使用requirejs或者seajs这样的技术来重新设计我写javascript库的基本模型,当我深入了解这个技术后,我发现使用模块加载系统来解决把javascript库里通用代码和业务代码解耦的问题,是不正确的,模块加载系统的作用范围是解决不同javascript库之间的依赖问题,而不是帮助你去如何开发一个javascript库。
那么什么是javascript的模块加载系统呢?
模块系统主要为了解决不同javascript库里操作对象的命名冲突问题以及不同javascript库之间依赖的问题,模块加载系统是针对大型web前端应用或者说是巨型的web前端应用。
一般巨型的web前端应用页面里,该页面的功能非常丰富,业务非常庞杂,而且随着时间推移,页面的功能经常会发生变迁,所以导致前端开发人员经常要开发出针对新功能的功能模块,但是实际业务里各个功能模块之间的功能还有可能相互渗透,相互依赖的,关系错综复杂,当页面复杂后,各个前端库之间的关系就出现很难管理和控制的问题,这个时候模块加载系统才会派上用场。
对于大多数程序员而言,能独立承担这么大web前端应用的机会并不是太多,而开发中小型web前端应用的机会会多的多,例如企业级的web项目,这样的项目使用到的javascript库的种类很少,各个库的依赖关系很好控制,是没有必要引入什么模块管理系统的必要,就算很多中小型互联网公司的网页,估计也不会比企业级web应用前端那么复杂,所以它的模块之间或者说javascript库之间的关系很好管理的。其实像上面这些中小应用都是针对某些或某一个具体场景进行的,因此我个人觉得面对这样的web前端项目我们最后能自己形成一个独立的javascript库,这个库的特点应该和jQuery这种类型的库类似:一个主库加上若干个插件库的模式,主库的目的是解决通用性的问题,它应该是可以进行复用和迁移的,而插件库的目的往往和业务代码相关的,不过为了区别主库和插件库的作用域问题,所以我在库里加上了命名空间的功能。
Javascript模块加载技术和hadoop的技术有些相同点,那就是它们都是针对超大型系统的技术,它们只有在一定条件下才能发挥它们的作用,所以这些技术都是从大型互联网公司推出出来,因为大型互联网公司随着应用变大变复杂后必须要去解决的问题,当你系统还是处于起步阶段,这些技术的运用往往要谨慎,我们应该找出最简单最有效的方法解决我们实际问题,如果你觉得这个系统以后会越来越大,那么你应该保留以后使用这些技术的接口,如果使用太早了,很有可能当系统规模扩大后,你重构代码的代价会更高。
对于模块加载系统,它最适合的场景是解决大型web前端应用模块之间的解耦的问题,如果我们只要新写一个javascript文件就马上使用模块加载技术,这个不是有点滥用技术的嫌疑了,我们运用某个技术之前不应该只是考虑它怎么用,如何用,应该还要想想使用它有没有价值的问题。
最后我想说的是,我觉得中小型web前端应用到了生产部署,因为javascript并非最复杂,所以所有外部javascript文件都打包成一个javascript外部文件最好,这样的好处就是减少了http请求个数,使用模块加载技术会让你打包文件操作很麻烦,甚至无法做到(像requirejs和seajs的模块都是以文件为单位的,每个模块就是一个独立文件),这和解决减少http目的是相悖的。