前端工程化:体系设计与实践(txt+pdf+epub+mobi电子书下载)

作者:周俊鹏

出版社:电子工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

前端工程化:体系设计与实践

前端工程化:体系设计与实践试读:

前言

前端工程师这一岗位最初被独立分化出来专注于网页样式(CSS)的制作,目的是为了令Web开发者将更多的精力投入负责的业务逻辑中。然而随着Web技术的发展以及PC、移动智能终端设备性能和功能的提升,用户对于网站的需求也不断增加。市场的需求促进技术的革新,对于前端工程师的要求早已不仅仅是编写CSS了。资源的多样性和逻辑的复杂性一度令前端开发工作异常烦琐且难以维护,工作效率的降低直接导致Web产品的迭代速度变慢,前端工程化便是在此时代背景下应运而生的。

事实上,前端工程化目前的形态和生态仍然处于非常原始的阶段。每个团队甚至每个人由于存在研究领域(比如业务层和框架层)和业务类型(比如Google Map与淘宝)的差异,从而对前端工程化有不同的需求和定位。本书将前端工程化解读为一系列规范和流程的集合,它不是一个框架或者工具,聚焦的不是某个垂直的研究领域或者特殊的业务类型,而是一种可演化、可扩展的服务,服务的目标是解决前端开发以及前后端协作开发过程中的难点和痛点问题,涵盖项目的起始、开发、测试以及部署环节。工具是前端工程化的实现媒介,规范是工程化的指导方针,工作流程是工程化的外在表现形式以及约束规范的载体。

本书通过解析一个Web项目迭代过程中前端开发者面临的诸多问题,从工程化的角度给出对应的解决方案,最终将各个环节串联为完整的工作流。希望读者通过阅读本书可以对前端工程化要解决的问题有大致的了解,从而能够对读者自行实现工程化方案有所帮助。

目标读者

本书的主要目标读者是对前端工程化有一定理解和实践的中高级前端工程师,同样适用于对前端工程化感兴趣的服务器端开发者以及运维人员。本书假设读者熟悉Web站点的基本工作原理,尤其是前端与服务器端之间的协作流程,并且对HTTP协议、异步通信、模块化等知识有深入的理解。

示例代码

本书选取了一个简易的前端工程化解决方案Boi作为示例,这并不是一个完整形态的解决方案,但是它的许多理念可以作为论证本书观点的参考。读者可以从GitHub上获取其源码:https://github.com/boijs/boi。

内容概览

本书第1章以前端工程师从无到有直至发展至今的历程作为后续内容的起始。从历史中我们提炼出前端开发人员在一个Web项目迭代周期各个阶段面临的诸多问题,这些问题是前端工程化诞生的催化剂,也是指导工程方案设计的本源。之后,我们会按照Web项目从起始到发布的流程分别介绍前端工程化在各个阶段的需求和功能设计,比如脚手架在项目初期减少了重复的体力操作并且降低了业务框架学习成本;构建系统从编程语言、优化和部署3个角度解决了前端开发语言内在的缺陷以及由宿主客户端特性引起的开发和生产环境之间的差异性;本地开发服务器提供了前后端并行开发的平台;部署功能权衡速度、协作和安全,把控着Web产品上线前的最后一道关卡。最后将这些功能模块合理地串联为完整的工作流,便是前端工程化的完整外在形态。

前端工程师的定位在不同的年代甚至不同的团队中存在着巨大的差异,即使仅以目前的时间节点为标准也难以给前端工程师一个绝对明确的定义。岗位职责的变化促进了工程体系的演进,所以本书在最后的章节中阐述了一些对前端工程师未来定位的思考,同时探讨了与之对应的前端工程体系的演进形式。

以下是分章节介绍:

● 第1章 前端工程简史 讲述前端工程师的发展史、在团队中的定位,以及前后端分离和前端工程化的进化历程与基本形态。

● 第2章 脚手架 讲述作为前端项目起始阶段取代烦琐人工操作的脚手架必须具备的要素以及本质,通过剖析目前市面上的经典案例讲解实现脚手架过程中需要考虑的要点以及如何集成Yeoman到工程化方案中。

● 第3章 构建 讲述构建系统面临的问题以及对应的解决方案。构建是前端工程体系中功能最多、最复杂的模块,也是串联本地开发服务器、部署的关键,是实现工作流的核心模块。

● 第4章 本地开发服务器 讲述如何以Mock服务实现前后端并行开发,以及配合动态构建进一步提升前端工程师的开发效率。

● 第5章 部署 讲述部署功能如何权衡速度、协作和安全3个重要原则,以及前端静态资源特殊的部署策略。

● 第6章 工作流 讲述如何将既有的功能串联成完整的工作流。以速度见长的本地工作流和注重严谨的云平台工作流,两者各有优劣,适用于不同需求和不同规模的团队。

● 第7章 前端工程化的未来 讲述前端工程师如何选择进阶的方向以便适应未来的变化。前端工程化是服务于前端开发的,前端工程师定位的改变必然会引起工程化方案的调整。本章通过分析未来工程化不变和可变的方面,探讨前端工程化未来的表现形式。“前端工程化系列”丛书

本书是“前端工程化系列”丛书之一,着重讲述辅助性质的工程体系设计和实践过程。前端工程化可以简单地理解为前端架构与工程体系的综合体,两者相辅相成。本系列丛书的后续作品将从综合的角度深层剖析架构与体系之间的关联及融合,讲述如何从宏观的角度打造合理的前端工程化生态。感兴趣的读者可以关注本系列丛书的相关动态。

联系作者

如果您在阅读过程中有任何问题,可以发送邮件到作者的个人邮箱:zjp0432@163.com。

致谢

感谢我的同事和领导在我创作本书期间给予的建议和支持。特别感谢我曾经的技术领导元亮,在与他共事期间我于前端工程领域的探索和研究得到了充分的空间和资源。

感谢电子工业出版社博文视点的编辑付睿,她在编辑和审校本书期间提出了宝贵的意见。

最后,感谢我的朋友、父母以及妻子刘女士在我创作本书期间给予的空间和支持。

读者服务

轻松注册成为博文视点社区用户(www.broadview.com.cn),扫码直达本书页面。

● 提交勘误:您对书中内容的修改意见可在 提交勘误 处提交,若被采纳,将获赠博文视点社区积分(在您购买电子书时,积分可用来抵扣相应金额)。

● 交流互动:在页面下方 读者评论 处留下您的疑问或观点,与我们和其他读者一同学习交流。

页面入口:http://www.broadview.com.cn/33090  第1章 前端工程简史

前端工程化这个概念在近两年被广泛地提及和讨论,究其原因,是前端工程师所负责的客户端功能逻辑在不断复杂化。如果说互联网时代是前端工程师的舞台可能有些夸大其词,但前端工程师绝对撑起了互联网应用开发的“半壁江山”。传统网站、手机应用、桌面应用、微信小程序等,前端工程师已经不是几年前被谑称的“切图仔”了。以往的“写demo,套模板”模式已经严重拖累了前端开发以及整体团队的开发效率。在这样的时代背景下,前端工程化便应运而生了。

在本章中,我们首先讨论当前市场环境下对前端工程师的技能要求是什么,以此为前提探讨前端开发以及前后端协作开发中有哪些问题需要从工程化的角度解决。随后,沿着前端工程化从无到有的进化历程,了解前端工程化带给前端开发模式的改革和效率的提升,从而总结出前端工程化应有的形态。最后结合作者的经验,讲述如何以Node.js为底层平台、以webpack为构建体系核心打造一套完整的前端工程解决方案。

本章主要包括以下内容。

● 前端工程师的基本素养。

● Node.js带给前端的机遇和挑战。

● 前后端分离的必要性和基本原则。

● 前端工程化的进化历程和基本模式。

● 最流行的构建工具之一:webpack。1.1 前端工程师的基本素养

在讨论前端工程化之前,首先需要弄清楚什么是前端工程师。前端工程师是被人误解的工作很简单的“切图仔”,还是包揽客户端和中间层的“大前端”呢?招聘市场上有大量的公司对前端工程师求贤若渴,但同时求职市场上也有大量的前端工程师在“求职若渴”。造成这种两难局面的原因是,用人单位与求职者对前端工程师的技能需求以及定位存在差异。

应该怎么定位前端工程师这个岗位?下面让我们从前端的发展历史中找出答案。1.1.1 前端工程师的发展历史

1990年,Tim Berners Lee发明了世界上第一个网页浏览器WorldWideWeb。1995年,Brendan Eich只用了10天便完成了第1版网页脚本语言(也就是目前我们所熟知的JavaScript)的设计。在网络条件与计算机设备比较落后的年代,网页基本是静态的。对网页脚本语言功能的最初设想仅仅是能够在浏览器中完成一些简单的校验,比如表单验证。所以网页脚本语言的特点是:功能简单、语法简洁、易学习、易部署。那个年代的Web应用是重服务器端、轻客户端的模式,Web开发人员以服务器端开发为主,同时兼顾浏览器端,没有所谓的前端工程师。

2005 年,AJAX 技术的问世令静态的网页“动”了起来,异步请求和局部刷新彻底改变了网页的交互模式。同时,网络速度与个人计算机的普及给网站带来了更多用户,用户对网站的需求也越来越多。需求与技术的同步增长让早期的重服务器端、轻客户端的天平向客户端有所倾斜,也就是从那个时候开始出现了第一批专职的前端工程师。这批前端工程师相对于服务器端工程师的优势主要体现在对交互与UI 的敏感度和专业度上。所以第一批前端工程师中有很大一部分是设计师出身,导致前端工程师们有了一个很不相称的称谓:美工。但不可否认的是,第一批前端工程师主要负责的是CSS与HTML的开发,虽然有了AJAX技术,但受限于JavaScript引擎的性能,浏览器端的功能逻辑仍然十分简单。

2008年,Google推出了全新的JavaScript引擎V8,采用JIT(实时编译)技术解释编译JavaScript代码,大大提高了JavaScript的运行性能。随后,Netscape公司的SpiderMonkey和苹果公司的JavaScriptCore也紧随V8,加入了JavaScript引擎的性能追逐战。JavaScript引擎性能的提升让许多早期不能在浏览器端实现的功能得以实现,浏览器能够承载几千行甚至几万行的逻辑,Web 应用服务器端与客户端的天平再次向客户端一方发生倾斜。业内开始提倡REST(Representational State Transfer,具象状态传输)风格的Web服务API与SPA(Single Page Application,单页应用)风格的客户端。前端工程师承担起了客户端的交互、UI 和逻辑的开发,工作职责进一步加重。

2009年,Node.js的问世在前端界引发了轩然大波。Node.js将JavaScript语言带到了服务器端开发领域,截止到目前,业内已经有很多公司将Node.js应用到企业级产品中。虽然Node.js仍然没有像PHP、Java等传统服务器端语言一样普及,但由它引发的“大前端”模式已经在Web开发领域中蔓延。Node.js对前端生态的促进,以及对同构开发的支持是 PHP、Java 等语言远不能比及的,本书所探讨的前端工程方案便是以 Node.js 为底层平台实现的。“大前端”模式下的前端工程师跨越了之前浏览器与服务器端之间看似难以逾越的鸿沟,踏入了Web服务器端开发领域。1.1.2 前端工程师的技能栈

从最初的重交互/UI,轻 JavaScript 的开发模式,到交互、UI、逻辑一把抓,再到“大前端”的服务器端、客户端全掌控,前端工程师的工作内容和工作职责不断扩宽。从前端工程师的发展历史中,我们可以总结出前端工程师的技能栈。

● 硬技能:HTML/CSS/JavaScript。这3项是前端工程师从蛮荒年代发展至今从未脱离的核心技术。

● 软技能:用户体验。用户体验是Web产品吸引用户的第一道菜,也是前端工程师工作产出的重点。

● 扩展技能:Node.js。并非特指 Node.js 本身,而是 Node.js 所代表的 Web服务器端知识。即使你不是一个“大前端”,了解Web 产品的运行原理也是一个前端工程师必备的素养。

1.硬技能——HTML/CSS/JavaScript

这3项俗称“前端工程师的三把刷子”,是前端工程师必须掌握的3项核心技能。其实将HTML/CSS与JavaScript放在一起讨论并不合适,HTML和CSS作为标记类语言,只有在浏览器环境或者类浏览器环境下才会被识别解析,所以可以认为这两者是DSL(Domain Specific Language,领域特定语言);而JavaScript与HTML/CSS的性质不同,虽然不如 C++、Java 等高级语言那样严谨,但其本质上是一门编程语言。同其他编程语言一样,对于JavaScript,掌握其语法和特性是最基本的。但上面这些只是应用能力,最终考量的仍然是计算机体系的理论知识。所以,数据结构、算法、软件工程等基础知识对于前端工程师同样重要,这些知识能够决定一个前端工程师的上限。

HTML/CSS/JavaScript这三者只是统称,代表着前端工程师能力的3个方面。三者相互耦合,并非独立。比如CSS必须与HTML配合、JavaScript逻辑须借助HTML和CSS直观地展示给用户。任何一项都是一个庞大的技能树,可以细分出很多子技能。对于HTML,要掌握各个标签的合理使用和基本的Web API。对于CSS,要在理解各属性的工作模式的前提下能够综合使用,给出合理的解决方案;并且由于浏览器的差异,还必须掌握必要的hack方案。虽然这些hack方案最终都会被历史的尘埃掩埋,但目前[1]我们仍然无法避免兼容性问题。对于JavaScript,与其他任何一门编程语言一样,除要求掌握基本的语法,有基本的应用编程能力以外,还必须具备良好的抽象能力以及架构能力。

2.软技能——用户体验

除了以上提到的“硬技能”外,前端工程师还必须掌握一项“软技能”,即用户体验。

前端工程师的产出是直接面向用户的,良好的用户体验是一个Web产品的基本要素。这里的用户体验并非指的是交互方案和视觉设计,当然这些也是用户体验的一部分。此处我们讨论的用户体验包括但不限于以下几点。

● 保证内容的快速展现,减少用户等待时间。

● 保证操作的流畅度。

● 如果是移动设备,应尽量减少设备的耗电量。

上述几点总结起来其实就两个字:性能。如果说按时完成了业务的所有需求是保证了“量”,那么提升产品的性能就是保证了“质”,两者缺一不可。

JavaScript设计之初最经典的应用场景是表单验证。比如,一个需要验证用户名和密码的表单,用户没有输入任何内容就单击“发送”按钮,仍然会发送一个请求到服务器端进行验证。这在今天的网络技术下没什么大不了,但在网络速度慢而且上网费用昂贵的年代,这样的代价是非常巨大的,并且用户必须等待服务器端处理后才能得到反馈。JavaScript在浏览器发送请求之前验证内容的有效性,避免一次无效的请求,既减轻了服务器端压力,节省了成本,又减少了用户等待时间,提升了用户体验。可见JavaScript设计的初衷便将用户体验作为重要的考虑因素。

在现今社会的快节奏下,用户对于产品的需求也倾向于快速化:快速展现、快速迭代。用户不想为了看一条新闻而去下载一款新闻软件,他们希望打开网站即可快速查看。Web 产品本身就具备快速的基因,性能优化的最终目标也是保证“足够快”。所以,前端工程师不仅要求熟练地使用基本的开发技能,还必须具备性能优化的意识和技能。

小贴士:你可能会产生疑问:学习能力不算软技能的一种吗?这是因为学习能力是任何岗位都必须具备的软技能之一,并不是专属于前端工程师的软技能。

3.扩展技能——Node.js

将Node.js定位为扩展技能,并非指的是Node.js本身,而是以Node.js为代表的Web服务器端知识。前端工程师掌握Web客户端的相关知识是基本要求,欠缺的是对Web服务器端的了解。虽然并不是每个前端工程师都是“大前端”,并且让前端工程师编写不熟悉的服务器端逻辑也并不十分恰当,专业的事应该由专业的人负责,但这并不意味着前端工程师不需要熟悉服务器端的理论知识。了解Web应用从前到后的工作流程和整体架构模型,有助于前端工程师编写更合理的客户端逻辑,以及对产品出现的问题及时定位。

综上所述,一个合格的前端工程师应该掌握的技术栈可以用图1-1概括。图1-1

前端工程师是承载用户层所有功能的资源产出者,不仅是客户端最终呈现给用户的HTML/CSS/JavaScript等资源成品,而且还包括这些资源从零开始到最终产出的生产流水线所涵盖的所有环节。请读者时刻谨记前端工程师的定位,这是本书讨论的前端工程化的重要前提。1.2 Node.js带给前端的改革1.2.1 前端的两次新生

Brendan Eich[2]可能也没有想到JavaScript这门第1版只用了10天便完成设计的脚本语言在今天会如此流行。JavaScript目前不仅可以开发传统的Web站点,而且还跨足了手机App、小程序、物联网等开发领域。JavaScript经历过两次革命性的突破,这两次突破也带给了前端两次新生。

1.第一次新生:AJAX

AJAX技术起步于微软Outlook的XMLHTTP组件,微软将其作为ActiveX组件的一部分加入Internet Explorer 5。随后,其他浏览器厂商,包括Mozilla、Safari、Opera等,实现了一个同样功能的JavaScript对象——XMLHttpRequest。微软是AJAX技术的布道者,Google的进一步推广将其带到了普通民众眼前。人们惊叹于Google地图、Gmail等Web应用程序绝佳的用户体验。Jesse James Garrett[3]在2005年2月“Ajax:A New Approach to Web Applications”一文中正式提出了“AJAX”一词,并一直沿用至今。随后,W3C在2006年正式发布了XMLHttpRequest规范草案。

AJAX 技术可以实现异步请求和局部刷新,彻底改变了传统 Web 站点的交互模式。Web不仅是供静态展示的网站,而且是一种由浏览器展现、资源寄存于Internet的应用程序。以此为契机,Web 开发者开始在 AJAX 技术的基础之上探索和开发更加丰富的功能和优雅的用户体验。与此同时,用户对Web应用的需求也不断提高,这间接推动了Web技术的发展。

这是AJAX技术带给前端的第一次新生。

2.第二次新生:Node.js

2009年第1版Node.js(只支持Linux和Mac OS X系统)的发布是值得铭记的里程碑。Node.js的作者Ryan Dahl设计Node.js的灵感来自Flickr(一个提供网络图片服务的平台)上的一个上传进度条,浏览器为了能够获取上传文件的进度而不得不频繁地向服务器发起查询请求。与这种方式相比,如果服务器能够在文件上传完毕之后主动推送一条消息给浏览器的话,会节省很多浏览器和网络资源消耗。这种理念便是Node.js实现异步操作的核心Event Loop(事件驱动)的雏形,如图1-2所示。图1-2

2011年,Node.js发布了支持Windows系统的版本,Node.js在Web开发界进一步流行起来。在此之前的十几年内,JavaScript一直被认为只能在浏览器里耍点小把戏。即便AJAX技术彻底改变了网站的交互模式,JavaScript也仍然未脱离浏览器这个“宿主”。Node.js带来的改革不仅仅是让JavaScript进入了服务器端开发领域,更重要的意义是丰富了 JavaScript 的生态。JavaScript 能做的事情越来越多,业内泛起了JavaScript学习潮,这在一定程度上加速了ECMAScript规范的迭代。

这是Node.js带给前端的第二次新生。

小贴士:随着用户对Web应用的期待越来越高,承载Web应用的浏览器也“被迫”加速了发展,尤其是 JavaScript 引擎。在 AJAX 技术问世之前,JavaScript引擎只要能够稳定运行几十行JavaScript代码即可,但是如今Web应用的JavaScript代码已经远远超过这个量级,动辄几百上千行。2008年,Google推出了全新的浏览器Chrome,搭载代号为V8的JavaScript引擎。V8引擎采用实时编译(JIT)技术将JavaScript代码编译为机器码执行,大大提高了 JavaScript 代码的运行效率。Node.js 便是使用 V8 引擎执行JavaScript代码的。1.2.2 Node.js带来的改革

Node.js并非一个JavaScript框架,而是一个集成了Google V8 JavaScript引擎、事件驱动和底层I/O API,并且可使用JavaScript语言开发服务器端应用的运行环境。与PHP不同的是,Node.js可以直接提供网络服务,不需要借助Apache、Nginx等专业的服务器软件。虽然并不建议在生产环境下直接将Node.js服务暴露给用户,但是Node.js 这种特性可以让我们更方便地开发各种工具,比如将在后续章节中讲解的前端工程化方案中本地服务器的搭建。

1.服务器端开发

Node.js作为服务器端平台已经逐步被国内外公司和团队接纳。2015年10月,著名的开源博客系统WordPress发布了使用Node.js重写的4.3版本。许多企业(国内的,比如阿里巴巴、美团等;国外的,比如IBM、LinkedIn、GoDaddy等)对Node.js也均有不同程度的使用。虽然Node.js尚未威胁到PHP、Java等传统Web服务器端语言的地位,但Node.js的事件驱动和异步I/O机制,以及其易学习、易部署和对前端工程师天然的语言共通性,让其成为实时应用、微服务以及前端工程化等应用场景的最佳技术选型之一。

2.同构JavaScript

Node.js 在使用 JavaScript 语言开发 Web 服务器端平台的同时,还提高了同构JavaScript开发的可行性。

同构(isomorphism)一词是数学领域的专业术语,指的是数学对象之间属性或者操作关系的一类映射。数学中研究同构的主要目的是为了把数学知识应用于更多不同的领域,同理,在JavaScript开发领域研究同构的主要目的也是为了将这门编程语言应用于不同的开发领域。同构JavaScript的概念最早由Airbnb工程师Spike Brehm提出,简单讲就是令JavaScript编写的代码既可以在浏览器端工作,也可以在服务器端工作,如图1-3所示。这意味着服务器端和浏览器端都可以承载网页的渲染工作。图1-3

传统网站的渲染流程是由浏览器主动发起请求,然后服务器端生成HTML文档后发送响应给浏览器,浏览器接到响应后将HTML文档渲染为可视网页。这是自浏览器发明以来就沿用至今的渲染流程。这种工作模式的优点是节省客户端资源,在客户终端设备以及浏览器性能普遍比较落后的情况下能够保证良好的渲染效果,并且服务器端渲染的网页更利于SEO(Search Engine Optimization,搜索引擎优化)。而其缺点是每访问一个页面都要发起请求,每个请求都需要服务器进行路由匹配、数据库查询、生成HTML文档后再发送响应给浏览器,这个过程会消耗服务器的大量计算资源,如图1-4所示。图1-4

随着个人终端设备和浏览器性能的不断提升,Web 开发者尝试将渲染以及路由工作交给客户端,服务器端RESTFul API只提供渲染HTML所需的JSON数据。这种形态的Web应用被称为SPA(Single Page Application,单页应用)。SPA有以下优点。

● 减轻了服务器的资源消耗。

● 与HTML文档比起来,JSON数据的体积小很多,减少了网络请求的时间消耗。

● 页面路由控制更快速灵活。

● 可以离线使用。

同时SPA也带来了新问题。首先,浏览器需要等待JavaScript文件加载完成之后才可以渲染后续的 HTML文档内容,用户在等待的过程中页面是空白的,这就是我们在进行Web产品性能评估时经常谈到的“白屏时间”;其次,由于客户端和服务器端编程语言不同,可能会存在一些诸如数据格式的差异,甚至路由逻辑冲突,比如vue-router history模式的路由,这些问题增加了维护难度;最后,SPA不利于常规的SEO(搜索引擎优化)爬虫(之所以说常规是因为Google已经针对SPA进行了SEO优化,但是目前国内的搜索引擎对SPA的支持并不理想)。

与传统的服务器端渲染模式和客户端渲染的单页应用相比,同构JavaScript拥有更好的性能、可维护性以及对SEO更好的支持。同构JavaScript的理念类似于Java秉承的“Write once,run anywhere”,JavaScript除命名以外终于又跟Java扯上了关系。Node.js是实现同构JavaScript开发的关键。一方面,JavaScript在浏览器环境下可以执行渲染工作;另一方面,Node.js 运行环境下同样可以使用 JavaScript 创建HTML字符串。在这个前提下,JavaScript开发生态中浮现了一大批支持同构开发的框架和库,比如Facebook推出的React.js和国内的Vue.js。

3.前端工具

除了服务器端开发外,Node.js 对前端最大的贡献是丰富了前端工具生态。在Node.js 出现以前,没有 Grunt、Gulp、webpack 等便捷且强大的工具,压缩合并JavaScript、CSS 代码对于前端工程师来说是一项非常艰难的任务。前端工程师不得不使用不熟悉的语言、工具来处理静态文件的压缩合并。而这些工具往往并不是为了处理静态文件的,比如Apache Ant。使用Ant处理静态文件可以说是杀鸡用了牛刀,而且这把牛刀用来杀鸡还并不好使。除此之外,也可以使用shell脚本完成这项工作,但对于并不擅长编写shell脚本的前端工程师来说学习成本和时间成本太高,往往要麻烦团队中的服务器端工程师代写。不论哪种选择,都会对项目的开发进度产生影响。

Node.js 的出现彻底解决了这些问题。目前耳熟能详的前端工具,比如 Grunt、Gulp、webpack,无一不是由Node.js承载的。结合JavaScript的灵活性与Node.js提供的API,前端工程师可以编写各种工具满足项目的开发需求。本书所介绍的前端工程化解决方案中的各个功能模块全部是由JavaScript语言实现的。1.3 前后端分离

从传统网站到SPA再到同构JavaScript,前端工程师的工作内容不断加重,客户端逻辑不断复杂化。原始的前后端耦合的串行开发流程已经不能满足Web产品快速的迭代需求,Web 开发者们开始尝试在开发、测试和部署等各个环节寻求更高效的协作方式。前后端分离似乎就是解决这个问题的“银弹”。

顾名思义,所谓前后端分离指的是通过将前端工程师与后端工程师进行明确、合理的分工,改善前后端协作中拖慢开发进度的环节,提高工作效率。前后端分离的核心是解耦。从开发、测试以及部署3个角度看,前后端分离对工作效率的提升如下。

● 从开发角度来讲,前后端分离的宗旨是实现并行开发,缩短开发周期。

● 从测试角度来讲,前后端分离令前端工程师和后端工程师更快速、精准地对问题进行定位。

● 从部署角度来讲,前后端分离将静态文件和动态文件分离部署并结合回滚策略,简化了部署流程,增强了应用程序的健壮性。1.3.1 原始的前后端开发模式

首先要说明此处“原始”一词背后的时代意义,那是在前端工程师这个岗位刚刚出现不久,前端工程师普遍地被称为“切图仔”或者“美工”的时代。前后端典型的协作模式是,前端工程师写demo,后端工程师写逻辑和套模板。在这种原始的分工模式下,前端工程师的主要工作是将UI设计稿使用HTML和CSS进行还原,对于JavaScript的开发顶多是实现一些动画效果,业务逻辑基本不涉及。然后,前端工程师将开发完成的demo交付给后端工程师,后端工程师做的第一件工作是将demo代码中的HTML和CSS套入服务器模板引擎中,俗称“套模板”,而后在此基础上编写客户端的JavaScript业务逻辑。

这种协同工作模式下的开发效率是非常低下的。请读者想象一下,如果在进行网站的UI测试时发现某个div的border颜色与设计稿不符,或者某个模块的显示完全错乱了,这时应该怎么办?测试人员将Bug反馈给开发团队后,前端工程师对Bug进行排查,发现测试环境中某个div的classname写错了,或者某个div标签没有闭合。你可能认为这些是后端工程师套模板过程中粗心大意导致的,但是这种问题是无法避免的,人不是机器,总会有粗心大意的时候。如果一个网站有成百上千个HTML 节点,这种人为过失导致的问题会被无限放大且非常难以排查。即使我们假设后端工程师百分之百不会粗心大意,如果发现上线后的网站样式与UI设计稿有1像素的偏差,前端工程师修改CSS或者HTML后,仍然需要后端工程师再重复一次套模板工作,完成后再提交测试。我们会发现,这种1像素的Bug修复需要调动整个开发团队(包括前端工程师和后端工程师)资源。这种模式在前些年非常普遍,而且很不幸的是,至今国内仍然有相当一部分团队使用这种原始的协作模式。

这种原始的前后端协作模式之所以在前些年比较普遍,一是因为当时客户端的逻辑并不十分复杂,JavaScript逻辑交给后端工程师就可以了,不需要专业的前端工程师。事实上,当时有相当一部分写demo的工作是交给UI设计师负责的,当然需要一些专业工具辅助,比如微软的 DreamWeaver;二是因为当时网站的迭代需求并不像如今这么快,没有频繁的更新也就不需要特别高效的生产流水线。但是在如今的市场环境下,一方面Web应用的迭代效率是争取用户的必要手段之一;另一方面,前端技术的快速发展已经超越了后端工程师的能力范畴,必须由专职的前端工程师负责。在这种环境下,原始的前后端开发模式的弊端被进一步地放大了,前后端分离便应时而生了。1.3.2 前后端分离的基本模式

合理的分工是前后端分离的第一步,也是后续各种优化方案的基础。团队人员按职能分为前端工程师和后端工程师,按照1.1节总结出的前端工程师的定位,前端工程师负责的内容包括以下几方面。

● CSS以及相关的图片等媒体资源。

● JavaScript逻辑。

● HTML文档,包括产出HTML的源文件,比如HTML模板。

对于前端工程师来说,后端工程师的唯一产出就是数据,包括用于服务器渲染HTML模板的初始数据和客户端异步请求接口返回的数据。

明确了各自的分工后,我们分别从开发、测试和部署3个方面分析前后端分离要解决哪些问题。

1.开发

开发阶段前后端分离要解决的问题可以按照资源类型分为两种:静态资源的处理和动态资源的处理。

静态资源指的是 JavaScript、CSS、图片等,这类资源在浏览器的呈现方式是静态的,不需要服务器做任何处理。动态资源指的是HTML模板,除非你的项目不需要任何服务器端渲染的 SPA,否则我们仍然不可避免地要处理前后端最难解耦的HTML模板。

静态资源的处理相对简单,因为这类文件不依赖任何服务器环境,只要最终在浏览器里解析即可。HTML模板的处理方案可以按照项目类型分为以下几种。

1)SPA项目。这类项目中不存在HTML模板的概念,所有的HTML实体内容均由JavaScript在浏览器下生成。所以SPA项目中可以将html文件作为静态文件处理。

2)HTML模板由服务器端部署的项目。这类项目最终的HTML模板需要与服务器端代码一同打包部署。由于静态文件必须由HTML引入,为了避免“套模板”,开发阶段前端工程师直接编写HTML模板更有利于快速开发和问题定位。

3)大前端项目。这类项目中前端工程师负责与客户端相关的所有文件,包括静态文件与HTML模板,这是最理想的模式。

可以看出不论是 SPA 还是大前端,开发阶段的前后端分离都比较容易实施。但我们不得不面对的一个现实是,目前国内的Web产品绝大多数是第二种项目类型。这也是最难以实现完全前后端分离的项目。

小贴士:之所以称为“大前端”而不是“全栈工程师”是因为大前端通常不接触数据库操作。大前端负责的并不是真正的Web服务层,而是中间层。中间层的作用主要解决的就是HTML的渲染,这也是为了实现前后端分离而探索出的一个模式。

对于HTML模板由服务器端部署的项目,前后端分离要解决3个问题。

1)HTML模板引擎的支持。

2)HTML模板的初始数据。

3)各种异步数据接口的数据。

HTML 模板引擎种类繁多,并且根据服务器端编程语言的不同,部署难度也不尽相同。易部署的如PHP、Node.js、Python等,稍难部署的如Java、.NET等。目前的市场情况较之前有了比较明显的改善,Node.js 的不断改进已经令很多初创团队选择Node.js作为Web服务的编程语言。并且成熟的团队通常都有中间层,Java承载着大后端数据服务,中间层使用易部署的编程语言,比如PHP、Node.js和Python。

HTML模板的初始数据和异步接口的数据都可以用Mock服务解决。前后端开发人员在编写代码之前约定好接口的请求规范和数据结构。开发期间,前端工程师按照规范使用Mock服务提供的模拟数据进行开发。Mock服务处理HTML模板的初始数据和异步接口数据稍有不同,HTML模板数据需要在服务器端渲染使用,在MVC架构模型中,这类数据通常由Controller提供给HTML模板引擎。在非大前端模式下,前端工程师如果不想花费时间与精力编写模拟Controller代码,可以在构建工具上下点功夫。在渲染HTML模板时注入约定格式的数据即可,本书将在第4章详细讲解具体的实现方案。

2.测试

测试分为两个阶段,第一个阶段是前后端工程师的单元测试,这个阶段前后端工程师的测试是独立的,各自的测试流程和结果不会影响对方;第二个阶段是集成测试,这个阶段前后端的代码进行整合,在测试环境下由专业的测试工程师进行测试用例遍历。

前后端分离首先要解决的是集成测试阶段的问题及时定位,解决方案并不是通过技术或工具,而是通过明确责任承担角色。测试工程师等同于内测用户,站在用户的角度上对产品进行使用和评估,他们反馈的问题就等同于是用户的反馈。既然是用户的反馈,那么直接责任人就应该是前端工程师。前端工程师负责所有与用户直接接触的功能和逻辑,所以有责任在出现问题时站在第一线。后端工程师的产出并不与用户直接接触,前端工程师更容易定位用户层面的问题。理想情况下,服务器端单元测试覆盖率达标并且测试通过后,接口是不应该存在逻辑性错误的。如果客户端出现因数据引起的问题,通常是因为客户端的JavaScript逻辑存在问题,比如一些side effect(临界问题)没有处理好。即使服务器端的单元测试没有达到理想情况,前端工程师通过调试工具也更容易发现问题的症结。

小贴士:前后端分离不仅仅是通过技术手段解决问题,技术和工具只是辅助,其本质是分工和角色的细分。这恰恰是目前很多团队在进行前后端分离时容易忽略的问题。

除集成测试阶段外,前后端分离还必须兼顾产品在生产环境下的质量保障问题。目的仍然是对出现问题的及时预警和快速修复。这方面的通常做法如下:

制定客户端监控系统,收集客户端问题并及时通知开发人员。

小贴士:大多数团队并未将生产环境的客户端质量保障作为前后端分离的一部分。服务器端通常具备监控、预警以及应急策略,尽可能保证服务器问题的及时处理。同理,客户端也应该具备监控机制,并且由前端工程师负责。

3.部署

前后端分离在部署阶段要解决的问题是静态资源和动态资源的分离部署。

与开发阶段类似,不同的项目类型需要制定不同的部署方案。在3种项目类型中,大前端模式下的部署方案是最简单的,因为前端工程师能够掌控所接触的所有资源。具体部署方案如下。

● 将JS、CSS、图片等静态资源部署到静态文件服务器。

● HTML模板文件与中间层的Node.js代码一同部署到Web服务器。

SPA项目的部署方案稍微复杂一些,由于SPA中的html文件不需要在服务器端渲染,因此其理论上可以与其他静态资源一同部署到静态文件服务器。但是需要注意的一个问题是,不能令浏览器将html文件强制缓存到本地。如果用户之前访问过此页面,html 文件被浏览器强制缓存到本地,那么即使开发人员更新了 html 文件,也会由于浏览器的缓存策略而无法获取最新版本的资源。除非用户手动清除浏览器缓存,而这显然是不可行的。解决这个问题的办法有两种,分别如下。

1)分别为html文件与其他静态资源设置不同的缓存策略。html文件可以使用协商缓存策略(浏览器HTTP请求返回状态码304),其他静态资源使用强缓存策略(浏览器HTTP请求返回状态码“200(from cache)”。关于这两种缓存策略的详细内容本书会在第3章介绍。

2)使用一刀切的方案,所有静态资源均使用协商缓存策略。

第一种方案不论是从客户端性能、用户体验,还是从服务器端压力的角度来讲都优于第二种。具体实施也不是很麻烦,Apache、Nginx等专业服务器软件都可以针对文件扩展类型设置不同的缓存策略。

最麻烦的是第二种项目,也就是HTML模板由服务器端部署,并且前端工程师不负责中间层或者服务器端开发的项目。这类项目通常的部署方案如下。

● 静态资源部署到静态文件服务器。

● HTML模板文件编写完成之后由前端工程师通过SVN、Git等版本管理工具同步到代码仓库,后端工程师拉取最新代码后,将模板文件与服务器端逻辑代码一同部署。

静态资源和动态资源分离部署的优点是:在集成测试阶段,对于只涉及一方(前端或者后端)的Bug,相关负责人修改代码后独立进行部署即可,不需要另一方再行部署。比如CSS样式出现问题,前端工程师修改css文件后部署到静态文件服务器,不需要后端工程师再部署一次服务器端文件即可在浏览器刷新后获取修复后的文件。当然,这个优点只是针对测试阶段,因为大部分公司供测试使用的静态文件服务器是不设置客户端缓存的,这样可以保证测试环境下每次访问网站都能拿到最新的资源。但是在生产环境下必须使用浏览器缓存,所以修复生产环境的问题必须按照上述部署策略进行重新部署。本书第5章将介绍具体的部署方案。1.3.3 前后端分离与前端工程化

前后端分离策略是制定前端工程化解决方案的指导方针之一;前端工程化的最终目的之一便是实现更合理、更便利的前后端分离开发环境。两者相互依赖、紧密耦合在一起。如果将前后端分离策略比喻成建筑设计图,那么前端工程化方案就是按照这张设计图进行具体建设的。在前端工程化这栋建筑平台上,前端开发人员和服务器端开发人员可以更顺畅、更高效地进行开发工作。1.4 前端工程化

虽然前端工程化是最近几年才兴起的一个方向,但工程化并不是一个新词。前端工程师普遍不熟悉的其他开发领域很早就具备了高度的工程化,比如Web服务器端开发。在前端业务逻辑比较简单的年代,前端资源通常作为服务器端资源的一种“附属品”,Web 开发者没有意识到且也没有必要为前端制定专门的工程化方案。前端需求和逻辑的不断加重是催生前端工程化的环境因素,前端相关技术、规范和工具的发展是前端工程化得以实施的必要前提。1.4.1 前端工程化的衡量准则

前端工程化的主要目标是解放生产力、提高生产效率。通过制定一系列的规范,借助工具和框架解决前端开发以及前后端协作开发过程中的痛点和难点问题。

1.3节我们从开发、测试和部署3个角度分析了前后端分离对于工作效率的提升,既然前后端分离是前端工程化方案的指导方针,这三者也就成为衡量前端工程化方案是否合格的重要因素。具体的衡量标准就是我们常说的3个字:快、准、稳。

1.从开发角度衡量工程化主要体现在“快”。

开发速度是Web产品迭代最迫切提升,也是催生开发人员与产品经理、项目经理以及测试人员之间矛盾的主要因素,自然也是衡量前端工程化方案最直观、最明显的标准。工程化方案的核心目标之一就是在保证质量的前提下,尽可能提高产品的开发速度。

2.从测试角度衡量工程化主要体现在“快”和“准”。

测试的“快”体现在前端工程师和服务器端工程师并行开发完成之后的集成测试阶段。1.3节从测试角度分析前后端分离时提到了完备且合理的单元测试通过后,集成测试阶段是不应该存在逻辑性错误的。但人不是机器,不可能考虑得面面俱到。从这个角度考虑,工程化要解决的就是尽量减少低级的逻辑错误,降低集成测试阶段消耗的时间成本。

测试的“准”体现在集成测试阶段对问题的准确定位。1.3节我们提到了,工程化不仅仅是冷冰冰的工具和平台,同时也需要严格的分工制度。通过明确责任人,对测试出现的问题进行快速准确的定位。

3.从部署角度衡量工程化主要体现在“稳”。

部署是一个完整迭代周期的最终阶段。经历了漫长的开发和测试,团队中的所有成员都希望自己的产品能够第一时间完美无误地出现在用户面前。部署并不是简单地把文件“放到”线上就可以了,还需要考虑用户客户端的缓存是否影响了新版本的展现、考虑测试用例没有覆盖100%情况下的危机处理、考虑不同地区开放不同版本等。如果你想将Web产品稳稳地呈现给用户,部署环节必须把好最后也是最关键的一关。1.4.2 前端工程化的进化历程

市场需求和技术的发展在不断地改变Web产品形态,在前端工程师的工作内容不断变化的过程中,前端工程化的形态也一直都在变化着。

1.混沌形态

我们不妨将这种“前端写demo,后端写逻辑、套模板”的开发模式称为“混沌形态”。这种形态的时代背景是Web产品的逻辑和交互普遍比较简单,前端工程师这一专业岗位刚刚兴起,但是负责的工作仅仅是样式以及部分动画逻辑。前端工程师与后端工程师之间的协作是串行的,如图1-5所示。

混沌形态下前端工程师的产出资源除了CSS外,均需要后端工程师进行二次处理后才会上线,甚至有时候连CSS都需要二次处理,比如行内样式。这种形态下是没有前端工程化可言的。图1-5

2.前后端分离形态

催动前端开发第一次进化的关键技术是 AJAX。AJAX 技术的问世不仅改变了Web页面的交互模式,也间接提高了用户对Web产品的需求,从而促进了前端逻辑的不断复杂化。服务器端工程师负责前端逻辑开发的混沌形态被打破,因为服务器端逻辑本身便具备高度的复杂度,再加上复杂的前端逻辑,自然不堪重负。所以,工程师开始思考改变原有的分工模式:前端逻辑、样式和HTML全部交由前端工程师开发。这是催生前端工程化萌芽的关键一步,此时的协作流程如图1-6所示。图1-6

在这种分工模式下,省去了后端工程师对JavaScript代码的整合以及对CSS代码的二次处理工作,从一定程度上提升了维护和迭代的工作效率。但是因为静态资源与动态资源一同部署,所以仍然难以避免必要的人工交付流程。

我们设想一下将这种分工模式带入当前时间节点,这时开发过程中会遇到哪些问题。

1)我们想使用最新的ECMAScript规范进行开发,但是受限于浏览器实现不理想,上线前需要使用特殊工具转译为浏览器支持的语法。

2)我们受够了CSS的弱编程能力,想使用LESS/SASS等预编译语法或者PostCSS自动处理hack。但是浏览器不支持,上线前需要使用特殊工具进行编译转换。

3)本地开发环境下静态资源的引用 URL 都是本地相对地址,上线前要修改为真实的 URL。手动修改非常烦琐,需要借助工具完成。这种功能通常被称为资源定位。

4)考虑产品的性能,上线前需要将JS、CSS、图片等资源进行压缩,需要使用CSS Sprites,甚至需要将小体积图片通过base64格式内嵌,这些都需要借助于工具实现。

5)模块化开发能够提高Web产品的性能和源代码的维护效率,散列的模块在上线前需要进行依赖分析与合并打包,需要借助于工具实现。

6)编写 JavaScript 逻辑代码时如果需要与数据接口交互,则依赖于服务器端接口API的完成进度。

7)静态文件(JS、CSS、图片等)与动态文件(HTML 模板)仍然存在于同一项目中,所以前端工程师产出的文件仍然需要服务器端工程师进行部署。

小贴士:此处列出的只是一些比较典型的问题,并未覆盖前后端开发以及协作过程中的全部问题。

将上述问题进一步划分:前5条因为不存在前后端的耦合,可以归类为前端开发层面的问题;第6条属于前后端协作的问题;第7条属于部署的问题。细化分类后的问题列表如下。

● 开发层面

✗ ES规范与浏览器兼容性不一致。

✗ CSS的弱编程能力。

✗ 资源定位。

✗ 图片压缩/base64内嵌/CSS Sprites。

✗ 模块依赖分析和压缩打包。

● 协作层面

✗ JavaScript部分逻辑依赖接口API。

● 部署层面

✗ 部分资源需要借助后端工程师部署。

笔者相信大多数一线开发者最迫切要解决的问题普遍集中在开发层面。在开发层面问题的描述中反复提到一个词——工具。开发者采用各种各样的专业工具解决对应的需求,比如使用Babel进行ES规范的转译、使用LESS/SASS编译工具进行预编译语法转译、使用r.js解决AMD模块的压缩打包等。将所有工具的功能进行整合并统一为规范的工具栈(请注意不是将工具整合,而是将功能整合),这就是前端工程化的第一步:构建。

第一步:加入构建流程

引入构建后的工作流程如图1-7所示。图1-7

构建流程可以确保前端工程师能够使用有助于提高开发和维护效率的框架、规范进行源代码的编写,比如使用 ECMAScript 6/7 规范编写 JavaScript、使用LESS/SASS等预编译工具编写Style、使用AMD/CommonJS等模块化方案进行模块化开发等。此外,构建还具备图片压缩、自动生成CSS Sprites等功能,进一步减少了烦琐的人工操作。

前端工程化进化到第一步后解决了开发层面的问题,会提高前端工程师的开发效率,但是仍未触及协作以及部署层面。

● 开发层面

✓ ES规范与浏览器兼容性不一致。

✓ CSS的弱编程能力。

✓ 资源定位。

✓ 图片压缩/base64内嵌/CSS Sprites。

✓ 模块依赖分析和压缩打包。

● 协作层面

✗ JavaScript部分逻辑依赖接口API。

● 部署层面

✗ 部分资源需要借助后端工程师部署。

构建流程的加入提高了前端工程师单方面的工作效率,下一步是思考如何提高整体团队的效率,也就是在前后端协作开发过程中遇到的问题。最典型的就是前端逻辑依赖后端接口的实现进度,这种串行的工作流程对于开发进度的影响是非常大的。所以,接下来首当其冲的便是解决前后端工程师并行开发的问题。

第二步:加入本地开发服务器

本地开发服务器并不是工具,而是一个真正意义上的Web服务。本地服务器最典型的应用是Mock服务,通过提供模拟接口和数据解决前端JavaScript对数据API的依赖问题,从而实现前后端并行开发,前提是前后端工程师在进入开发阶段之前需要协商制定接口API的详细规范。

对于一些有云Mock服务器的团队来讲,本地服务器甚至可以不提供Mock服务。但是如果项目需要SSR(Server Side Render,服务器端渲染)并且本地服务器与服务器端使用相同的编程语言,本地服务器还应该具备HTML模板解析功能。这样,前端工程师负责View层的开发工作,后端工程师负责服务器端逻辑开发。这种模式对Mock服务有了额外的需求——提供服务器端渲染的页面初始数据。云Mock平台是无法完成此项功能的,这是本地 Mock 服务独有的优势。所以,不论项目是否需要SSR,我们都建议将Mock服务集成到本地开发服务器。即使你的团队有云Mock服务,本地的Mock服务也可以使用代理模式将请求转交给云Mock服务。

由于所有的客户端相关资源(包括Views)均交由前端工程师负责开发,后端工程师不需要对前端工程师产出的文件进行二次处理,只进行一次支付便可部署,因此可以使用Git、SVN等版本管理工具替代人工交付,对代码回滚提供了更严谨的技术支持。

此外,本地服务器与构建功能相结合,可以提供动态构建、浏览器自动刷新等功能,这进一步提高了前端工程师的工作效率。

综上所述,本地服务器须具备以下功能。

● Mock 服务。如果团队具备统一的云 Mock 平台,本地服务器可以不提供Mock服务。但如果需要支持SSR,则必须提供本地Mock

试读结束[说明:试读内容隐藏了图片]

下载完整电子书

若在网站上没有找合适的书籍,可联系网站客服获取,各类电子版图书资料皆有。

客服微信:xzh432

登入/注册
卧槽~你还有脸回来
没有账号? 忘记密码?