如何在 PR 评论中自动推送体积变化报告
解读
在国内前端团队的日常协作中,体积变化报告(bundle size diff)已经成为衡量 PR 质量的核心指标之一。面试官抛出这道题,并不是想听你“跑通 Grunt”这么简单,而是考察你能否把**“构建 → 数据采集 → 基准对比 → 评论推送”做成一条可落地、可维护、可回滚的自动化链路,同时兼顾国内网络环境**(GitHub 访问不稳定、企业 GitLab 私有化、钉钉/飞书机器人 webhook 等)与合规要求(源码不外泄、token 最小权限)。因此,回答必须体现:
- 用 Grunt 把“构建后体积采集”做成原子任务;
- 用国内 CI(GitLab-CI、Gitee Go、Jenkins 中文社区版)触发;
- 用企业 IM 机器人或 PR 接口回写评论;
- 失败可重试、数据可缓存、敏感信息不落地。
知识点
- 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-gitlab或grunt-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.yml 或 Jenkinsfile 里只需:
script:
- npm ci
- npx grunt size:baseline size:current size:diff comment:post
即可在每次 MR/PR 中看到结构化、可交互、可追踪的体积变化报告,无需人工介入。
拓展思考
- monorepo 场景:若仓库含 20+ 子包,可在 Grunt 里用
grunt-subgrunt并行跑各子包 size 任务,再聚合为一张总表,避免评论过长。 - 预算拦截:在
size:diff后加grunt-fail-on-budget任务,当总增幅超预算(如 50 kB)时直接非零退出码,让 CI 状态变为 failed,强制 review。 - 可视化回溯:把每次 diff json 上传到 私有 OSS + TableStore,再用 飞书多维表格 做趋势图,每周自动生成“体积周报” 推送给架构组。
- 安全加固:token 使用 CI_JOB_TOKEN 最小化权限,若必须存长期令牌,走 阿里云 KMS 加密存储,Grunt 任务里通过
grunt-kms-decrypt动态解密,杜绝明文泄露。