根本原因是CSS中url()路径以最终生成的CSS文件位置为基准,构建后CSS与图片目录分离导致相对路径失效;Vite仅对src/assets下字面量路径自动哈希重写,public目录或变量拼接路径不会被处理。

为什么CSS里的 url() 路径在构建后变成 404?
Vite 对 CSS 中 url() 的路径重写,依赖于你配置的 base 和资源实际存放位置。开发时能加载,是因为 dev server 做了路径代理;但 build 后是纯静态文件,url('./img/logo.png') 会被解析为相对于当前 CSS 文件的位置,而打包后 CSS 可能被移到 /assets/ 目录下,导致相对路径失效。
常见错误现象:
- 控制台报
GET <a href="https://www.php.cn/link/6a8006b6f714a6e3bf592b18c63b33b7">https://www.php.cn/link/6a8006b6f714a6e3bf592b18c63b33b7</a> 404(本该是/assets/logo.xxxx.png) - 构建产物中 CSS 文件里仍保留原始相对路径,没被自动转成带 hash 的绝对路径
原因本质:Vite 只对 src/assets 下通过 import 引入的资源做哈希+路径重写;CSS 里的 url() 若指向非 src/assets 下的路径(比如直接写 url('../public/logo.png') 或 url('/logo.png')),就不会被处理。
解决建议:
- 把图片等资源统一放在
src/assets目录下,CSS 中用相对路径引用(如url('./logo.png')),Vite 会自动解析、哈希、注入正确路径 - 避免在 CSS 中使用
url('/public/logo.png')或url('../images/logo.png')—— 这些路径不会被 Vite 编译器识别和改写 - 若必须用
public目录资源,CSS 中应写url('/logo.png')(以/开头),并确保base配置与部署路径一致,否则请求会落到错误前缀下
build 后 CSS 引用的字体或背景图路径没加 hash 怎么办?
Vite 默认会对 src/assets 下的字体(.woff/.ttf)、图片(.png/.jpg)等资源自动哈希并重写路径,但前提是:
立即学习“前端免费学习笔记(深入)”;
- 文件必须在
src/assets(或其子目录)中 - CSS 中的
url()必须是可静态分析的字符串字面量,不能是变量拼接(如url('${iconPath}'))
典型错误示例:
body { background: url("../assets/bg.jpg"); } // ✅ 正确,会被重写.icon { mask-image: url("data:image/svg+xml;..."); } // ✅ 内联 data URL,不涉及路径.dynamic { background: url("./" + icon); } // ❌ 不会被处理,构建时报 warning,运行时 404关键点:
- Vite 的 CSS 资源重写发生在构建阶段,只处理字面量路径,不执行 JS 表达式
- 字体文件如果放在
src/assets/fonts/,且 CSS 中写url('./fonts/inter.woff2'),构建后会变成url('/assets/inter.a1b2c3.woff2')(前提是base: '/') - 如果字体放在
public/fonts/,则需写url('/fonts/inter.woff2'),且确保 Nginx 或服务器能从/fonts/直接服务该文件
设置了 base: '/admin/',但 CSS 里的 url() 还是请求 /assets/xxx?
这说明 base 配置未生效,或资源路径未落入 Vite 的处理范围。
先验证:
- 打开
dist/index.html,检查<link rel="stylesheet">的href是否已带/admin/前缀(如/admin/assets/style.css) - 再打开该 CSS 文件,搜索
url(,看路径是否也已补全前缀(如url("/admin/assets/bg.png"))
如果 HTML 中路径正确,但 CSS 里仍是 /assets/bg.png,大概率是:
- 资源不在
src/assets下,比如放在public/assets—— Vite 不会重写public目录内资源的引用路径 -
vite.config.ts中base被其他插件覆盖,或配置在错误作用域(比如只写了build.base,而没写顶层base) - 使用了自定义 PostCSS 插件,干扰了 Vite 默认的 asset 处理逻辑
快速修复:
- 确保 base 是顶层字段:export default defineConfig({ base: '/admin/' })
- 把所有待哈希的资源挪进 src/assets,CSS 中用相对路径引用
- 不要依赖 public 目录来“绕过”路径问题——它只会让问题更难追踪
动态生成的 CSS 背景图路径怎么处理?
Vite 无法处理运行时拼接的 url(),比如 Vue 模板中::style="{ backgroundImage: <code>url(${imgUrl}) }"。这种写法在构建后,imgUrl 若是字符串变量,不会被 Vite 解析,也就不会加 hash、不会适配 base。
可行方案只有两种:
- 用
import预先引入:import bg from '@/assets/bg.jpg';,再:style="{ backgroundImage: `url(${bg})` }" - 用
new URL(..., import.meta.url)动态构造(推荐):const bg = new URL('@/assets/bg.jpg', import.meta.url).href,它会在构建时被 Vite 静态分析并重写
注意:require() 在 Vite 中不可用,process.env.BASE_URL 是 Vue CLI 的遗留物,Vite 中无效。真正起作用的只有 import 和 new URL(..., import.meta.url)。
真正容易被忽略的是:即使你设了 base: '/admin/',CSS 文件本身路径变了,里面的 url() 却没跟着变——这不是 bug,是 Vite 对路径作用域的明确划分。你得让资源“进圈”,它才帮你改。


















