Git钩子脚本如何检查包体积大小

wen 实用脚本 1

本文目录导读:

Git钩子脚本如何检查包体积大小

  1. 检查单个文件大小
  2. 检查打包后的体积(针对前端项目)
  3. 检查打包产物中的具体文件
  4. 使用 Node.js 脚本进行更精确的控制
  5. 集成到 pre-commit 钩子
  6. 使用 Git Hooks 管理工具
  7. 注意事项

Git 钩子脚本可以通过在 pre-commitpre-push 阶段运行体积检查来防止大文件或过大的包被提交,以下是几种实现方案:

检查单个文件大小

在 pre-commit 钩子中检查

创建 .git/hooks/pre-commit 文件:

#!/bin/bash
# 设置最大文件大小限制(10MB)
MAX_SIZE_MB=10
MAX_SIZE=$((MAX_SIZE_MB * 1024 * 1024))
# 获取暂存区中的文件列表
files=$(git diff --cached --name-only --diff-filter=ACM)
# 标记是否有大文件
has_large_files=false
for file in $files; do
    if [ -f "$file" ]; then
        # 获取文件大小
        size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
        if [ "$size" -gt "$MAX_SIZE" ]; then
            echo "❌ 错误: 文件 '$file' 过大 (${size} 字节 / ${MAX_SIZE_MB}MB限制)"
            has_large_files=true
        fi
    fi
done
if [ "$has_large_files" = true ]; then
    echo "请优化文件大小后重新提交"
    exit 1
fi

检查打包后的体积(针对前端项目)

检查 dist 目录大小

#!/bin/bash
# 检查构建输出目录大小
MAX_DIST_SIZE_MB=50
DIST_DIR="dist"
if [ -d "$DIST_DIR" ]; then
    dist_size=$(du -sm "$DIST_DIR" | cut -f1)
    if [ "$dist_size" -gt "$MAX_DIST_SIZE_MB" ]; then
        echo "❌ 警告: dist目录体积过大 (${dist_size}MB / ${MAX_DIST_SIZE_MB}MB限制)"
        exit 1
    fi
fi

检查打包产物中的具体文件

针对 Webpack/Vite 构建产物

#!/bin/bash
# 检查特定的打包文件
MAX_CHUNK_SIZE_MB=1
BUILD_DIR="dist"
# 查找所有 JS 和 CSS 文件
find "$BUILD_DIR" -type f \( -name "*.js" -o -name "*.css" \) | while read -r file; do
    size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
    size_mb=$((size / 1024 / 1024))
    if [ "$size_mb" -gt "$MAX_CHUNK_SIZE_MB" ]; then
        echo "❌ 警告: ${file#./} 体积过大 (${size_mb}MB)"
        exit 1
    fi
done

使用 Node.js 脚本进行更精确的控制

创建 scripts/check-bundle-size.js

#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const MAX_SIZE_MB = 10;
const IGNORE_PATTERNS = ['node_modules', '.git', '*.map'];
function getFileSizeInMB(filePath) {
    const stats = fs.statSync(filePath);
    return stats.size / (1024 * 1024);
}
function shouldIgnore(filePath) {
    return IGNORE_PATTERNS.some(pattern => {
        if (pattern.startsWith('*')) {
            return filePath.endsWith(pattern.slice(1));
        }
        return filePath.includes(pattern);
    });
}
function checkLargeFiles() {
    // 获取暂存区的文件
    const files = execSync('git diff --cached --name-only --diff-filter=ACM')
        .toString()
        .trim()
        .split('\n')
        .filter(Boolean);
    let hasLargeFiles = false;
    files.forEach(file => {
        if (shouldIgnore(file)) return;
        if (fs.existsSync(file)) {
            const sizeMB = getFileSizeInMB(file);
            if (sizeMB > MAX_SIZE_MB) {
                console.log(`❌ ${file}: ${sizeMB.toFixed(2)}MB (限制: ${MAX_SIZE_MB}MB)`);
                hasLargeFiles = true;
            } else if (sizeMB > MAX_SIZE_MB * 0.8) {
                console.log(`⚠️  ${file}: ${sizeMB.toFixed(2)}MB (接近限制)`);
            }
        }
    });
    if (hasLargeFiles) {
        process.exit(1);
    }
}
checkLargeFiles();

集成到 pre-commit 钩子

完整的 pre-commit 脚本:

#!/bin/bash
echo "🔍 执行包体积检查..."
# 配置
MAX_FILE_SIZE_MB=10
MAX_TOTAL_SIZE_MB=100
EXCLUDE_PATTERNS="*.map node_modules/ dist/ coverage/"
# 检查单个文件大小
echo "检查单个文件大小..."
git diff --cached --name-only --diff-filter=ACM | while read file; do
    if [ -f "$file" ]; then
        # 跳过排除文件
        skip=false
        for pattern in $EXCLUDE_PATTERNS; do
            if [[ "$file" == $pattern ]]; then
                skip=true
                break
            fi
        done
        if [ "$skip" = false ]; then
            size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
            size_mb=$(echo "scale=2; $size / 1048576" | bc)
            if (( $(echo "$size_mb > $MAX_FILE_SIZE_MB" | bc -l) )); then
                echo "❌ 文件过大: $file (${size_mb}MB)"
                exit 1
            elif (( $(echo "$size_mb > $MAX_FILE_SIZE_MB * 0.8" | bc -l) )); then
                echo "⚠️  文件接近限制: $file (${size_mb}MB)"
            fi
        fi
    fi
done
# 检查暂存文件总体积
echo "检查暂存文件总体积..."
total_size=0
git diff --cached --name-only --diff-filter=ACM | while read file; do
    if [ -f "$file" ]; then
        size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
        total_size=$((total_size + size))
    fi
done
total_size_mb=$(echo "scale=2; $total_size / 1048576" | bc)
if (( $(echo "$total_size_mb > $MAX_TOTAL_SIZE_MB" | bc -l) )); then
    echo "❌ 暂存文件总体积过大: ${total_size_mb}MB"
    exit 1
fi
echo "✅ 体积检查通过"
exit 0

使用 Git Hooks 管理工具

推荐使用 husky 管理钩子:

// package.json
{
  "husky": {
    "hooks": {
      "pre-commit": "node scripts/check-bundle-size.js"
    }
  },
  "scripts": {
    "check:size": "node scripts/check-bundle-size.js"
  }
}

注意事项

  1. 设置合理的阈值:根据项目特点和网络环境调整
  2. 考虑 Git LFS:对大文件使用 Git Large File Storage
  3. 忽略特定文件和目录:如 .map 文件、node_modules
  4. 考虑并行处理:对大项目使用 xargs 或其他并行工具加速
  5. 提供详细信息:在输出中包含文件路径、大小和建议

这样可以在提交前自动检查包体积,避免意外提交过大的文件。

抱歉,评论功能暂时关闭!