本文目录导读:

在Git钩子中直接检查页面加载时间比较困难,因为Git钩子运行在服务端或本地,无法直接访问浏览器环境,您可以通过以下几种方案实现类似的功能:
使用Node.js脚本进行服务端渲染测试
pre-commit钩子示例
#!/bin/bash
# .git/hooks/pre-commit
# 获取即将提交的文件列表
FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(html|js|css)$')
if [ -n "$FILES" ]; then
echo "🔍 检查提交文件性能..."
# 使用Node.js进行初步性能检查
node -e "
const fs = require('fs');
const files = process.argv[1].split('\n').filter(Boolean);
files.forEach(file => {
if (fs.existsSync(file)) {
const content = fs.readFileSync(file, 'utf-8');
// 检查常见性能问题
const performanceIssues = [];
// 检查大文件
const size = Buffer.byteLength(content, 'utf-8');
if (size > 50000) {
performanceIssues.push('文件过大: ' + (size/1024).toFixed(2) + 'KB');
}
// 检查图片大小
const imgMatches = content.match(/<img[^>]+>/gi) || [];
imgMatches.forEach(img => {
if (img.includes('base64')) {
const base64Match = img.match(/base64,([^\"']+)/);
if (base64Match && base64Match[1].length > 100000) {
performanceIssues.push('发现大Base64图片');
}
}
});
// 检查JavaScript
if (file.endsWith('.js')) {
// 检查同步请求
if (content.includes('XMLHttpRequest') && !content.includes('async')) {
performanceIssues.push('存在同步AJAX请求');
}
// 检查大循环
const forMatches = content.match(/for\s*\([^)]+\)/g);
if (forMatches && forMatches.length > 10) {
performanceIssues.push('存在过多循环');
}
}
if (performanceIssues.length > 0) {
console.log('⚠️ ' + file + ':');
performanceIssues.forEach(issue => console.log(' - ' + issue));
}
}
});
" "$FILES"
fi
使用Puppeteer进行实际加载测试
安装依赖
npm install puppeteer --save-dev
post-merge钩子示例
// .git/hooks/post-merge
#!/usr/bin/env node
const puppeteer = require('puppeteer');
async function checkLoadTime(url) {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
// 收集性能指标
await page.goto(url, { waitUntil: 'networkidle0' });
const performance = await page.evaluate(() => {
const perfData = performance.getEntriesByType('navigation')[0];
const resources = performance.getEntriesByType('resource');
return {
// 核心Web指标
FCP: performance.getEntriesByName('first-contentful-paint')[0]?.startTime,
LCP: new Promise((resolve) => {
new PerformanceObserver((list) => {
const entries = list.getEntries();
resolve(entries[entries.length - 1].startTime);
}).observe({ type: 'largest-contentful-paint', buffered: true });
}),
// 加载时间
domContentLoaded: perfData.domContentLoadedEventEnd,
loadComplete: perfData.loadEventEnd,
// 资源分析
totalResources: resources.length,
totalSize: resources.reduce((acc, res) => acc + (res.transferSize || 0), 0),
// 慢资源
slowResources: resources
.filter(res => res.duration > 5000)
.map(res => ({
name: res.name,
duration: res.duration,
size: res.transferSize
}))
};
});
console.log('📊 加载性能报告:');
console.log(` FCP: ${performance.FCP?.toFixed(0)}ms`);
console.log(` 总资源数: ${performance.totalResources}`);
console.log(` 总大小: ${(performance.totalSize / 1024).toFixed(2)}KB`);
if (performance.slowResources.length > 0) {
console.log('⚠️ 慢资源警告:');
performance.slowResources.forEach(res => {
console.log(` - ${res.name}: ${res.duration.toFixed(0)}ms`);
});
}
await browser.close();
}
// 监控本地开发服务器
checkLoadTime('http://localhost:3000').catch(console.error);
集成性能测试工具
使用Lighthouse脚本
// .git/hooks/pre-push
#!/usr/bin/env node
const { execSync } = require('child_process');
async function runLighthouseCheck() {
try {
console.log('🏃 运行Lighthouse性能测试...');
// 确保本地服务器运行
execSync('npx http-server ./dist -p 8080 -c-1 --silent &', {
shell: true,
timeout: 3000
});
// 运行Lighthouse
execSync('npx lighthouse http://localhost:8080 --chrome-flags="--headless" --output=json --output-path=./lighthouse-report.json', {
timeout: 30000
});
// 读取报告
const report = require('./lighthouse-report.json');
const performanceScore = report.categories.performance.score * 100;
console.log(`📊 性能评分: ${performanceScore}`);
if (performanceScore < 80) {
console.log('❌ 性能评分低于80分,请优化后重试');
process.exit(1);
}
console.log('✅ 性能检查通过');
} catch (error) {
console.error('❌ 性能测试失败:', error.message);
process.exit(1);
}
}
runLighthouseCheck();
简单的文件级别检查
适合快速部署的轻量方案
#!/bin/bash
# .git/hooks/pre-commit
# 定义阈值
MAX_JS_SIZE=500000 # 500KB
MAX_CSS_SIZE=100000 # 100KB
MAX_HTML_SIZE=50000 # 50KB
# 检查即将提交的文件
echo "🔍 检查文件大小限制..."
git diff --cached --name-only | while read file; do
if [ -f "$file" ]; then
size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
case "$file" in
*.js)
if [ $size -gt $MAX_JS_SIZE ]; then
echo "⚠️ $file 过大 ($((size/1024))KB)"
fi
;;
*.css)
if [ $size -gt $MAX_CSS_SIZE ]; then
echo "⚠️ $file 过大 ($((size/1024))KB)"
fi
;;
*.html)
if [ $size -gt $MAX_HTML_SIZE ]; then
echo "⚠️ $file 过大 ($((size/1024))KB)"
fi
;;
esac
fi
done
# 检查图片文件
echo "🔍 检查图片优化..."
git diff --cached --name-only -- '*.png' '*.jpg' '*.jpeg' '*.gif' '*.webp' | while read file; do
if [ -f "$file" ]; then
size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
if [ $size -gt 100000 ]; then # 100KB
echo "⚠️ 图片文件过大: $file ($((size/1024))KB)"
fi
fi
done
最佳实践建议
-
选择合适的钩子类型:
pre-commit:执行快速检查,适合文件大小限制post-commit:执行耗时操作,如详细性能分析pre-push:执行完整性能测试
-
配置CI/CD集成:
# .github/workflows/performance.yml name: Performance Check on: [pull_request] jobs: performance: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Test load time run: | npm install npm run build npx lighthouse https://your-site.com --output=json -
自定义阈值:
// 在项目根目录创建 .perfconfig.js module.exports = { thresholds: { fcp: 2000, // First Contentful Paint < 2s lcp: 2500, // Largest Contentful Paint < 2.5s tti: 3000, // Time to Interactive < 3s fileSize: { js: 300000, // 300KB css: 100000, // 100KB images: 200000 // 200KB } } };
这些方案可以根据您的具体需求选择合适的实现,对于生产环境,建议结合多种方案进行全面检查。