hash-loadm.js 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. /**
  2. * 构建后处理:给 build/js/load.m.js 加内容 hash 文件名(load.m.<hash>.js),
  3. * 并把 build 下所有 HTML 里对 load.m.js 的引用一起改写为带 hash 的文件名。
  4. *
  5. * 目的:load.m.js 在 public/ 下是逐字拷贝、文件名固定,CDN 会长期缓存,
  6. * 每次改完都要手动刷 CDN。加内容 hash 后「内容变 → 文件名变 → 新 URL」,
  7. * CDN 必然回源拉取新版本,无需再手动刷新。
  8. *
  9. * 用法:craco build 之后执行(见 package.json 的 build/gzip 脚本)。
  10. */
  11. const fs = require("fs");
  12. const path = require("path");
  13. const crypto = require("crypto");
  14. const buildDir = path.resolve(__dirname, "..", "build");
  15. const loadmRel = path.join("js", "load.m.js");
  16. const loadmAbs = path.join(buildDir, loadmRel);
  17. if (!fs.existsSync(loadmAbs)) {
  18. console.warn("[hash-loadm] 跳过:未找到 " + loadmAbs);
  19. process.exit(0);
  20. }
  21. const content = fs.readFileSync(loadmAbs);
  22. const hash = crypto.createHash("md5").update(content).digest("hex").slice(0, 10);
  23. const hashedName = "load.m." + hash + ".js";
  24. const hashedAbs = path.join(buildDir, "js", hashedName);
  25. // 生成带 hash 的副本(保留原文件作为兜底,不影响已改写的引用)
  26. fs.copyFileSync(loadmAbs, hashedAbs);
  27. // 改写 build 下所有 HTML 对 load.m.js 的引用(兼容 /js/、./js/ 等任意前缀)
  28. let htmlCount = 0;
  29. const walk = (dir) => {
  30. for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
  31. const p = path.join(dir, entry.name);
  32. if (entry.isDirectory()) {
  33. walk(p);
  34. } else if (entry.name.toLowerCase().endsWith(".html")) {
  35. const html = fs.readFileSync(p, "utf8");
  36. const next = html.replace(/load\.m\.js\b/g, hashedName);
  37. if (next !== html) {
  38. fs.writeFileSync(p, next);
  39. htmlCount++;
  40. }
  41. }
  42. }
  43. };
  44. walk(buildDir);
  45. console.log(
  46. "[hash-loadm] " + loadmRel + " -> js/" + hashedName + ",已改写 " + htmlCount + " 个 HTML"
  47. );