浅谈什么是前端工程化

1. 什么是前端工程化

自有前端工程师这个称谓以来,前端的发展可谓是突飞猛进。相比较已经很是成熟的其余领域,前端虽是后起之秀,但其野蛮生长是其余领域不能比的。虽然前端技术飞快发展,可是前端总体的工程生态并无同步跟进。目前绝大多数的前端团队仍然使用很是原始的“切图(FE)->套模板(RD)”的开发模式,这种模式下的前端开发虽然说不是刀耕火种的原始状态,可是效率很是低下。php

前端的工程化问题与传统的软件工程虽然有所不一样,可是面临的问题是同样的。咱们首先回顾一下传统的软件开发流程模型:
css

上图中的运行和维护并非串行关系,也并不是绝对的并行关系。维护贯穿从编码到运行的整个流程。html

若是说计算机科学要解决的是系统的某个具体问题,或者更通俗点说是面向编码的,那么工程化要解决的是如何提升整个系统生产效率。因此,与其说软件工程是一门科学,不如说它更偏向于管理学和方法论。前端

软件工程是个很宽泛的话题,每一个人都有本身的理解。以上是笔者我的的理解,仅供参考。node

具体到前端工程化,面临的问题是如何提升编码->测试->维护阶段的生产效率。python

可能会有人认为应该包括需求分析和设计阶段,上图展现的软件开发模型中,这两个阶段具体到前端开发领域,更恰当的称谓应该是功能需求分析和UI设计,分别由产品经理和UI工程师完成。至于API需求分析和API设计,应该包括在编码阶段。程序员

2. 前端工程化面临的问题

要解决前端工程化的问题,能够从两个角度入手:开发和部署。es6

从开发角度,要解决的问题包括:web

  1. 提升开发生产效率;
  2. 下降维护难度。

这两个问题的解决方案有两点:npm

  1. 制定开发规范,提升团队协做能力;
  2. 分治。软件工程中有个很重要的概念叫作模块化开发其中心思想就是分治。

从部署角度,要解决的问题主要是资源管理,包括:

  1. 代码审查;
  2. 压缩打包;
  3. 增量更新;
  4. 单元测试;

要解决上述问题,须要引入构建/编译阶段。

2.1 开发规范

开发规范的目的是统一团队成员的编码规范,便于团队协做和代码维护。开发规范没有统一的标准,每一个团队能够创建本身的一套规范体系。

值得一提的是JavaScript的开发规范,尤为是在ES2015愈来愈普及的局面下,保持良好的编码风格是很是必要的。笔者推荐Airbnb的eslint规范。

2.2 模块/组件化开发

2.2.1 模块仍是组件?

不少人会混淆模块化开发和组件化开发。可是严格来说,组件(component)和模块(module)应该是两个不一样的概念。二者的区别主要在颗粒度方面。《Documenting Software Architectures》一书中对于component和module的解释以下:

A module tends to refer first and foremost to a design-time entity. ... information hiding as the criterion for allocating responsibility to a module.
A component tends to refer to a runtime entity. ... The emphasis is clearly on the finished product and not on the design considerations that went into it.

In short, a module suggests encapsulation properties, with less emphasis on the delivery medium and what goest on at runtime. Not so with components. A delivered binary maintains its "separateness" throughout execution. A component suggests independently deployed units of software with no visibility into the development process.

简单讲,module侧重的是对属性的封装,重心是在设计和开发阶段,不关注runtime的逻辑。module是一个白盒;而component是一个能够独立部署的软件单元,面向的是runtime,侧重于产品的功能性。component是一个黑盒,内部的逻辑是不可见的。

用通俗的话讲,模块能够理解为零件,好比轮胎上的螺丝钉;而组件则是轮胎,是具有某项完整功能的一个总体。具体到前端领域,一个button是一个模块,一个包括多个button的nav是一个组件。

模块和组件的争论由来已久,甚至某些编程语言对二者的实现都模糊不清。前端领域也是如此,使用过bower的同行知道bower安装的第三方依赖目录是bower_component;而npm安装的目录是node_modules。也不必为了这个争得头破血流,一个团队只要统一思想,保证开发效率就能够了。至因而命名为module仍是component都无所谓。

笔者我的倾向组件黑盒、模块白盒这种思想。

2.2.2 模块/组件化开发的必要性

随着web应用规模愈来愈大,模块/组件化开发的需求就显得愈来愈迫切。模块/组件化开发的核心思想是分治,主要针对的是开发和维护阶段。

关于组件化开发的讨论和实践,业界有不少同行作了很是详细的介绍,本文的重点并不是关注组件化开发的详细方案,便再也不赘述了。笔者收集了一些资料可供参考:

  1. Web应用的组件化开发;
  2. 前端组件化开发实践;
  3. 大规模的前端组件化与模块化。

3. 构建&编译

严谨地讲,构建(build)和编译(compile)是彻底不同的两个概念。二者的颗粒度不一样,compile面对的是单文件的编译,build是创建在compile的基础上,对所有文件进行编译。在不少Java IDE中还有另一个概念:make。make也是创建在compile的基础上,可是只会编译有改动的文件,以提升生产效率。本文不探讨build、compile、make的深层运行机制,下文所述的前段工程化中构建&编译阶段简称为构建阶段。

3.1 构建在前端工程中的角色

在讨论具体如何组织构建任务以前,咱们首先探讨一下在整个前端工程系统中,构建阶段扮演的是什么角色。

首先,咱们看看目前这个时间点(2016年),一个典型的web先后端协做模式是什么样的。请看下图:

上图是一个比较成熟的先后端协做体系。固然,目前因为Node.js的流行开始普及大前端的概念,稍后会讲述。

自Node.js问世以来,前端圈子一直传播着一个词:颠覆。前端工程师要借助Node.js颠覆以往的web开发模式,简单说就是用Node.js取代php、ruby、python等语言搭建web server,在这个颠覆运动中,JavaScript是前端工程师的信心源泉。咱们不讨论Node.js与php们的对比,只在可行性这个角度来说,大前端这个方向吸引愈来愈多的前端工程师。

其实大前端也能够理解为全栈工程师,全栈的概念与编程语言没有相关性,核心的竞争力是对整个web产品从前到后的理解和掌握。

那么在大前端模式下,构建又是扮演什么角色呢?请看下图:

大前端体系下,前端开发人员掌握着Node.js搭建的web server层。与上文提到的常规前端开发体系下相比,省略了mock server的角色,可是构建在大前端体系下的做用并无发生改变。也就是说,不管是大前端仍是“小”前端,构建阶段在两种模式下的做用彻底一致,构建的做用就是对静态资源以及模板进行处理,换句话说:构建的核心是资源管理

3.2 资源管理要作什么?

前端的资源能够分为静态资源和模板。模板对静态资源是引用关系,二者相辅相成,构建过程当中须要对两种资源使用不一样的构建策略。

目前仍然有大多数公司将模板交由后端开发人员控制,前端人员写好demo交给后端程序员“套模板”。这种协做模式效率是很是低的,模板层交由前端开发人员负责可以很大程度上提升工做效率。

3.2.1 静态资源构建策略

静态资源包括js、css、图片等文件,目前随着一些新规范和css预编译器的普及,一般开发阶段的静态资源是:

  1. es6/7规范的文件;
  2. less/sass等文件(具体看团队技术选型);
  3. [可选]独立的小图标,在构建阶段使用工具处理成spirit图片。

构建阶段在处理这些静态文件时,基本的功能应包括:

  1. es6/7转译,好比babel;
  2. 将less/sass编译成css;
  3. spirit图片生成;

以上提到的几个功能能够说是为了弥补浏览器自身功能的缺陷,也能够理解为面向语言自己的,咱们能够将这些功能统称为预编译。

除了语言自己,静态资源的构建处理还须要考虑web应用的性能因素。好比开发阶段使用组件化开发模式,每一个组件有独立的js/css/图片等文件,若是不作处理每一个文件独立上线的话,无疑会增长http请求的数量,从而影响web应用的性能表现。针对诸如此类的问题,构建阶段须要包括如下功能:

  1. 依赖打包。分析文件依赖关系,将同步依赖的的文件打包在一块儿,减小http请求数量;
  2. 资源嵌入。好比小于10KB的图片编译为base64格式嵌入文档,减小一次http请求;
  3. 文件压缩。减少文件体积;
  4. hash指纹。经过给文件名加入hash指纹,以应对浏览器缓存引发的静态资源更新问题;
  5. 代码审查。避免上线文件的低级错误;

以上几个功能除了压缩是彻底自动化的,其余两个功能都须要人工的配置。好比为了提高首屏渲染性能,开发人员在开发阶段须要尽可能减小同步依赖文件的数量。

以上提到的全部功能能够理解为工具层面的构建功能。

以上提到的构建功能只是构建工具的基本功能。若是停留在这个阶段,那么也算是个及格的构建工具了,但也仅仅停留在工具层面。对比目前较流行的一些构建产品,好比fis,它具有以上所得的编译功能,同时提供了一些机制以提升开发阶段的生产效率。包括:

  1. 文件监听。配合动态构建、浏览器自动刷新等功能,提升开发效率;
  2. mock server。并不是全部前端团队都是大前端(事实上不多团队是大前端),即便在大前端体系下,mock server的存在也是颇有必要的;

咱们也能够将上面提到的功能理解为平台层面的构建功能。

3.2.2 模板的构建策略

模板与静态资源是容器-模块关系。模板直接引用静态资源,通过构建后,静态资源的改动有如下几点:

  1. url改变。开发环境与线上环境的url确定是不一样的,不一样类型的资源甚至根据项目的CDN策略放在不一样的服务器上;
  2. 文件名改变。静态资源通过构建以后,文件名被加上hash指纹,内容的改动致使hash指纹的改变。

其实url包括文件名的改动,之因此将二者分开论述是为了让读者区分CDN与构建对资源的不一样影响。

对于模板的构建宗旨是在静态资源url和文件名改变后,同步更新模板中资源的引用地址

如今有种论调是脱离模板的依赖,html由客户端模板引擎渲染,简单说就是文档内容由JavaScript生成,服务端模板只提供一个空壳子和基础的静态资源引用。这种模式愈来愈广泛,一些较成熟的框架也驱动了这个模式的发展,好比React、Vue等。但目前大多数web产品为了提升首屏的性能表现,仍然没法脱离对服务端渲染的依赖。因此对模板的构建处理仍然颇有必要性。

具体的构建策略根据每一个团队的状况有所差别,好比有些团队中模板由后端工程师负责,这种模式下fis的资源映射表机制是很是好的解决方案。本文不讨论具体的构建策略,后续文章会详细讲述。

模板的构建是工具层面的功能。

3.2.3 小结

构建能够分为工具层面和平台层面的功能:

  • 工具层面
  1. 预编译,包括es6/7语法转译、css预编译器处理、spirit图片生成;
  2. 依赖打包;
  3. 资源嵌入;
  4. 文件压缩;
  5. hash指纹;
  6. 代码审查;
  7. 模板构建。
  • 平台层面
  1. 文件监听,动态编译;
  2. mock server。

4. 总结

一个完整的前端工程体系应该包括:

  1. 统一的开发规范;
  2. 组件化开发;
  3. 构建流程。

开发规范和组件化开发面向的开发阶段,宗旨是提升团队协做能力,提升开发效率并下降维护成本。

构建工具和平台解决了web产品一系列的工程问题,旨在提升web产品的性能表现,提升开发效率。

随着Node.js的流行,对于前端的定义愈来愈宽泛,在整个web开发体系中。前端工程师的角色愈来愈重要。本文论述的前端工程体系没有涉及Node.js这一层面,当一个团队步入大前端时代,前端的定义已经不只仅是“前端”了,我想Web工程师这个称号更合适一些。

以前跟一位前端架构师讨论构建中对于模块化的处理时,他提到一个颇有意思的观点:所谓的压缩打包等为了性能作出的构建,实际上是受限于客户端自己。试想,若是将来的浏览器支持大规模并发请求、网络延迟小到微不足道,咱们还须要压缩打包吗?

诚然,任何架构也好,策略也好,都是对当前的一种解决方案,并非一条条铁律。脱离了时代,任何技术讨论都没有意义。

学习前端的同窗们,欢迎加入前端学习交流群

前端学习交流QQ群:461593224

相关文章
相关标签/搜索