Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

web前端工程化 #17

Open
Seasons123 opened this issue Apr 25, 2017 · 0 comments
Open

web前端工程化 #17

Seasons123 opened this issue Apr 25, 2017 · 0 comments

Comments

@Seasons123
Copy link
Owner

Seasons123 commented Apr 25, 2017

https://www.zhihu.com/question/24558375

目前来说,Web业务日益复杂化和多元化,前端开发已经由以WebPage模式为主转变为以WebApp模式为主了。现在随便找个前端项目,都已经不是过去的拼个页面+搞几个jQuery插件就能完成的了。工程复杂了就会产生许多问题,比如:如何进行高效的多人协作?如何保证项目的可维护性?如何提高项目的开发质量?...前端工程化是前端架构中重要的一环,就是为了解决上述各种效率方面的问题的。而前端工程本质上是软件工程的一种,因此我们应该从软件工程的角度来研究前端工程。那么前端工程化需要考虑哪些因素?我认为前端工程化主要应该从模块化、组件化、规范化、自动化四个方面来思考,下面一一展开。

模块化

简单来说,模块化就是将一个大文件拆分成相互依赖的小文件,再进行统一的拼装和加载。只有这样,才有多人协作的可能。

JS的模块化

在ES6之前,JavaScript一直没有模块系统,这对开发大型复杂的前端工程造成了巨大的障碍。对此社区制定了一些模块加载方案,如CommonJS、AMD和CMD等,某些框架也会有自己模块系统,比如Angular1.x。现在ES6已经在语言层面上规定了模块系统,完全可以取代现有的CommonJS和AMD规范,而且使用起来相当简洁,并且有静态加载的特性。
规范确定了,然后就是模块的打包和加载问题:

1. 用Webpack+Babel将所有模块打包成一个文件同步加载;
2. 用SystemJS+Babel分模块异步加载;3. 将两者结合在一起。

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也属于这一种。

组件化

(1)首先,组件化≠模块化。好多人对这两个概念有些混淆。
模块化只是在语言层面上,对代码的拆分;而组件化是基于模块化,在设计层面上,对UI(用户界面)的拆分。从UI拆分下来的每个包含模板(HTML)+样式(CSS)+逻辑(JS)功能完备的结构单元,我们称之为组件。其实,组件化更重要的是一种分治思想。Keep Simple. Everything can be a component.这句话就是说页面上所有的东西都是组件。页面是个大型组件,可以拆成若干个中型组件,然后中型组件还可以再拆,拆成若干个小型组件,小型组件也可以再拆,直到拆成DOM元素为止DOM元素可以看成是浏览器自身的组件,作为组件的基本单元。
传统前端框架/类库的思想是先组织DOM,然后把某些可复用的逻辑封装成组件来操作DOM,是DOM优先;而组件化框架/类库的思想是先来构思组件,然后用DOM这种基本单元结合相应逻辑来实现组件,是组件优先。这是两者本质的区别。
(2)其次,组件化实际上是一种按照模板(HTML)+样式(CSS)+逻辑(JS)三位一体的形式对面向对象的进一步抽象。所以我们除了封装组件本身,还要合理处理组件之间的关系,比如(逻辑)继承、(样式)扩展、(模板)嵌套和包含等,这些关系都可以归为依赖。
其实组件化不是什么新鲜的东西,以前的客户端框架,像WinForm、WPF、Android等,它们从诞生的那天起就是组件化的。而前端领域发展曲折,是从展示页面为主的WebPage模式走过来的,近两年才从客户端框架经验中引入了组件化思想。其实我们很多前端工程化的问题都可以从客户端那里寻求解决方案。目前市面上的组件化框架很多,主要的有Vue、React等。你感兴趣可以都研究一下,选择一套中意的。其实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两句命令就行。下图是我们的构建工具任务流。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant