本文目录导读:

在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 } } };
这些方案可以根据您的具体需求选择合适的实现,对于生产环境,建议结合多种方案进行全面检查。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播