如何在 HTML 与 CSS 中自动替换引用路径

解读

国内前端项目上线前普遍要经过“路径加哈希防缓存”“CDN 域名切换”“多环境部署”三道关。
如果手写修改 href、src、url(),不仅效率低,还容易漏改,导致测试环境白屏或生产环境 404。
面试官问“自动替换引用路径”,实质在考察:

  1. 你是否理解“构建阶段一次性替换”优于“运行时拼接”;
  2. 你是否能用 Grunt 生态快速落地,并兼顾缓存击穿、并行上传、回滚等工程细节;
  3. 你是否知道路径替换与文件 rev 必须原子化,否则上线瞬间会出现 race condition。

知识点

  1. Grunt 任务链:grunt-contrib-copy → grunt-filerev → grunt-usemin
    • filerev 根据文件内容生成 8 位 hash 并重命名;
    • usemin 在 HTML/CSS/JS 中扫描注释块 <!-- build:css /css/index.css -->,自动把原始路径替换成 带 hash 的最终路径
  2. useminPrepare 阶段会输出 concat、uglify、cssmin 子任务配置,避免手写重复配置。
  3. 路径别名:若公司 CDN 域名带版本号,如 //static.xxx.com/v123/,可用 grunt-string-replace 在 usemin 之后二次替换,保证灰度发布时一键切流。
  4. 缓存策略:替换后的路径需同步写入 manifest.json,供 Node 层做 HTTP 2 Server Push离线包增量更新
  5. 回滚方案:grunt-rev-rewrite 支持反向还原,紧急回滚时 30 秒内可退回上一版文件名。

答案

“我会在 Gruntfile 里用三步完成自动替换:
第一步,grunt-contrib-copy 把开发目录整站到 .tmp,保持目录结构不变;
第二步,grunt-filerev 对图片、字体、JS、CSS 做内容哈希重命名,生成 index-3f4e2a1a.css 这类文件;
第三步,grunt-usemin 解析 HTML 里的 build 注释块,自动把
<link rel="stylesheet" href="/css/index.css">
替换成
<link rel="stylesheet" href="/css/index-3f4e2a1a.css">
同时在 CSS 内部把 url(../img/logo.png) 替换成 url(../img/logo-8c9d3357.png)
整个流程一次性串行执行,保证 rev 与替换原子化;上线前再跑一遍 grunt usemin:html usemin:css --env=prod,即可输出符合 CDN 域名的最终包。”

拓展思考

  1. 多环境差异:测试环境用 /static/ 路径,生产用 //cdn.xxx.com/。可以把域名抽成 <%= grunt.config.get('domain') %>,通过 grunt --domain=//cdn.xxx.com/ 注入,避免多套模板。
  2. 雪碧图路径:grunt-spritesmith 生成的雪碧图 CSS 也带 url(),必须在 filerev 之后再跑一遍 grunt-css-url-replace,否则雪碧图文件名已变而 CSS 仍指向旧名。
  3. HTTP 2 多路复用:若公司全站 HTTP 2,可关闭合并步骤,仅保留 filerev + replace,减少大文件阻塞首屏的风险。
  4. 微前端场景:子应用独立构建,主应用通过 import-map 动态注入路径,此时 Grunt 只需输出一份 asset-manifest.json,供主应用运行时拉取,无需再触碰 HTML。