如何在 HTML 与 CSS 中自动替换引用路径
解读
国内前端项目上线前普遍要经过“路径加哈希防缓存”“CDN 域名切换”“多环境部署”三道关。
如果手写修改 href、src、url(),不仅效率低,还容易漏改,导致测试环境白屏或生产环境 404。
面试官问“自动替换引用路径”,实质在考察:
- 你是否理解“构建阶段一次性替换”优于“运行时拼接”;
- 你是否能用 Grunt 生态快速落地,并兼顾缓存击穿、并行上传、回滚等工程细节;
- 你是否知道路径替换与文件 rev 必须原子化,否则上线瞬间会出现 race condition。
知识点
- Grunt 任务链:grunt-contrib-copy → grunt-filerev → grunt-usemin
- filerev 根据文件内容生成 8 位 hash 并重命名;
- usemin 在 HTML/CSS/JS 中扫描注释块
<!-- build:css /css/index.css -->,自动把原始路径替换成 带 hash 的最终路径。
- useminPrepare 阶段会输出 concat、uglify、cssmin 子任务配置,避免手写重复配置。
- 路径别名:若公司 CDN 域名带版本号,如
//static.xxx.com/v123/,可用 grunt-string-replace 在 usemin 之后二次替换,保证灰度发布时一键切流。 - 缓存策略:替换后的路径需同步写入 manifest.json,供 Node 层做 HTTP 2 Server Push 或 离线包增量更新。
- 回滚方案: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 域名的最终包。”
拓展思考
- 多环境差异:测试环境用
/static/路径,生产用//cdn.xxx.com/。可以把域名抽成<%= grunt.config.get('domain') %>,通过grunt --domain=//cdn.xxx.com/注入,避免多套模板。 - 雪碧图路径:grunt-spritesmith 生成的雪碧图 CSS 也带 url(),必须在 filerev 之后再跑一遍 grunt-css-url-replace,否则雪碧图文件名已变而 CSS 仍指向旧名。
- HTTP 2 多路复用:若公司全站 HTTP 2,可关闭合并步骤,仅保留 filerev + replace,减少大文件阻塞首屏的风险。
- 微前端场景:子应用独立构建,主应用通过 import-map 动态注入路径,此时 Grunt 只需输出一份 asset-manifest.json,供主应用运行时拉取,无需再触碰 HTML。