服务器 频道

百度日志中台前端重构实践

  日志中台是百度内部针对打点数据的全生命周期管理平台,作为公司日志数据的唯一入口,承担以下核心职能:1.功能覆盖:提供从数据采集、传输、存储到查询分析的一站式服务,支持产品运营分析、研发性能监控、运维管理等多元场景。2.业务赋能:通过标准化流程实现用户行为日志的埋点申请、审批及退场管理,助力APP端、服务端等业务线挖掘数据价值。3.生态协同:与大数据平台、推荐中台、性能平台深度联动,避免重复建设,提升资源利用率,强化业务中台能力。

  01 项目背景

  2020年初启动的日志中台前端项目,随着业务发展逐渐暴露出严重问题。整个前端项目技术负债多,有500多个文件,共11万多行源码。项目已经变得老旧而臃肿。面临线上bug频发、排查问题效率低下等各种问题,陈旧的技术栈与低效的流程也制约了团队的生产力。因此需进行全面全面重构,通过基于业务导向的架构优化、开发测试流程规范化,从而提升前端开发效率,使项目具备长期稳健发展的技术基础。本文将重点介绍我在重构项目过程中的一些实践经验。

  02 前端项目面临的问题

  先介绍下日志中台前端项目的基本情况

  核心框架:Vue 2.6 + Vuex 3.1.1 + VueRouter 3.0.6

  UI组件库:ElementUI 2.15.13

  构建工具:@vue/cli-service 3.11.0(基于Webpack 4)

  部署平台:测试环境(FIS3)、生产环境(Tower)

  下面我将从4个维度来分析下前端项目所面临的各种问题。

  2.1 代码质量

  由于项目没有接入代码格式化 prettier 和 代码规范检查 eslint,导致项目的代码质量堪忧,各种各样的代码风格并存。在开发需求过程中,各自的编码风格不一致,维护时需额外适应时间,甚至由此引发线上问题。

  2.2 基础建设

  1. 代码臃肿,维护困难

  全项目500+源文件中,30+文件超1000行,5+文件超2000行,最大文件达5000行。

  巨型文件导致:

  IDE卡顿(Mac开发时频繁卡住)。

  热更新失效(>2s延迟,大文件需手动刷新浏览器)。

  2. 技术栈陈旧

  仍使用已停止维护的vue-cli(Webpack 4时代工具链),与现代构建工具(Vite、Webpack 5)存在代差。

  2.3 构建和部署

  测试环境

  测试环境的部署采用的是 fis3,这是百度FE团队早期自研的集构建、部署于一身前端构建工具,日志中台项目使用其部署测试环境的功能。具体流程就是在开发者本地执行打包操作,然后将打包产物通过fix3推送到后端的服务器上去,替换掉之前的打包产物,从而实现部署新版本。

  这种方式存在诸多问题:

  本地构建依赖不一致,易引发环境差异问题。

  无CDN缓存,静态资源直推后端服务器。

  无版本管理,存在代码覆盖风险。

  FIS3已停止维护,社区无支持。

  本质问题:前后端未完全分离,违背当前主流协作模式。

  生产环境

  生产环境的部署则采用的是Tower平台,这是百度内部的线上部署平台,通过平台的形式将master分支的代码在服务器上编译构建,将打包后的产物推送到线上环境对应的服务器上,从而实现完整的上线流程。这种上线方式同样存在诸多不足:

  上线耗时长达30分钟,无增量构建能力。

  多服务器部署时存在“漂移现象”(请求路由不一致)。

  操作流程复杂,平台限制多(如回滚困难)。

  仍缺失CDN加速,影响页面加载性能。

  2.4 优质组件

  在Vue技术栈中,模块和组件的模糊概念,导致很多开发者无法区分其区别。

  1. 组件与模块概念混淆

  src/components目录下堆积40+文件夹,但90%为一次性业务模块(如5个重复封装的Table组件),缺乏真正的复用价值。

  2. 基础建设缺失

  无通用业务组件库,开发依赖Element UI原始组件。

  高频逻辑(如表单校验、数据请求)需重复实现,通过“复制粘贴”开发,导致代码冗余和一致性风险。

  03 全面重构拆分

  下面是针对以上项目中的各个痛点的重构具体手段。

  3.1 接入工程化

  前端项目若缺乏统一的代码规范和质量控制,随着业务增长,代码可维护性会急剧下降,最终导致开发效率低下、线上问题频发。因此,引入业界成熟的工程化方案是提升代码质量的关键。  

  工程化改造步骤

  1. 清理冗余配置

  移除项目中无用的、过时的配置(如废弃的.babelrc、冗余的webpack配置等),减少干扰项。

  2. 统一基础配置文件

  在项目根目录下添加必要的配置文件,确保团队开发环境一致:

  .vscode/settings.json(统一VSCode编辑器配置)

  .editorconfig(统一缩进、换行等基础格式)

  .npmrc(设置为百度npm镜像)

  .browserslistrc(明确目标浏览器兼容范围)

  3. 接入代码规范工具

  Prettier:自动格式化代码,统一风格(如缩进、引号、分号等)。

  ESLint:检查JavaScript/Vue代码质量,避免常见错误。

  Stylelint(可选):规范CSS/Less代码风格。

  4. 优化开发体验

  推荐安装必要的VSCode插件(如ESLint、Prettier、Volar等),提升开发效率。

  5. 提交时增量强制校验(Git Hooks)

  接入husky+lint-staged,在git commit时自动执行代码检查,阻止不合规代码提交。

  配置参考:

  VSCode统一配置

  https://www.yuque.com/shuoshubao/bg00go/wc87bknptk3lomed#NStKP

  工程化配置方案https://www.yuque.com/shuoshubao/bg00go/wc87bknptk3lomed#SJTr2

  历史代码修复策略

  原则:“自动修复优先,手动修复补充”,避免无限制添加eslint-disable或ignore规则,导致规范形同虚设。

  具体执行步骤:

  1. 自动格式化(Prettier)

  2. ESLint自动修复

  3. 分析剩余问题

  使用eslint-formatter-html生成报告,评估剩余问题。

  调整ESLint规则(如放宽部分历史代码限制),拆解为多个小任务手动修复。

  4. 回归测试

  联合熟悉业务的同学进行全量测试,确保修复过程不影响系统功能。

  效果验证

  代码风格统一:所有新提交的代码均符合规范,减少风格争议。

  错误率下降:低级语法错误、边界条件导致的JS报错大幅减少。

  开发体验提升:IDE卡顿减少(格式化后代码更简洁),热更新效率提高。

  3.2 升级基建

  3.2.1 源码优化与依赖治理

  问题现状:

  项目存在大量技术债务,包括:

  冗余资源(未压缩图片约2M)

  无效依赖(22个未使用的npm包)

  混合模块规范(require/import混用)

  废弃技术栈(如已停止维护的iView)

  优化措施:

  1. 资源优化

  使用基于Tinypng封装的工具批量压缩图片,体积减少65%

  清理已下架页面的遗留代码(约15个路由)

  2. 依赖治理

  移除22个无用依赖

  统一使用ES Module规范(手动替换require为import)

  3. 技术栈升级

  替换老旧组件库:vue-json-diff、vue-code-diff、vue-codemirror 替换为 monaco-editor

  3.2.2 构建相关

  相对于以往的 Webpack 或者 Vue CLI,存在开发服务器启动慢(平均45秒)、热更新延迟高(2.5秒)、构建流程复杂(需Babel转译ES5)。

  Vite 配置详见:https://www.yuque.com/shuoshubao/bg00go/wc87bknptk3lomed#wyx0p

  接入Vite后,低配置电脑同学开发时的平均热更新时间由2.5秒缩短到100毫秒。在单个需求完成耗时方面,由之前的4.2人天缩减到3.4人天,综合人效提高19%。

  另一方面,由于 Vue CLI 是基于babel将esnext代码转成es5,而Vite基于esbuild不需要进行降级编译。在将 Vite 的配置 build.target 设置为 ['chrome100'] 后,甚至连非常新的esnext语法糖都不需要转换,浏览器直接可以使用前端的源码,极大的利用了esnext带来的开发便利,而不需要关注Babel的版本以及各种依赖包和复杂的配置。

  3.2.3 部署相关

  百度内部主流的部署平台是 Fcnap。这是一个类似Vercel的前端一站式部署平台,基于git分支,只要检测到分支变动,就会触发自动构建和部署。

  只需配置好各个测试环境以及生产环境的基本信息,后续在需要开发中,只需要将分支和测试环境关联起来,就可以达到随时提交代码随时部署的效果;上线过程更是丝滑,只需要将代码合到master分支,就会自动上线。

  将 fis3 以及 Tower 迁移到 Fcnap 后有如下优势:

  测试和生成环境使用一套部署逻辑

  上线部署耗时由30分钟缩减至2分钟

  提供cdn功能,每次上线后增量更新的静态资源只有500kb

  上线期间访问系统不会出现白屏现象

  上线过程对用户无任何影响

  3.2.4 接口调试

  传统开发模式的痛点

  在传统前后端协作中,存在典型的"接口依赖症":

  1. 开发阻塞:前端必须等待后端接口Ready才能开始调试

  2. 效率低下:联调阶段频繁出现接口变更,导致重复返工

  3. 数据不可控:依赖真实测试环境数据,难以覆盖边界场景

  数据表明:在接口未就绪阶段,前端开发效率会下降60%以上

  真正的"前后端分离"实践

  核心原则:开发阶段解耦,联调阶段对接

  1. 规范先行:

  后端通过YAPI等平台提供完整的接口文档

  包含:请求方法、参数结构、响应体示例、状态码定义

  2. Mock数据要求:

  真实业务数据(非简单根据接口文档生成各种随机数据)

  可自定义异常场景(404, 502等真实场景还原)

  支持动态响应(根据参数返回不同数据)

  针对这个开发环节,我们也基于Vite实现了一个非常好用的插件:vite-plugin-mock,用于提升开发效率。整体的设计如下:  

  相比于传统的 mock 方案,vite-plugin-mock在开发体验、数据维护上有更好的开发体验。

  3.3 构建体积优化

  这一部分主要从以下三个技术方案着手优化,再配合其他人工优化手段,打包体积由开始的 14M 优化到 1.8M,接入cdn功能后,则仅有500kb。

  3.3.1 element-ui

  fork element-ui 源码, 采用rollup进行打包,优化部分源码,修复部分 bug,重新发包为 @baidu-log/element-ui

  这一步骤,js 体积从 1.2M 优化到 500kb。并结合下面 externals 功能,进一步使用cdn功能缓存这部分文件体积。

  3.3.2 引入externals功能

  将基础包通过cdn的形式在 index.html 模板中引入其umd格式的文件,从而避免打包这部分内容。这部分会用到cdn的缓存功能,会节约掉大约 2M 的体积。

  vite-plugin-externals

  这个是开源的vite插件,配置也比较简单,详见配置:https://www.yuque.com/shuoshubao/bg00go/wc87bknptk3lomed#LiR2X

  vite-plugin-assets

  这个是为了配合上面vite-plugin-externals插件,将对应的externals的npm包对应的umd文件插入到模板中,代码详见:https://www.yuque.com/shuoshubao/bg00go/wc87bknptk3lomed#xts88

  为什么不直接写在 index.html 里呢?因为像 vue 和 react 这样的框架,在开发时都提供了对应的开发调试工具:dev-tools。而使用 dev-tools 则需要提供对应的 dist/vue.js,而react对应的则是 react.development.js。

  3.3.3 大包的特殊处理

  1. monaco-editor

  项目中用到了 monaco-editor 这个编辑器组件,直接打包将会非常大,有10M以上的体积。根据官方提供的方案即可进行如下封装,其中 cdn 地址由百度的 npm 镜像服务提供支持。

  代码详见:https://www.yuque.com/shuoshubao/bg00go/wc87bknptk3lomed#gozcq

  2. xlsx, fabric 等

  在项目中用到了 xlsx, fabric, markdown-it, echarts, draw.io 这几个体积很大的包,但又不属于很基础的包,只有少部分页面的某个功能点才会用到。针对这些包采用从cdn异步加载其umd包的形式来引入,而不是通过 import npm包的形式。

  代码详见:https://www.yuque.com/shuoshubao/bg00go/wc87bknptk3lomed#rEBee

  以上两种优化方案,与常见的动态引入方案(dynamic import)是有很大区别的,dynamic import 是通过编译工具将对应的npm包打包成一个独立的chunk,然后在使用的时候再通过loadScript方式引入。这种问题在于文件的缓存,一是chunk可能会变,二是像Vercel这种平台,每次发布都是一个全新的 s3 bucket,上线后缓存功能也就失效了。而上述这种方案,则利用npm镜像服务,每次都访问固定的cdn地址,也就达到了cdn的缓存目的了。

  3.4 建设组件库

  鉴于项目没有优质组件的背景,从零到一搭建了组件库,组件库主要包含以下内容:

  1. 基于 Vuepress 建设高质量组件库文档

  2. 迁移 element-ui 文档,并修复其中大量劣质示例代码

  3. 采用 Vitest 编写工具方法的测试用例

  4. 提供9个高频优质通用组件,10个业务组件

  组件库文档:https://logsfe.vercel.app/

  文档分为以下几大模块

  优质组件:https://logsfe.vercel.app/components/Table/

  组件库里的方法:https://logsfe.vercel.app/utils.html

  @nbfe/tools工具库方法: https://logsfe.vercel.app/tools/date.html

  ElementUI 文档:https://logsfe.vercel.app/element/icon.html

  前端定制的开发规范:https://logsfe.vercel.app/contribute/

  实际效果:组件库中的组件在项目中目前已被使用240次,用户使用体验良好。

  3.4.1 通用组件

  基于大量的B端系统开发经验,提炼出配置化表格和配置化表单组件,满足项目中90%的开发场景,通过重构部分页面后比较分析,在写对应模块时,能减少40%的代码。

  通用组件均与业务解耦,设计优雅的api,并提供大量示例。组件库里只提供少量的优质组件,严格把控每一行提交的代码,并为组件中的工具函数提供符合 JSDoc-style 规范的注释,且通过 Vitest 来编写单元测试。

  3.4.2 element-ui 文档集成

  在实际工作中,发现 element-ui 文档存在很多问题且早已不维护。

  主题与日志中台不符,不利于查看

  组件默认size过大,一页都看不了多少示例

  右侧没有 toc 功能,不方便快速定位

  示例很多写法不优雅,以及很多冗余代码被人机的复制到了项目中

  在线调试示例采用的是 codepen 平台,这个平台很慢而且经常挂了

  基于以上各种问题,将 element-ui 官方的示例 fork 到组件库中,使用和日志中台一样的主题,并修复上述各种问题。  

  并使用纯前端来实现了一个完全可用的 codepen 组件使用示例功能。  

  3.4.3 通用工具库

  基于B端系统抽象的实用工具方法集合。在组件库中提供优质的说明文档和使用示例。这个已经发布到npm上,并在多个公司和团队使用。

  包括日期处理、数据处理、接口数据格式化、针对element-ui的一些实用封装。目前已在项目中被93个文件使用150次。

  项目地址:https://www.npmjs.com/package/@nbfe/tools

  04 总结与展望

  在频繁的需求迭代过程中,项目迟早会变成臃肿老旧的样子。当开发体验、开发速度、代码质量、项目可维护性、联调测试体验、线上质量等全方位令人举步维艰的时候,就该发起大规模的全面重构了。对每一项重构技术需要深刻掌握,才能掌握重构的深度和保证重构后的项目质量。另外,还定制了很多开发规范和优秀实践指导,但项目中仍存在大量不符合规范的地方,将在未来继续进行全量修复,直到将一个老旧的项目重构到更接近现代化前端项目的程度。

0
相关文章