如何在 PR 评论中自动推送体积变化报告

解读

在国内前端团队的日常协作中,体积变化报告(bundle size diff)已经成为衡量 PR 质量的核心指标之一。面试官抛出这道题,并不是想听你“跑通 Grunt”这么简单,而是考察你能否把**“构建 → 数据采集 → 基准对比 → 评论推送”做成一条可落地、可维护、可回滚的自动化链路,同时兼顾国内网络环境**(GitHub 访问不稳定、企业 GitLab 私有化、钉钉/飞书机器人 webhook 等)与合规要求(源码不外泄、token 最小权限)。因此,回答必须体现:

  1. 用 Grunt 把“构建后体积采集”做成原子任务;
  2. 国内 CI(GitLab-CI、Gitee Go、Jenkins 中文社区版)触发;
  3. 企业 IM 机器人或 PR 接口回写评论;
  4. 失败可重试、数据可缓存、敏感信息不落地。

知识点

  • Grunt 任务原子化:grunt-contrib-clean、grunt-webpack、grunt-asset-monitor 等插件的串行与并行写法;
  • 体积采集精度:webpack-bundle-analyzer 的 json 模式、rollup-plugin-bundle-size、grunt-size-report;
  • 基准存储策略:.gitattributes 过滤、Git LFS、私有 OSS 桶、CI 缓存 key 命名规则;
  • diff 算法:gzip 前后双指标、依赖模块三级分类(runtime、async、duplicate);
  • 鉴权与网络:GitHub/GitLab PAT 只开 api 读、写 comment 权限,国内镜像源同步策略;
  • 评论模板设计:markdown 表格折叠、emoji 标识阈值、@指定代码owner;
  • 失败降级:CI 步骤 continue-on-error、Grunt force 模式、企业微信群机器人限流重试;
  • 合规审计:token 存 CI 变量并开审计日志,体积数据不落公网,评论内容脱敏。

答案

整条链路分四步,全部用 Grunt 子任务封装,保证本地可复现、CI 可调用。

第一步:采集
在 Gruntfile 里注册任务 size:current

  • 先用 grunt-webpack 打出生产包;
  • 再跑 grunt-asset-monitor,把每个 chunk 的原始体积、gzip 体积、解析后模块列表写入 dist/size-current.json
  • 文件名带 commit-sha 防止并发写冲突。

第二步:获取基准
注册任务 size:baseline

  • CI 启动时,通过 git fetch origin main:main 拿到目标分支;
  • checkout 到 main,执行同样 size:current 逻辑,产出 dist/size-baseline.json
  • 若公司用 私有 OSS 做基准缓存,可在 Grunt 里用 grunt-aws-sdk 插件,以 project-name/main-branch.json 为 key 直接下载,省去二次构建,节省 70% 时间

第三步:diff 与格式化
注册任务 size:diff

  • 读取两个 json,按 chunk 名对齐,计算 Δ = current - baseline
  • 阈值策略:gzip 后 > 1 kB 且增幅 > 5 % 标 🔴,降幅 > 5 % 标 🟢,其余 ⚪;
  • 生成 markdown 文本,顶部一句“体积变化总览:+2.34 kB(+3.1 %)”,下方折叠详情,避免刷屏;
  • 同时输出 size-diff.json 供后续步骤使用,保证数据与展示分离

第四步:推送评论
注册任务 comment:post

  • 判断环境变量 CI_MERGE_REQUEST_IID(GitLab)或 GITHUB_PR_NUMBER(GitHub)是否存在,自动识别 CI 平台
  • grunt-gitlabgrunt-github-api 插件,携带 PROJECT_ACCESS_TOKEN(只开 api 与 notes 权限)调用接口;
  • 评论前查询是否已存在“体积报告”评论,有则 PATCH 更新,无则 POST 新建,防止重复刷屏
  • 若公司代码托管在 Gitee 私有化部署,可改用 grunt-http 直接调 /v5/repos/{owner}/{repo}/pulls/{number}/comments
  • 网络超时统一走 retry-axios 封装,默认 3 次退避
  • 失败时把 diff 文件上传到 企业微信群机器人,以 Markdown 形式推送,保证信息必达

最终,在 .gitlab-ci.ymlJenkinsfile 里只需:

script:
  - npm ci
  - npx grunt size:baseline size:current size:diff comment:post

即可在每次 MR/PR 中看到结构化、可交互、可追踪的体积变化报告,无需人工介入

拓展思考

  1. monorepo 场景:若仓库含 20+ 子包,可在 Grunt 里用 grunt-subgrunt 并行跑各子包 size 任务,再聚合为一张总表,避免评论过长。
  2. 预算拦截:在 size:diff 后加 grunt-fail-on-budget 任务,当总增幅超预算(如 50 kB)时直接非零退出码,让 CI 状态变为 failed,强制 review
  3. 可视化回溯:把每次 diff json 上传到 私有 OSS + TableStore,再用 飞书多维表格 做趋势图,每周自动生成“体积周报” 推送给架构组。
  4. 安全加固:token 使用 CI_JOB_TOKEN 最小化权限,若必须存长期令牌,走 阿里云 KMS 加密存储,Grunt 任务里通过 grunt-kms-decrypt 动态解密,杜绝明文泄露