// build-h5-smart.js - 带智能缓存的 H5 构建脚本 const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); const { execSync } = require('child_process'); const { glob } = require('glob'); const CACHE_MARKER_FILE = 'dist/h5/.build-cache-marker'; const SOURCE_PATTERNS = ['src/**/*', 'config/**/*', 'package-lock.json', '.build/h5_for_production.js']; // 计算文件哈希 function hashFile(filePath) { if (!fs.existsSync(filePath)) { return ''; } const content = fs.readFileSync(filePath); return crypto.createHash('md5').update(content).digest('hex'); } // 计算多个文件的组合哈希 async function hashFiles(patterns) { const hashes = []; for (const pattern of patterns) { try { // 使用 glob 查找匹配的文件 const files = await glob(pattern, { cwd: process.cwd(), ignore: ['**/node_modules/**', '**/dist/**', '**/.git/**'], nodir: true }); // 对每个文件计算哈希 for (const file of files.sort()) { const hash = hashFile(file); if (hash) { hashes.push(`${file}:${hash}`); } } } catch (error) { console.warn(`警告: 无法处理模式 ${pattern}: ${error.message}`); } } // 将所有哈希组合成一个总哈希 const combined = hashes.join('\n'); return crypto.createHash('md5').update(combined).digest('hex'); } // 检查 H5 构建缓存 async function checkH5BuildCache() { console.log('🔍 检查 H5 构建缓存...'); // 检查构建产物是否存在 if (!fs.existsSync('dist/h5')) { console.log('❌ 构建产物不存在'); return false; } // 检查缓存标记文件 if (!fs.existsSync(CACHE_MARKER_FILE)) { console.log('❌ 缓存标记文件不存在'); return false; } try { // 读取缓存的哈希值 const cachedHash = fs.readFileSync(CACHE_MARKER_FILE, 'utf8').trim(); // 计算当前源文件的哈希值 console.log('📊 计算源文件哈希...'); const currentHash = await hashFiles(SOURCE_PATTERNS); console.log(` 缓存哈希: ${cachedHash.substring(0, 8)}...`); console.log(` 当前哈希: ${currentHash.substring(0, 8)}...`); if (cachedHash === currentHash) { console.log('✅ H5 构建缓存命中!'); return true; } else { console.log('❌ 源文件已更改,需要重新构建'); return false; } } catch (error) { console.error('⚠️ 检查缓存时出错:', error.message); return false; } } // 保存构建缓存标记 async function saveBuildCacheMarker() { console.log('💾 保存构建缓存标记...'); try { const currentHash = await hashFiles(SOURCE_PATTERNS); // 确保目录存在 const markerDir = path.dirname(CACHE_MARKER_FILE); if (!fs.existsSync(markerDir)) { fs.mkdirSync(markerDir, { recursive: true }); } fs.writeFileSync(CACHE_MARKER_FILE, currentHash); console.log(`✅ 缓存标记已保存: ${currentHash.substring(0, 8)}...`); } catch (error) { console.error('⚠️ 保存缓存标记时出错:', error.message); } } // 执行 H5 构建 function buildH5() { console.log('🔨 开始构建 H5...'); try { execSync('node .build/h5_for_production.js', { stdio: 'inherit', cwd: process.cwd() }); console.log('✅ H5 构建完成'); return true; } catch (error) { console.error('❌ H5 构建失败:', error.message); return false; } } // 主函数 async function main() { console.log('🚀 智能 H5 构建系统'); console.log('====================\n'); try { // 检查缓存 const cacheHit = await checkH5BuildCache(); if (cacheHit) { console.log('\n🎉 使用缓存的构建产物,跳过构建步骤'); return; } // 需要重新构建 console.log('\n📦 执行 H5 构建...'); const success = buildH5(); if (success) { // 保存新的缓存标记 await saveBuildCacheMarker(); console.log('\n🎉 构建成功!'); } else { console.error('\n❌ 构建失败'); process.exit(1); } } catch (error) { console.error('❌ 错误:', error.message); process.exit(1); } } // 运行 main();