谁能介绍下web前端工程化
谁能介绍下web前端工程化?
作者:赵雨森
链接:https://www.zhihu.com/question/24558375/answer/139920107
来源:知乎
目前来说,Web业务日益复杂化和多元化,前端开发已经由以WebPage模式为主转变为以WebApp模式为主了。现在随便找个前端项目,都已经不是过去的拼个页面+搞几个jQuery插件就能完成的了。工程复杂了就会产生许多问题,比如:如何进行高效的多人协作?如何保证项目的可维护性?如何提高项目的开发质量?…
前端工程化是前端架构中重要的一环,就是为了解决上述各种效率方面的问题的。而前端工程本质上是软件工程的一种,因此我们应该从软件工程的角度来研究前端工程。
那么前端工程化需要考虑哪些因素?
我认为前端工程化主要应该从模块化
、组件化
、规范化
、自动化
四个方面来思考,下面一一展开。
模块化
简单来说,模块化就是将一个大文件拆分成相互依赖的小文件,再进行统一的拼装和加载。只有这样,才有多人协作的可能。
JS的模块化
在ES6之前,JavaScript一直没有模块系统,这对开发大型复杂的前端工程造成了巨大的障碍。对此社区制定了一些模块加载方案,如CommonJS、AMD和CMD等,某些框架也会有自己模块系统,比如Angular1.x。
现在ES6已经在语言层面上规定了模块系统,完全可以取代现有的CommonJS和AMD规范,而且使用起来相当简洁,并且有静态加载的特性。
规范确定了,然后就是模块的打包和加载问题:
- 用Webpack+Babel将所有模块打包成一个文件同步加载;
- 用SystemJS+Babel分模块异步加载;
- 将两者结合在一起。
CSS的模块化
虽然SASS、LESS、Stylus等预处理器实现了CSS的文件拆分,但没有解决CSS模块化的一个重要问题:选择器的全局污染问题。
按道理,一个模块化的文件应该要隐藏内部作用域,只暴露少量接口给使用者。而按照目前预处理器的方式,导入一个CSS模块后,已存在的样式有被覆盖的风险。虽然重写样式是CSS的一个优势,但这并不利于多人协作。
为了避免全局选择器的冲突,各厂都制定了自己的CSS命名风格:
BEM风格;
Bootstrap风格;
Semantic UI风格;
我们公司的NEC风格;
…
但这毕竟是弱约束。选择器随着项目的增长变得越多越复杂,然后项目组里再来个新人带入自己的风格,就更加混乱了。
所以我很赞同这句话:
与其费尽心思地告诉别人要遵守某种规则,以规避某种痛苦,倒不如从工具层面就消灭这种痛苦。
从工具层面,社区又创造出Shadow DOM、CSS in JS和CSS Modules三种解决方案。
Shadow DOM是WebComponents的标准。它能解决全局污染问题,但目前很多浏览器不兼容,对我们来说还很久远;
CSS in JS是彻底抛弃CSS,使用JS或JSON来写样式。这种方法很激进,不能利用现有的CSS技术,而且处理伪类等问题比较困难;
CSS Modules仍然使用CSS,只是让JS来管理依赖。它能够最大化地结合CSS生态和JS模块化能力,目前来看是最好的解决方案。Vue的scoped style也属于这一种。
组件化
首先,组件化≠模块化。好多人对这两个概念有些混淆。
模块化只是在语言层面上,对代码的拆分;而组件化是基于模块化,在设计层面上,对UI(用户界面)的拆分。
从UI拆分下来的每个包含模板(HTML)+样式(CSS)+逻辑(JS)功能完备的结构单元,我们称之为组件。
其实,组件化更重要的是一种分治思想。
Keep Simple. Everything can be a component.
这句话就是说页面上所有的东西都是组件。页面是个大型组件,可以拆成若干个中型组件,然后中型组件还可以再拆,拆成若干个小型组件,小型组件也可以再拆,直到拆成DOM元素为止。DOM元素可以看成是浏览器自身的组件,作为组件的基本单元。
传统前端框架/类库的思想是先组织DOM,然后把某些可复用的逻辑封装成组件来操作DOM,是DOM优先;而组件化框架/类库的思想是先来构思组件,然后用DOM这种基本单元结合相应逻辑来实现组件,是组件优先。这是两者本质的区别。
其次,组件化实际上是一种按照模板(HTML)+样式(CSS)+逻辑(JS)三位一体的形式对面向对象的进一步抽象。
所以我们除了封装组件本身,还要合理处理组件之间的关系,比如(逻辑)继承、(样式)扩展、(模板)嵌套和包含等,这些关系都可以归为依赖。
其实组件化不是什么新鲜的东西,以前的客户端框架,像WinForm、WPF、Android等,它们从诞生的那天起就是组件化的。而前端领域发展曲折,是从展示页面为主的WebPage模式走过来的,近两年才从客户端框架经验中引入了组件化思想。其实我们很多前端工程化的问题都可以从客户端那里寻求解决方案。
目前市面上的组件化框架很多,主要的有Vue、React、Angular 2、我们公司 @郑海波 的Regular、Avalon等。你感兴趣可以都研究一下,选择一套中意的。其实Vue文档中的对比其他框架一文已经讲得很详细了。
规范化
模块化和组件化确定了开发模型,而这些东西的实现就需要规范去落实。
规范化其实是工程化中很重要的一个部分,项目初期规范制定的好坏会直接影响到后期的开发质量。
我能想到的有以下一些内容:
目录结构的制定
编码规范
前后端接口规范
文档规范
组件管理
Git分支管理
Commit描述规范
定期CodeReview
视觉图标规范
…
其中编码规范最好采取ESLint和StyleLint等强制措施,因为人是靠不住的,比如可以Lint通不过不能提交代码等。
前后端接口管理可以了解一下我们公司出的NEI - 接口管理平台。
自动化
作了这么多年程序猿的我,一直秉持的一个理念是:
任何简单机械的重复劳动都应该让机器去完成。
所以我也认为,前端工程化的很多脏活累活都应该交给自动化工具来完成。
图标合并
不要再用PS拼雪碧图了,有Gulp+SpriteSmith;
不要再用Icomoon了,这仍然是半自动的,有FontCustom。
持续集成
自动化构建
自动化部署
自动化测试
前端自动化测试能够提高代码质量、减少人肉测试等,这些优点是不言而喻的。
市面上前端测试框架有很多,选择哪个都不会有太大问题,我们用的是:Karma
+ Mocha
+ Chai
构建工具
最后就是你的团队可能不只一个项目,如果每个项目都搭一套gulp+webpack+babel+…,维护成本比较高,而且不能保证统一性。
因此基于Gulp实现一套独立于项目的构建工具是最好的解决方案。
可以参考一下我们网易蜂巢的构建工具rainfore/pursuit-cli,开发者只要会用pursuit dev和pursuit online两句命令就行。
下图是我们的构建工具任务流。
最后
下面是我前段时间写的一篇文章《网易蜂巢的工业化前端架构》,用微信扫一扫。以网易蜂巢下的五个单页系统(SPA)为例,详细讲述了我们组前端工程化的一些细节。