【阿豫DEEP】前端工程化建设

233 阅读11分钟

一、前言

前端工程化的提法有很多年了,已经是每个前端团队必要的基础设施,社区有很多文章,看起来很多人理解都不一样,也有一些很优秀的开源框架。但前端工程化绝对不等同简单的创建、调试、构建等流程,而是一个体系化、标准化的工程系统。

在这里我也根据自己的经验以及在团队中的实践来说下我理解的前端工程化。本文不讲具体的实现,主要从工程化的本质思考,从前端的需求出发来简单聊下做什么样的工程化。篇幅有限,以及牵扯到涉密问题,很多功能点细节讲不到,还请铁子们谅解。

二、思考

2.1 什么是工程化?

工程化是一种遵循一定标准与规范,通过工具和技术手段提高效率、降低成本、保证质量的管理模式和方法论。

从这个概念的表诉中可以提炼以下关键点:

image.png 这几个关键点虽然非常抽象,但是很精准的解释了工程化的意义。

2.2 前端为什么需要工程化?

早期的Web开发环境相对简单,页面功能单一,交互性较弱,前端代码量小且直接嵌入到后端模板中或者无需编译直接部署,这种模式在一定程度上能够满足当时的需求。但在现代模式下随着业务的爆发式增长和各种技术和工具层出不穷,也给我们带来新的挑战,主要表现在:

2.2.1 多语言与多框架

目前前端发展出很多开发语言( es6及其以上版本、typsscript、nodejs、less等)和开发框架(react、vue)以及新特性,每种组合都有特定的应用场景,在方便开发的同时为了支持大部分浏览器,需要把代码转译为适配大部分浏览器都代码,这就牵扯到代码编译过程。

2.2.2 模块化与产物多样性

基于不同的场景和应用,需要面对多模块(AMD, CMD, CJS, EJS模块)和多产物(组件库、插件包、Web页、H5页、低码页)的实现,开发一套灵活且兼容性强的构建系统显得尤为重要。

2.2.3 多项目并行与多人协作

随着业务需求的多样化,企业往往同时推进多个项目,团队成员需要协作进行开发,如何保证团队成员研发体验一致,高效率开发、高质量配合,实施高效的CI/CD流程是面临的核心挑战。

综上所述,前端工程化的兴起,是技术进步与时代需求交织催生的必然结果,通过标准化流程、自动化工具的引入,前端工程化不仅解决了技术复杂性带来的挑战,也为团队协作、持续交付、质量保证等管理层面的问题提供了有效的解决方案。

2.3 前端工程化解决什么问题?

image.png

2.4 前端需要什么样的工程化?

前端需要什么样的工程化,关键是好用,好用可以从以下几个指标来论述:性、效率以及对团队工作的支持程度。以下是一些常用的评估指标:

2.4.1 功能性

工程化工具需要提供了全面且必要的功能,以满足不同项目阶段的需求,如项目创建、调试、编译、部署、自检、CI/CD等能力。

2.4.2 易用性

  • 开箱即用:容易安装、安装之后即能使用。
  • 学习曲线:学习曲线平缓,容易上手,详尽的使用文档和教程。
  • 易操作:一条命令解决问题。

2.4.3 排障

  • 异常内容:异常内容需清晰明了且看的懂。
  • 异常定位:报错内容准确描述准确、报错文件的位置能够定位、不同颜色区分不同的报错内容。
  • 异常解决:最好根据异常内容自动给出解决方法或建议。

image.png

2.4.4 用户体验

  • log日志:首先日志要简洁且必要,无需把所有的日志都打印出来,可以设置debug开关控制是否显示全量日志。
  • 响应速度:命令执行完之后,可快速响应,若需要一段时间,可设置进度条提示。
  • 自动化程度:工具支持高度的自动化操作,如自动化测试、自动化部署等,以提高工作效率。

image.png

2.4.5 高可用

  • 兼容性:需要满足当前占比80%的依赖包、开发语言、开发框架、浏览器、node环境等。
  • 稳定性:工具在运行过程中是否稳定可靠,不易出现崩溃或错误。
  • 容错机制:工具是否具备强大的容错机制,能够在出现错误时提供恢复方案或自动修复。

2.4.6 高扩展

  • 可配置:通过配置实现工程能力的定制。
  • 可扩展:通过插件扩展、命令扩展等机制实现自定义能力。
  • 插拔能力:可实现开关实现某些功能和插件的开启或关闭。

2.4.7 规范性

  • 解决方案规范:通过解决方案规范使得工程能力和解决方案能够按照规范执行。
  • 插件规范:通过插件规范使得在能力扩展上能够各个插件能够有机统一。

三、前端工程化要怎么做?

3.1 框架图

先来一张框架图

【阿豫DEEP】前端工程化建设-流程图.jpg

整个工程化主要服务的载体是解决方案,对外暴露若干命令,通过命令可以执行响应的工程能力。同时通过扩展能力可以实现工程能力的扩展。

具体的执行流程请看下图

image.png

3.2 规范/标准

做任何系统和架构首先要标准规范先行,可以确保项目长期可持续性、可维护性、可兼容性。

标准/规范同时也制定了整个系统能够有机运行的基本接口和框架。

3.3 解决方案

目的

通过解决方案快速帮助研发标准落地,提升研发效率。同时有自定义的解决方案也方便统一接入到工程化框架中。

手段

通过插件的形式收敛项目的各种标准和能力,达到各个项目在标准和能力的接入和使用上达到统一,以及插件管理上的统一。

标准规范

解决方案主要分为两部分:工程配置 和 最佳实践

  • 工程配置
{
  solutionPlugin: string,// 解决方案配置可以抽象为一个插件
  plugins: any[],// 工程插件
  runTime: () => {}, // 运行时
  buildTime: () => {}, // 构建时
  config:{[s]: string}, // 工程侧配置 
}
  • 最佳实践目录
qt-solution-web
├─ .vscode						// vscode 配置
│    ├─ extensions.json
│    └─ settings.json
├─ src							// 代码
│    ├─ common					// 公共文件夹
│    │    ├─ assets				// 资源
│    │    ├─ components			// 组件
│    │    ├─ configs			// 配置
│    │    ├─ hooks				// hooks
│    │    ├─ layouts			// 布局
│    │    ├─ constants			// 常量
│    │    ├─ types				// 接口类型声明文件
│    │    ├─ store				// 全局管理
│    │    └─ utils				// 工具函数
│    ├─ pages					// 页面
│    │    └─ index
│    ├─ App.less
│    ├─ App.tsx					// 应用入口文件
│    ├─ index.tsx				// 应用初始化文件
│    └─ routes.tsx
├─ .editorconfig
├─ .eslintignore
├─ .eslintrc.js
├─ .gitignore
├─ .markdownlint.json
├─ .markdownlintignore
├─ .prettierrc.js
├─ .stylelintignore
├─ .stylelintrc.js
├─ README.md
├─ commitlint.config.js
├─ f2elint.config.js
├─ solution.js					// 解决方案配置
├─ package-lock.json
├─ package.json
└─ tsconfig.json

3.4 插件

目的

使插件在接入和使用上能够统一,插件之间有机结合形成合力,作为解决方案某种能力的载体,可以集成到解决方案。

手段

通过统一的插件规范,实现插件的标准化、体系化。

标准规范

  • 运行时插件
export interface Iplugin {
  pluginName: string; // 插件名字
  addParams: any[]; // 注入参数
  apply: (context: IContenxt) => Promise<any>; // 插件执行入口
  runTime: () => {}, // 运行时
  run: () => void; // 独立安装时启动插件
}
  • 构建时插件

export interface Iplugin {
  pluginName: string; // 插件名字
  addParams: IAddParams; // 注入参数
  apply: (context: IContenxt) => Promise<any>; // 插件执行入口
  buildTime: () => {}, // 构建时
  config:{[s]: string}, // 工程侧配置 
}

3.5 工程能力

工程化对外输出的形式是以命令的形式存在的(例如:qtcli dev),命令参数是工程能力定制化的重要途径。基于研发生命周期大概分为这几个命令:

3.5.1 项目创建(Init)

项目创建阶段,以Init命令为核心,标志着生命周期的起点。它不仅仅是一个简单的文件夹结构生成操作,而是涵盖了对多种项目解决方案类型的全方位支持,实现项目的本地化,全链路初始化。通过这一流程可实现团队项目的标准化。

image.png

3.5.2 项目调试(Dev)

进入开发调试阶段,Dev命令扮演着关键角色,通过参数差异化构建,实现了开发环境的个性化与灵活性。该命令能够依据开发者设定的不同参数,如启用https、启用mock数据、绑定端口域名等。

image.png

  • 差异化构建

同时对于多页项目可以选择要构建的页面,节省构建时间

image.png

3.5.3 项目构建(build)

构建阶段代表这产物的生成,产物的大小、类型、环境等需要根据具体的情况而不同。

  • 参数

image.png

3.5.4 项目校验修复(Lint)

在持续集成和代码质量管理中,Lint命令是不可或缺的一环。它依据预设的编码规范和最佳实践,对项目代码进行全面检查,及时发现潜在的语法错误、代码风格不一致或性能瓶颈等问题。通过自动修复建议或直接修正简单问题,Lint不仅提升了代码质量,也促进了团队间的编码规范一致性,加速了代码提交到合并的流程。

3.5.5 项目发布(publish)

最终,当项目经过充分测试验证后,通过Publish命令完成软件的版本发布。此命令负责自动化处理版本控制、构建产物上传至分发渠道、文档更新等一系列发布前后的必要操作。支持多渠道分发、自动版本号管理,确保发布过程既安全又高效。此外,集成日志记录和通知功能,让团队成员能实时跟踪发布状态,迅速响应可能的发布问题。

3.6 扩展能力

由于前端需求多变,存在差异,所以拥有强壮的扩展能力是前端工程化确保项目长期可维护与灵活性的必备的能力。想要具备平稳的扩展能力就需要在设计之初做好标准和规范的设计。所以在这里我们主要是根据解决方案、插件规范进行扩展。

3.6.1 方案扩展:标准化接入,灵活应变

方案扩展的核心在于建立一套清晰、可复用的解决方案框架,允许开发者根据特定场景轻松接入工程化体系。这要求在设计阶段就确立一套解决方案标准,确保新解决方案能够无缝融入现有体系。包括实现解决方案的接入、下载、本地化、初始化等流程。

3.6.2 插件扩展:遵循规范,即插即用

插件机制是提升前端工程化灵活性的重要手段。通过定义明确的插件接口和生命周期管理策略,开发者可以依据统一的插件规范开发功能模块,这些模块能够不侵入主系统增强或修改其行为。比如更改默认流程、插入新的流程等。

3.6.3 命令扩展:自动化流程,提升效率

命令行工具的扩展能力让开发者能够自定义一系列操作,如初始化项目、生成组件模板、部署应用等,极大地提升了开发效率。例如,开发一个“add-page”命令,自动创建包含必要文件和目录结构的新页面模板,减少重复工作,保证代码一致性。

3.6.4 配置扩展:定制化配置,满足多元需求

配置的扩展性是前端工程化中的核心能力。允许开发者根据自身需求调整构建流程、优化策略、环境变量等,是应对复杂多变场景的有效方式。比如利用Webpack的配置能力,可以轻松实现按需加载、代码拆分、资源压缩等功能的定制;利用插件配置可以实现插件的插拔,参数透传等。

综上所述,前端工程化的扩展能力是通过标准化的解决方案、规范化的插件体系、便捷的命令行工具以及灵活的配置机制共同构建的。不仅增强了项目的可扩展性和可维护性,也为开发者提供了更加高效、个性化的开发环境,是推动前端项目持续演进与创新的重要基石。

四、总结

工程化不是简单的脚手架,而是标准化、系统化的工程系统;不是仅仅支持项目的构建调试,而是需要为整个研发提供能力支撑。就像汽车底盘一样,为传动、行驶、转向、制动等提供能力支持。工程化不是一蹴而就的,而是不断演进优化的,所以需要一个标准化规范化的设计支撑。