前端工程化

前言

提到前端往往很多人的映像就是入门简单,HTML、CSS加一起一个星期基本上就能大概上手,JS难一点但也能很快写一些简单的小效果,在网上随便一搜索各种特效代码随意用,一个新手前端也能在很短的时间里写出炫酷的页面效果,然而入门简单并不意味着前端这碗饭很好吃,做惯了切图、布局、扣特效的前端新同学在向前发展的路上越来越觉得吃力,而没有任何编程思想和软件开发基础很多人对前端工程化、组件化、模块化、自动化这些“高大上”的词汇云里雾里。本文用最简单的语言介绍一下我对前端工程化、组件化、模块化、自动化的理解。

前端工程化

前端开发已经由以WebPage模式为主转变为以WebApp模式为主了。现在随便找个前端项目,都已经不是过去的拼个页面+搞几个jQuery插件就能完成的了。工程复杂了就会产生许多问题,比如:如何进行高效的多人协作?如何保证项目的可维护性?如何提高项目的开发质量?

所以前端工程化我认为就是:将前端项目当成一项系统工程进行分析、组织和构建从而达到项目结构清晰、分工明确、团队配合默契、开发效率提高的目的.

再用一句通俗的话来概括前端工程化:前端工程化就是用工程化的思维看待和开发自己的项目,利用工程化的思维去代替那些重复性、机械性、复杂化的工作,而不再是直接撸起袖子一个页面一个页面开写

模块化

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

举个简单的例子,我们要写一个实现A功能的JS代码,这个功能在项目其他位置也需要用到,那么我们就可以把这个功能看成一个模块采用一定的方式进行模块化编写,既能实现复用还可以分而治之,同理在写样式的时候,如果我们需要某种特殊的样式,会在很多地方应用,那么我们也可以采用一定的方式进行CSS的模块化,具体说来,JS模块化方案很多有AMD/CommonJS/UMD/ES6 Module等,CSS模块化开发大多是在less、sass、stylus等预处理器的import/mixin特性支持下实现的

js模块化

在ES6之前,JavaScript一直没有模块系统,这对开发大型复杂的前端工程造成了巨大的障碍。对此社区制定了一些模块加载方案,如CommonJS、AMD和CMD等,现在ES6已经在语言层面上规定了模块系统,完全可以取代现有的CommonJS和AMD规范,而且使用起来相当简洁,并且有静态加载的特性。

规范确定了,然后就是模块的打包和加载问题:
  • 用Webpack+Babel将所有模块打包成一个文件同步加载,也可以打成多个chunk异步加载;

  • 用SystemJS+Babel主要是分模块异步加载;

  • 用浏览器的<script type="module">加载

目前Webpack远比SystemJS流行。Safari已经支持用type="module"加载了。

css模块化

虽然SASS、LESS、Stylus等预处理器实现了CSS的文件拆分,但没有解决CSS模块化的一个重要问题:选择器的全局污染问题。

按道理,一个模块化的文件应该要隐藏内部作用域,只暴露少量接口给使用者。而按照目前预处理器的方式,导入一个CSS模块后,已存在的样式有被覆盖的风险。虽然重写样式是CSS的一个优势,但这并不利于多人协作。

为了避免全局选择器的冲突,各厂都制定了自己的CSS命名风格:

但这毕竟是弱约束。选择器随着项目的增长变得越多越复杂,然后项目组里再来个新人带入自己的风格,就更加混乱了。

所以我很赞同这句话:

与其费尽心思地告诉别人要遵守某种规则,以规避某种痛苦,倒不如从工具层面就消灭这种痛苦。

从工具层面,社区又创造出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也算是一种。

资源的模块化

Webpack的强大之处不仅仅在于它统一了JS的各种模块系统,取代了Browserify、RequireJS、SeaJS的工作。更重要的是它的万能模块加载理念,即所有的资源都可以且也应该模块化。
资源模块化后,有三个好处:
  • 依赖关系单一化。所有CSS和图片等资源的依赖关系统一走JS路线,无需额外处理CSS预处理器的依赖关系,也不需处理代码迁移时的图片合并、字体图片等路径问题;

  • 资源处理集成化。现在可以用loader对各种资源做各种事情,比如复杂的vue-loader等等。

  • 项目结构清晰化。使用Webpack后,你的项目结构总可以表示成这样的函数:
    dest = webpack(src, config)

组件化

首先,组件化≠模块化。好多人对这两个概念有些混淆。

模块化只是在文件层面上,对代码或资源的拆分;而组件化是在设计层面上,对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模式走过来的,近两年才从客户端框架经验中引入了组件化思想。其实我们很多前端工程化的问题都可以从客户端那里寻求解决方案。

自动化

作了这么多年程序猿的我,一直秉持的一个理念是:

任何简单机械的重复劳动都应该让机器去完成。

所以我也认为,前端工程化的很多脏活累活都应该交给自动化工具来完成。

图标合并

  • 不要再用PS拼雪碧图了,统一走Webpack吧;
  • 不要再用Icomoon了,统一走Webpack吧。

持续集成

自动化构建

自动化部署

自动化测试

前端自动化测试能够提高代码质量、减少人肉测试等,这些优点是不言而喻的。

市面上前端测试框架有很多,选择哪个都不会有太大问题,我们用的是:Karma + Mocha + Chai

posted @ 2017-07-28 10:20  烁儿  阅读(248)  评论(0编辑  收藏  举报