build-h5-smart.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // build-h5-smart.js - 带智能缓存的 H5 构建脚本
  2. const fs = require('fs');
  3. const path = require('path');
  4. const crypto = require('crypto');
  5. const { execSync } = require('child_process');
  6. const { glob } = require('glob');
  7. const CACHE_MARKER_FILE = 'dist/h5/.build-cache-marker';
  8. const SOURCE_PATTERNS = ['src/**/*', 'config/**/*', 'package-lock.json', '.build/h5_for_production.js'];
  9. // 计算文件哈希
  10. function hashFile(filePath) {
  11. if (!fs.existsSync(filePath)) {
  12. return '';
  13. }
  14. const content = fs.readFileSync(filePath);
  15. return crypto.createHash('md5').update(content).digest('hex');
  16. }
  17. // 计算多个文件的组合哈希
  18. async function hashFiles(patterns) {
  19. const hashes = [];
  20. for (const pattern of patterns) {
  21. try {
  22. // 使用 glob 查找匹配的文件
  23. const files = await glob(pattern, {
  24. cwd: process.cwd(),
  25. ignore: ['**/node_modules/**', '**/dist/**', '**/.git/**'],
  26. nodir: true
  27. });
  28. // 对每个文件计算哈希
  29. for (const file of files.sort()) {
  30. const hash = hashFile(file);
  31. if (hash) {
  32. hashes.push(`${file}:${hash}`);
  33. }
  34. }
  35. } catch (error) {
  36. console.warn(`警告: 无法处理模式 ${pattern}: ${error.message}`);
  37. }
  38. }
  39. // 将所有哈希组合成一个总哈希
  40. const combined = hashes.join('\n');
  41. return crypto.createHash('md5').update(combined).digest('hex');
  42. }
  43. // 检查 H5 构建缓存
  44. async function checkH5BuildCache() {
  45. console.log('🔍 检查 H5 构建缓存...');
  46. // 检查构建产物是否存在
  47. if (!fs.existsSync('dist/h5')) {
  48. console.log('❌ 构建产物不存在');
  49. return false;
  50. }
  51. // 检查缓存标记文件
  52. if (!fs.existsSync(CACHE_MARKER_FILE)) {
  53. console.log('❌ 缓存标记文件不存在');
  54. return false;
  55. }
  56. try {
  57. // 读取缓存的哈希值
  58. const cachedHash = fs.readFileSync(CACHE_MARKER_FILE, 'utf8').trim();
  59. // 计算当前源文件的哈希值
  60. console.log('📊 计算源文件哈希...');
  61. const currentHash = await hashFiles(SOURCE_PATTERNS);
  62. console.log(` 缓存哈希: ${cachedHash.substring(0, 8)}...`);
  63. console.log(` 当前哈希: ${currentHash.substring(0, 8)}...`);
  64. if (cachedHash === currentHash) {
  65. console.log('✅ H5 构建缓存命中!');
  66. return true;
  67. } else {
  68. console.log('❌ 源文件已更改,需要重新构建');
  69. return false;
  70. }
  71. } catch (error) {
  72. console.error('⚠️ 检查缓存时出错:', error.message);
  73. return false;
  74. }
  75. }
  76. // 保存构建缓存标记
  77. async function saveBuildCacheMarker() {
  78. console.log('💾 保存构建缓存标记...');
  79. try {
  80. const currentHash = await hashFiles(SOURCE_PATTERNS);
  81. // 确保目录存在
  82. const markerDir = path.dirname(CACHE_MARKER_FILE);
  83. if (!fs.existsSync(markerDir)) {
  84. fs.mkdirSync(markerDir, { recursive: true });
  85. }
  86. fs.writeFileSync(CACHE_MARKER_FILE, currentHash);
  87. console.log(`✅ 缓存标记已保存: ${currentHash.substring(0, 8)}...`);
  88. } catch (error) {
  89. console.error('⚠️ 保存缓存标记时出错:', error.message);
  90. }
  91. }
  92. // 执行 H5 构建
  93. function buildH5() {
  94. console.log('🔨 开始构建 H5...');
  95. try {
  96. execSync('node .build/h5_for_production.js', {
  97. stdio: 'inherit',
  98. cwd: process.cwd()
  99. });
  100. console.log('✅ H5 构建完成');
  101. return true;
  102. } catch (error) {
  103. console.error('❌ H5 构建失败:', error.message);
  104. return false;
  105. }
  106. }
  107. // 主函数
  108. async function main() {
  109. console.log('🚀 智能 H5 构建系统');
  110. console.log('====================\n');
  111. try {
  112. // 检查缓存
  113. const cacheHit = await checkH5BuildCache();
  114. if (cacheHit) {
  115. console.log('\n🎉 使用缓存的构建产物,跳过构建步骤');
  116. return;
  117. }
  118. // 需要重新构建
  119. console.log('\n📦 执行 H5 构建...');
  120. const success = buildH5();
  121. if (success) {
  122. // 保存新的缓存标记
  123. await saveBuildCacheMarker();
  124. console.log('\n🎉 构建成功!');
  125. } else {
  126. console.error('\n❌ 构建失败');
  127. process.exit(1);
  128. }
  129. } catch (error) {
  130. console.error('❌ 错误:', error.message);
  131. process.exit(1);
  132. }
  133. }
  134. // 运行
  135. main();