Teambition是一家追求卓越技术的公司,咱们工程师都很Geek,咱们使用了不少新潮的,开源的技术。同时咱们也贡献了不少开源的项目。咱们但愿可以把一些技术经验分享给你们。因而有了这个「创做随笔」。废话休说,「创做随笔」第一弹,来自咱们的前端工程师寸志,谈一谈他在前端模块化开发方面的一些感想。前端
在模块化方面,Node.js就显得游刃有余。node
做为用户,咱们把代码放到一个个JavaScript文件中,而后Node.js就有一套规则帮咱们把这些代码组织起来,Node.js还有包的概 念,因而咱们就可使用npm将代码放到一个个包中,放到这里那里的node_modules中使用。很方便不是?感谢Node.js。git
可在浏览器端,模块化这事就没那么简单了。github
前端的模块
前端的一个模块包含不少东西,JavaScript、CSS、图片字体等等。甚至,可能根据业务须要,还包含国际化的文件。一个模块若是包含以上这些东西,复杂度就上了几个数量级。chrome
怎么复杂了?和高大上的iOS开发比起来,人家有SDK,代码随便往项目里扔,图片扔,国际化有成熟的解决方案,最后构建一下一个可运行的应用就出来了。npm
前端缺少SDK,没有成熟统一的开发方案,集成方案,前端模块化之路很崎岖。开发时,咱们须要一种方式来组织,加载代码,发布时,咱们还须要另一种方式将代码、资源合并到一块儿发布。浏览器
眼前的现状
TJ 给出了本身解决方案——Component。能够份文件开发,而后再把JavaScript、CSS和模板文件合并到一块儿。我只能说,理想很丰满,现实很骨感,Component没法适应各类奇葩的应用场景。缓存
或者咱们自由一点——服务器
依赖的第三方模块,咱们有Bower,好爽,运行个命令,依赖就安装好了。前端工程师
可是Bower不是银弹,Bower只解决了模块依赖,安装依赖的问题。Bower中的模块没有任何标准和规则,有的只有JavaScript,有 的支持AMD,有的可能只有CSS。文件结构,入口文件彻底不同。并非使用Bower安装的模块咱们就可使用一样的方式使用任何一个模块,使用某种 工具将这些模块打包发布!
AMD做为事实上的前端JavaScript模块化标准,或能够出来解救咱们。不少Bower模块都是支持AMD规范的。并且AMD还提供了打包工具,总算有点解脱了。好景不长……
每一个模块中的HTML怎么办,若是咱们使用的框架是Backbone,注定咱们要将HTML模板转换成JavaScript模块,或者使用模块加载 器的插件来实现。若是咱们使用AngularJS,那却是能够交由AngularJS。发布时Backbone中的模块使用AMD打 包,AngularJS可使用Grunt内联到页面中。
HTML模块也没有固定的模式,没有固定的SDK来解脱咱们。咱们只能组合现有的工具!
CSS就更不用说了,分开写,使用LESS、SASS来组织?再一次没有固定的模式没有SDK。
还有图片呢,字体呢?
拼凑的方案
前端若是想作模块化开发,首先须要针对每一种资源(JavaScript、CSS、模板等)寻找一种模块与集成方案,而后须要根据状况的不一样选用不一样的工具框架拼凑出来。
JavaScript
目前比较拿的出手的,也就是JavaScript的模块化,好比AMD或者CMD等等,分别可使用RequireJS和SeaJS。
去年在研究基于Backbone的框架Marionette时,想与Sea.js结合使用。如今来看这种组合是彻底没有必要的。 Marionette提供了模块化的组织方案,反而生拉硬扯在一块儿,冲突得很难受。其实把JavaScript文件一列放在HTML中也没什么问题。
究竟使用什么来实现JavaScript,每每与选择的JavaScript框架有关,选Backbone能够AMD,也能够CMD。选AngularJS直接引用就行。
CSS
CSS模块化应该是两方面的问题——
一是模块必须有一套基础样式。与JavaScript相比,CSS冲突简直是屡见不鲜,Shadow DOM还没成熟,原生的CSS样式隔离还在路上。因此必须有一套基础样式来规定这一套模块化组件的样式。咱们能够选Bootstrap,若是闲它过重,也能够本身写。
其次,每一个组件必须有命名空间,避免组件间样式冲突。若是选择使用LESS、SASS等,那就比较好办,它们的缩进语法避免写不少重复的CSS代码。
HTML模板
若是使用AngularJS,那AngularJS已经帮您解决了模板模块化的问题,AngularJS能够根据模块代码中的引用加载对应的 HTML。若是使用Backbone,能够选择各类各样的模板引擎,Mustache?不过比起AngularJS就低端些,咱们必须本身处理模板文件, 要么经过模块加载器经过XHR请求,而后动态编译;或者将Mustache编译成JS,在当作模块加载。
图片、字体?
放在使用他们的模块中,该怎么引用就怎么引用。
国际化文件?这些就很少说了,总之,每种文件须要选定一种开发的组织方式。
模块分发
模块采用统一的模式来开发以后,只需选定一种包的分发方式就好了——Bower。npm不适合这样的场景,npm的版本管理太过细致了。若是同一个项目中容许出现同一模块的不一样版本,事情就作的太过复杂了。
发布上线
发布上线必须一个以终为始的过程。若是你不追求网站或者应用的速度,那就把那些开发文件直接丢到生产服务器上去吧。别说,我还真见过这样的商用的网站。
若是讲究一些方案,资源合并成数个文件,代码线上组合和运行方式彻底能够与本地开发不同。只须要功能在就行。
JavaScript代码打成一个文件,或者两个?都行。若是使用RequireJS,那RequireJS提供了打包的工具,打包成几个文件,什么粒度,都行。若是是Sea.js也有对应的工具。就算文件都是一个一个列出来,咱们也老是能够打出来你想要的文件。
CSS等等其余资源都是如此,就算开发时各自不一样的结构模式,打包时都是能够打的。
至于上线CDN,版本号缓存什么的并不在本文的讨论范围以内。
总结
前端模块没有什么特效药。惟一要遵照的原则就是,比起Node.js来说,每种资源必需要有一种本身的开发和上线组织方式(Node.js开发和上线都是一致的),开发和上线彻底能够是两种方式,大可没必要人云亦云,只要适合能够随意组合;CSS在CSS Scoped Style正式使用以前,应该有一套基础样式和沙盒(模块样式命名空间)。