可能很多人和我一样, 首次听到"前端架构"这个词, 第一反应是: "前端还有架构这一说呢?" 在后端开发领域, 系统规划和可扩展性非常关键, 因此架构师备受重视, 早在开发工作启动之前, 他们就被邀请加入到项目中, 而且他们会跟客户讨论即将建成的平台的架构要求, 使用还什么技术栈? 内容类型是什么? 这些内容如何被创建?软件架构师的职责就是要保证项目中每一步都在总体架构的指导下进行, 而不会随机决定.
现在的前端领域, 随着JS框架, UI框架和各种库的丰富, 前端架构也变得十分的重要. 如果一个大型项目没有合理的前端架构设计, 那么前端代码可能因为不同的开发人员随意的引入各种库和UI框架, 导致代码量变得异常臃肿, 最终结果可能是代码变得无法维护, 页面性能低下,不得已只能推翻重构. 所以我们需要在项目开始前, 同样的需要对前端代码进行架构, 一旦前端架构师设计出所有前端开发人员都要遵循的检验机制, 建立起系统设计的规范, 那么项目就拥有了可以衡量代码质量的标准, 前端开发人员也能享受到更高效的工作流. 所以, 前端架构的定义可以用以下一句话来总结:
前端架构是一系列工具和流程的集合, 旨在提升前端代码的质量, 并实现高效, 可持续的工作流.
本系列的前端架构文章, 将分别围绕前端架构的四个核心展开, 分别是代码, 流程, 测试, 文档.
前端架构的四个核心
(一) 代码
归根到底, 所有的网站都是由一堆文本文件和资源文件组成的. 当我们面对制作网站所产生的大量代码时, 就会发现为代码和资源设定一个期望是多么重要. 在代码部分, 我们会专注于如果实现系统架构中的HTML, CSS, JavaScript.
(二) 流程
现在早已过了FTP上传文件的时代, 那么现在重要的是思考怎么用工具和流程构建一个高效且避免出错的工作流. 工作流变得越来越复杂, 那些用于它们的工具也同样如此. 这些工具在提高生产力, 加快效率和保持代码一致性上带来了惊人的效果, 但也伴随着过度工程化和抽象化的风险. 所以, 现有的工作流是需要改变的.
(三) 测试
要构建一个可扩展和可持续优化的系统, 必须保证新代码和老代码能够很好的兼容. 我们的代码不会独立存在, 它们都是大型系统中的一部分. 创建覆盖面广泛的测试方案, 能确保老代码还能正常运作.
(四) 文档
一般而言, 如果不是团队中的重要成员要离开, 我们几乎都不会意识到文档的重要性. 等到那个时候, 大家将不得不停下手头的工作, 优先编写所有的文档. 作为前端机构师, 你要善于在项目开发的同时编写良好的文档.
流程核心
现在的前端工作流程已经发生了很大的改变, 最开始的Web开发阶段, 一般的工作流程是根据邮件交流来理解客户的需求, 然后通过FTP登录他们的服务器, 对网站代码做必要的修改. 这种做法是非常不成熟的. 如果误解了邮件的内容, 改错了代码, 会发生什么呢? 如果修改了一部分css代码, 导致破坏了很多页面的布局呢? 如果我改掉一个JavaScript的bug, 但又引发两个bug呢?
经过多年的项目开发, 现在已有了一整套成熟的开发流程, 一般公司的开发流程为以下几个步骤:
- PM(产品经理)提出需求,并和开发人员讨论需求的具体细节和可行性
- 需求确定之后, 发布出原型图和需求文档
- 开发人员根据原型图和需求文档进行开发, 前端还需要UI(网页设计人员)提供设计图, 项目总监使用JIRA等项目管理工具来跟踪工作流
- 搭建测试环境来测试代码, 开发人员完成功能开发并自测通过后, 提交给测试人员进行测试
- 测试人员和需求方通过后, 将代码合并到远程的master分支, 并部署上线
下面将分别从每个步骤讨论其它们在现代化开发流程中的必要性:
(一)需求
提出需求是进行开发的初始工作, PM提出了明确的需求后. FE(前端开发人员)才能进行开发. 当然, 互联网行业中对于提出需求是否需要开发人员参与讨论是有不同的争议的, 有的人认为让开发人员参与需求阶段, 可能会因为开发人员的技术认知水平和惯性思维等因素, 限制PM提出一个有创意的需求. 也有的人认为应当让开发人员参与需求讨论, 因为可能因为PM完全不懂技术, 导致提出根本无法实现的需求.
毫无疑问, PM比起开发人员更加懂得需求, 因为他们会在告知开发人员需求之前完成需求收集, 需求描述, 需求全景图, 需求分析, 用户故事等一系列专业化的工作 . 但我赞同开发人员同时也在需求上能有一定的话语权, PM在需求表达阶段让UI, FE, BE(后端开发人员)参与讨论, 不仅能让开发人员更好的理解需求, 也可能让PM发现一些忽视的点, 从而更好的提出一个完整的方案.
(二)原型
原型图是现代开发流程中不可或缺的一环, 它对于项目中的每个角色都有着重要的意义:
- PM进行需求验证的方式: PM在使用Axure画原型图的过程也是自己构思产品的过程, 经过原型图能够使得PM更加的理解产品.
- 给需求方确认需求的工具: PM理解的需求可能和需求方的需求是有出入的, 设计出原型图作给需求方来验证需求的正确性是十分必要的.
- UI设计出设计图的依旧: 原型几乎有了整个界面的雏形, 拿到原型图后, UI能够更好的根据原型图和PM讨论其设计样式, 更快的交付出设计图给FE, 极大的降低了沟通成本.
- 开发人员开发的依据: 初级的前端可能只会拿着设计图进行切图, 很可能切完图之后, 发现功能完全添加不进去的情况. 有经验的前端都会同时拿着设计图和原型图进行开发. 通过设计图在写
html
和css
的同时通过原型图去写js的业务逻辑部分. 同时, 原型图也是后端开发人员提供业务接口的依据. - 测试人员测试的依据: 作为一个现测试人员,可以从原型快速了解产品的核心功能,和页面大致展现形式,方便测试人员提早了解需求,评估需求,制定测试计划,分配测试任务,然后各自开始编写测试用例
可以说, (一)(二)步骤是前端开发人员进行开发的前提, 原型其实也是为项目中各角色更好的理解需求而服务的. 下面, 我以一个例子, 来解释一下什么叫做真正的理解需求.
需求场景假设
加入现在有个论坛的项目, 产品经理小C提了个需求"给论坛增加评论功能". 作为前端工程师的小A接到需求后, 该如何高质量的完成这个需求?
- 项目名称: 兴趣论坛
- 项目主要成员: 前端工程师小A, 后台工程师小B, 产品经理小C
- 产品需求: 给论坛增加评论功能.
此时, 小A接到需求后, 脑海里可能浮现的是下面这张图:
需求明确和需求确认
可能一些同学听到需求后, 就着手开始进行开发了. 不就一个简单的评论功能吗? 一个<textarea>
, 加个<button>
, 在引入jQuery进行ajax
提交和DOM
的操作就搞定了. 作为一名有经验的前端开发人员,要明白的是实际的项目并不是像写demo那么随意, 我们写出来的代码是要部署到线上环境给用户使用的. 所以, 面对"给论坛增加评论功能"这样的不明确的需求,是还需要进行需求明确和需求确认的.
1. 需求明确
想想我们平时在论坛或者微博里面见到的评论功能, 就真的是上图所显示的这么一个简单<textarea>
和<button>
就能够搞定的吗? 是不是评论可能还有以下的功能:
- 是否需要支持富文本输入?
- 是否需要支持微博, 微信朋友圈, qq空间的评论分享
- 发表评论后, 评论如何展示?
也许经过一番需求明确, 最终的需求会是下图所示. 所以遇到需求不明确的情况, 一定要明确具体需求, 避免后期无意义的返工和延期.
2. 需求确认
需求已经明确了, 需要支持富文本输入, 需要暂时评论, 这就足够了吗? 其实不够, 作为一个有经验的前端开发人员, 还有很多的细节需要确认, 比如:
- 评论最大支持输入多少个字? (非常重要, 关乎后台存储方案的设计)
- 一个中文字符算1个字, 还是2个英文字母算一个字? (产品语言, 技术语言之间的沟通转换)
- 输入内容过长, 如何进行错误提示?(交互细节)
- 输入内容过长时, 是否运行提交评论? 如允许, 是对评论内容进行截断后提交?(容错机制)
- 用户未输入内容的情况下, 评论框内默认提示文案是什么?(交互细节)
- .......
一个评论功能可能需要明确的需求有很多, 这里就不在更多的赘述了, 从这个例子可以看出, 如果不是十分懂技术的PM, 是很难提出一个明确的需求的. 所以作为开发人员的我们, 在明确了需求之后还需要进行需求确认, 而且可能是反复的进行需求确认.
(三)开发
1. 本地部署
如果公司没有一套标准的本地部署流程的话, 那么它会成为你敲代码前花费较多时间的一个部分, 可能包括拉取多个代码库, 配置服务器设置, 修改本机host或设置VPN. 不管流程是什么, 请一定要确保在README.md文件中说明每一步所对应的操作, 确保新的工程师能够很快的通过git clone xxx
代码之后, 就能够将代码在本地运行起来. 千万不要低估README.md文件的重要性, 一个清晰的README.md文件可以让一个新入职的工程师在Git的远程仓库上拉代码之后几分钟就能运行起来. 当然, 对于一个依赖较多且配置项繁琐的项目, 如果缺少一个清晰的README. md文件, 花费几天的时间才在本地环境跑起来也是不足为奇的.
2. 创建功能分支
在多人开发的项目中, 是绝对不允许你直接在master分支下进行开发的, master分支有且只能用作保存上线版本的代码, 在开发过程中, 应该针对每个功能点通过git checkout -b newBranchName
来创建一个新的功能分支, 在该功能分支上将该功能开发完毕并在本地进行了自测之后, 再将该功能分支merge
到dev分支上, dev分支主要用来合并功能分支代码并交由测试人员进行测试, 当本次迭代所有的功能测试完毕之后, 才能够将dev分支上的代码merge
到master分支上, 并准备上线.
3. 使用自动化工具(Gulp, Webpack等)
如果有一定工作年限的前端开发者, 那么一定经历过从Grunt转移到Gulp, 并在近两年转移到Webpack的过程. 这类的自动化工具, 能够极大的优化我们的工作流程, 帮助我们高效率的完成类似于自动刷新页面, 压缩CSS, JS和合并压缩代码等机械重复的体力活. 对于自动化工具对于开发人员的优点, 我看过下面这样一句话说得很好:
每件事都是一个程序, 开发也像程序一样, 每个步骤都是一段代码, 当开发规模随着文档, 代码, 需求而增加时, 重复的步骤变得越来越多. 此时, 如果可以像抽象代码一样抽象出一些相同操作就可以大大提升开发效率. 因此, 出现了更多优质的工具来代替人工做一些不断重复的开发以减少程序员的工作量.
目前前端领域应该使用得最多的两个自动化工具就是Gulp和Webpack. 这两者在功能上有一定的区别, Gulp是一个自动化构建工具, 你可以通过丰富的插件在项目中自动的帮你执行常见的任务. Webpack是一个自动化打包工具, 通过一个入口文件, 将所有依赖的模块打包成为一个js文件, 当然你也可以通过code spliting将其切分为多个js文件, 按需加载以提高效率.
目前主流的前端框架(Vue, React和Angular)都是使用的Webpack进行打包, 就目前的使用来看, 通过各种loader和plugins, 几乎webpack能够满足所有的项目需求. 在前端架构中, 由于项目工程化的要求, 使用gulp和webpack这类的自动化工具进行项目的构建是必须的.
(四)测试
测试是项目把关的最后一个环节, 经过了测试员这关才能把项目进行验收上线. 现在国内的网络公司由于项目工期的要求, 对于测试这一块, 大部分的做法还是雇佣能力水平一般的测试人员, 通过重复点击运行项目流程的方式进行测试, 对于测试工具的使用较少. 目前其实已经有了一批成熟的js测试工具, 例如Jasmine, Karma, Mocha, NightWatch.当你开始为应用程序规划测试时, 请记住以下几条建议:
- 测试用例应该在建站的同时, 甚至在建站之前就开始编写
- 测试代码是真实的代码, 应该一起或立即提交到系统代码库中
- 必须在所有的测试用例通过后, 才能把代码合并到主干中
- 在主干上运行测试工具, 结果应该都为通过才能上线
前端自动化测试的细节将在下一篇的文章中做详细的探讨, 这里我们只是强调测试在整个项目流程的必要性.
(五)上线
在测试通过之后, 一个项目的最后流程就是上线了. 上线时采用JenKins这类的持续集成工具进行代码部署是一个优秀的架构所必须的, 持续集成工具能够在代码发布到服务器前, 先对代码进行一些处理, 这意味着我们可以在Git上忽略那编译后的资源. 以Vue的项目举例, 我们上线前只需要将在dev上测试通过的代码merge到master分支上, 在上传到远程Git仓库中. 在使用Jenkis进行部署上线就行, 一旦配置过上线前的处理流程, Jenkins就能自动帮我执行npm run build
的操作并将build
好的dist文件夹自动部署到服务器上.
友情链接
- 前端进阶之路: 前端架构设计(1)-代码核心
参考资料
- 前端进阶之路: 如何高质量完成产品需求
- 产品原型的重要性
- 原型设计是什么, 该怎么使用它?
- 改进我的前端工作流