Sapper

2021年02月18日

谈谈前端工程化


在写这篇文章前,我有去掘金和知乎上看别人对前端工程化的理解,各自各样的都有,但是没有一篇跟我想的一样。不知道我理解的是不是错的,总之我想把我此时此刻的想法记录下来,等多年以后见识多了再回头来验证。

前端工程化的由来

随着项目做的越来越多,你会发现其实工作中存在着很多重复的工作。于是你就开始不断的做封装,提升代码复用性,降低重复的工作。

封装的程度可大可小,大致分几个层次:

  1. 函数封装、代码逻辑封装、组件封装
  2. 通用组件或通用工具类封装
  3. 脚手架工具、模板生成工具
  4. 项目管理系统

但即使做到第 4 阶段还是不够,这只是在开发阶段提供便利,其他方面并没有得到提升,比如发布、部署也是一个繁琐的过程。随着前端技术逐渐成熟,整个前端项目体系不断完善,由此形成了前端工程化体系。

前端工程化是什么

前端工程化是软件工程的一种实现,是为了提高效率和降低成本而存在的。前端工程化不是单从开发角度考虑,而是为整个项目生命周期各个阶段考虑。最近很流行的一张 DevOps 闭环图很能体现整个项目生命周期:

dev 开发阶段

  1. plan 制定计划
  2. code 编码
  3. build 构建
  4. test 测试

ops 运维阶段

  1. release 发布
  2. deploy 部署
  3. operate 运营
  4. monitor 监控

监控通常是为了完善系统,所以监控完下一步就是制定计划,形成闭环。前端工程化要做的就是让各个阶段能够更快的进行。

从前端角度去看,以上那些阶段将转化为:设计、开发、测试、部署、监控。

设计

处于 plan 阶段,在接到需求后进行需求分析、熟悉业务、任务拆解。对于新项目,还需进行架构设计。

架构设计

架构设计通常是根据业务场景做做技术栈选型、路由设计、项目结构设计。像业界一些热门词比如中台、微前端之类的可以在这阶段考虑要不要引入,不过要记住,任何技术的引入都需要充分考虑业务场景。任何一项技术架构都没有厉不厉害、好不好用之说,只有合不合适的问题。

前端工程化在架构设计上的体现就是前端脚手架,就像 Vue 的 @vue/cli 一样,只要在终端运行命令行,项目结构就帮你搭建好了。然后再通过问答的方式,选出你想要的技术栈或者业务方案。就这样一套架构设计就完成了。

当然仅仅这样是不够的,@vue/cli 只会选出一些常用的技术栈和 Vue 相关的技术栈。公司都会自己沉淀一些技术,比如常用工具类和组件库。实际项目开发,也不仅仅是只有技术问题,还会沉淀一些业务方案。

总的来说,公司应该要有属于自己的一套脚手架,将多年沉淀的技术方案和业务方案集成在一套脚手架里。这样在架构设计阶段,就是一条命令行和几个问答就能解决了。至于如何有效的做技术沉淀就是另外一个问题,还有开发一个脚手架并不容易,最好是基于第三方的做封装才能有效避开很多坑。

需求分析

理论上每次有新的需求都应该做需求分析,至于如何做需求分析,我还没找到有什么有效的方案。但至少要做到熟悉需求、熟悉业务,了解为什么会有这样需求出现。只有从业务的角度看需求,你才能预知未来可能会做怎样的需求变动,在代码上就能提前做防患。

在这阶段还要有个重要的环节,就是做任务拆解。很多人拿到原型后,就从头到尾一个一个页面做下去。又或者根据业务流程顺序,一个一个页面做下去。大多数人是以页面为单位做开发,这个在以往的 JQuery 确实只能这样,但在这组件化的时代,应该有更有效的方式。

以页面为单位做开发会有个现场,就是容易出现重复造轮子的现象,A 页面做了,B 页面又做了一遍。要是不同人开发,就是开发两遍。要是同一个人开发,很多人就开启 CV 大法,复制粘贴改一改就完事。不仅浪费时间,代码质量也下降,更重要的是你又错失了一个沉淀技术的机会。经常听到有人说 “现在项目那么赶,先复制粘贴下,后面有空再来优化代码”,可结果能有几个人会改,下一个任务还在等着你做。这种现象的问题根据是任务分配不合理造成的,如果你的任务就只是封装这个组件,而不是做这个页面,你肯定会好好对待。

一块需求的开发,应该是包含一个任务叫任务拆解。这个任务就负责分析各个页面的异同点,和根据业务需求预知后续可能出现页面。然后拆分为组件开发、逻辑开发、页面开发,这边的页面开发应该是分析完的不可拆分的页面,或者各个组件和逻辑的组合拼凑任务。

开发

处于 code 阶段,是写代码的阶段,写出的代码被称为开发环境的代码。这阶段主要注重的是如何更快的完成系统开发,也就是提升开发效率。在实际项目开发过程中,时常会因为需求变更而需求修改原来的代码,所以这阶段又注重代码可维护性。

提高开发效率

这方面在前端工程化里面主要做两件事情:编译、预览,其他都是特定场合或特定技术栈做的事。

  • 编译:ES6+ 代码转为 ES5 代码,或者引入一些插件做代码转化。
  • 预览:让项目在浏览器上跑起来,页面热更新处理。

通常都会借助一些构建工具来完成,比如 Webpack、rollup、vite。每一种构建工具都有各自的优势,具体使用哪种应该是由业务场景决定的。选择更合适的构建工具主要是为了提升编译速度,为了能够更快看到页面效果。

提高维护性

这方面在前端工程化的体现就是规范化:代码规范化、接口规范化、文件结构规范化等等。用规范化来让所有开发者保持相同的编码风格和组织方式,这样一来查找文件和修改代码就会更加迅速。最常见的就是使用 ESLint 做代码规范化。强制让所有人的代码风格保持一致。

测试

这阶段包含 codetest 阶段,这边的测试不是测试工程师做的测试工作,而是前端做单元测试和集成测试。在前端工程里,test 可以在 build 之前执行,针对于开发环境的代码做测试。用于测试的代码也需要编写,所以也包含在 code 里。

很多公司在这个阶段是采用人工测试,人工测试通常是不靠谱的,容易漏掉一些业务细节。使用单元测试和集成测试就会逼着你编写测试方案,考虑得会更加全面。最重要的是能保留当前测试方案,将来需求变更或者重构代码时才不容易遗漏需求,有效降低 bug 量。

部署

这是 buildreleasedeploy 综合起来的阶段。到这阶段就说明系统现阶段的功能已经开发完成了,下一步就是发给测试工程师做测试工作。测试工程师通常会有自己的测试环境,会将系统部署到测试环境才能进行测试。所以这个阶段就是完成系统构建、软件包发布、将包部署在测试环境上。

前端工程化在这方面已经有比较完善的方案了,就是自动化部署。例如 GitHub Actions ,使用 Github 管理项目,执行 git push --tags 推送源码上去就会自动帮你执行这一系列部署操作。公司内部项目可以使用 GitLab 也有类似的功能。

部署之前有个构建工作,将代码构建成生产环境的软件包。这过程与开发类似,需要借助 Webpack 之类的构建工具完成。与开发不同的是,开发注重的是编译构建速度,而这阶段注重的是代码体积尽可能小。为了让最终的软件包体积尽可能小,在设计阶段的技术选型环节就要考虑好。

监控

这个现在还没什么想法,后续补充!

总结

前端工程化包含很多阶段,每个阶段都是作用于项目,所以通常会在 npm scripts 上体现:

{
    "scripts": {
        "start": "webpack-dev-server --mode=development",
        "build": "webpack --mode=production",
        "lint": "eslint --ext js,vue src",
        "test": "jest",
        "deploy": "git push --tags"

    }
}

你也许会看到这样的 npm scripts ,也许会更多。这边不讨论如何定义 npm scripts ,这边想说的是每一个阶段的实现,都是通过执行一条条命令行来触发,创建项目也是通过命令行创建。所以前端工程化的都是建立在 NodeJS 平台和 npm 体系,命令行工具的开发就成为了前端工程化的基础。后续有机会再写在命令行工具的相关文章。

以上是我的一些拙见,如果有哪个地方说得不对的话,欢迎来提 issue


Maxi Ferreira

你好!我是诀死行者,一个专注于研究诀死 (JS) 功法的修行者。很高兴在修行的路上有你的陪伴, 你可以到 GitHub 观摩我的修行成果, 也可以到我的网站查阅我的修行笔记。