本文目录导读:

Git钩子脚本如何检查性能预算?手把手教你用自动化守住性能红线
目录导读
- 什么是性能预算?为什么需要Git钩子来检查?
- Git钩子脚本的核心原理与触发时机
- 实战:编写检查性能预算的pre-commit钩子
- 常见问题与进阶技巧
- 问答环节:解决你关于性能预算检查的疑惑
什么是性能预算?为什么需要Git钩子来检查?
性能预算(Performance Budget)是指为页面加载时间、JavaScript体积、图片大小等关键指标设定的允许上限。“首页JavaScript总量不超过200KB”“首屏加载时间低于3秒”。
传统做法是在CI/CD流水线中检查,但问题在于:开发者可能提交了超标的代码,等CI跑完才发现,回退成本高,而Git钩子(Git Hooks) 能在提交前或推送前自动拦截超标代码,实现“左移测试”:
- 左移测试:在问题最早阶段(本地提交时)发现并修复。
- 即时反馈:开发者立即收到警告,无需等待远程CI。
- 团队统一标准:每个人本地执行相同脚本,确保性能红线不被突破。
Git钩子脚本的核心原理与触发时机
Git钩子是存放在.git/hooks/目录下的可执行脚本(如Shell、Node.js、Python),最常用的两个:
| 钩子名 | 触发时机 | 适合检查性能预算吗? |
|---|---|---|
pre-commit |
git commit 前 |
✅ 检查新增/修改文件的资源体积 |
pre-push |
git push 前 |
✅ 检查全量性能指标(如构建产物) |
工作原理:
脚本执行完毕后返回0表示通过,返回非0表示拒绝提交/推送。
实战:编写检查性能预算的pre-commit钩子
以下是一个完整的Shell脚本示例,检查被暂存(staged)的图片、CSS、JavaScript、JSON文件大小是否超过设定的预算(单位:字节)。
步骤1:进入Git项目根目录
cd your-project
步骤2:创建pre-commit文件
touch .git/hooks/pre-commit chmod +x .git/hooks/pre-commit
步骤3:编写脚本内容
#!/bin/bash
# pre-commit性能预算检查脚本
# 定义预算(字节)
IMAGE_BUDGET=102400 # 100KB
JS_BUDGET=204800 # 200KB
CSS_BUDGET=51200 # 50KB
JSON_BUDGET=10240 # 10KB
echo "🔍 检查性能预算..."
# 获取暂存的文件列表(仅新增/修改)
staged_files=$(git diff --cached --name-only --diff-filter=ACM)
# 标记是否失败
failed=0
for file in $staged_files; do
if [ ! -f "$file" ]; then
continue # 跳过删除的文件
fi
file_size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
budget=0
case "$file" in
*.png|*.jpg|*.jpeg|*.gif|*.webp|*.svg)
budget=$IMAGE_BUDGET
;;
*.js|*.mjs)
budget=$JS_BUDGET
;;
*.css|*.scss|*.less)
budget=$CSS_BUDGET
;;
*.json)
budget=$JSON_BUDGET
;;
esac
if [ $budget -ne 0 ] && [ "$file_size" -gt "$budget" ]; then
echo "❌ $file 大小: ${file_size}字节,预算: ${budget}字节(超限)"
failed=1
fi
done
if [ $failed -ne 0 ]; then
echo "⚠️ 性能预算超标!请优化文件后重新commit。"
exit 1
else
echo "✅ 所有暂存文件通过性能预算检查。"
exit 0
fi
效果演示
- 当提交一个150KB的图片时,会拒绝commit并输出:
❌ assets/banner.png 大小: 153600字节,预算: 102400字节(超限) ⚠️ 性能预算超标!请优化文件后重新commit。
常见问题与进阶技巧
Q1:如何检查构建后的打包体积?
进阶方案:在pre-push钩子中运行构建命令,然后解析打包报告,例如使用Webpack的--json输出:
npx webpack --json > dist/stats.json # 解析stats.json中的totalSize是否超限
Q2:预算值从哪里获取?
- 人工设定:根据团队历史数据或行业基准(如Lighthouse建议)。
- 工具生成:使用
bundlesize(npm包)或webpack-bundle-analyzer。 - 动态计算:从
package.json或配置文件读取。
Q3:如何忽略某些文件?
在脚本中添加排除逻辑:
if [[ "$file" == *"vendor.js"* ]] || [[ "$file" == *"large-icon.png"* ]]; then continue # 跳过白名单文件 fi
Q4:脚本可以跨平台吗?
上述Shell脚本在macOS和Linux上通用,Windows用户可改用Node.js脚本,
// .git/hooks/pre-commit (使用node)
const { execSync } = require('child_process');
const files = execSync('git diff --cached --name-only').toString().trim().split('\n');
// 遍历检查...
process.exit(filesFailed ? 1 : 0);
问答环节:解决你关于性能预算检查的疑惑
问:性能预算检查会拖慢git commit吗?
答:脚本只检查暂存文件(而非全量),通常耗时<1秒,如果构建产物很大,建议用pre-push代替pre-commit。
问:如何让团队所有人都使用同一个钩子?
答:不要共享./git/hooks/目录(不可被commit),推荐使用:
- husky:npm包,自动安装钩子到
./husky/_。 - git template:设置全局模板目录。
- post-checkout钩子:克隆后自动下载最新钩子。
问:预算超限后,有没有自动压缩工具?
答:可以在脚本中集成imagemin或terser进行自动压缩并重新staging,但需谨慎(可能改变文件内容),推荐做法是:警告但允许提交,然后在CI中再次验证,防止本地工具失效。
问:我的项目使用Monorepo,预算怎么分模块?
答:在根目录的performance-budget.config.js中定义每个包的预算,脚本读取配置并匹配路径。
{
"packages/*/dist/*.js": 200000,
"packages/admin/dist/*.js": 500000
}
通过Git钩子脚本检查性能预算,能将性能问题扼杀在本地开发阶段,大幅减少线上回归成本,核心要点:
- 选对钩子:
pre-commit用于单体文件,pre-push用于构建产物。 - 定义清晰预算:基于真实场景(如3G网络、核心交互时间)。
- 脚本可复用:使用husky或git template让全团队自动生效。
建议从简单的图片/JS文件大小检查开始,逐步升级到解析Webpack/Esbuild打包报告,性能红线不是枷锁,而是保障体验的“安全网”。