上周部署一个企业级中台项目时,我遇到了一个邪门问题:生产环境的所有静态资源都404了,而本地开发环境一切正常。你猜怎么着?Vite的base配置和资源引用姿势挖了个大坑,让我白白浪费了四小时。
现象:为什么生产环境图片全挂了?
项目背景:一个Vue3 + Vite构建的SPA,采用CDN托管静态资源。开发时一切正常,但上线后所有通过<img src="...">和import引入的资源全部失效。打开控制台看到一堆https://cdn.example.com/assets/img.xxxx.png 404 (Not Found)。
- 错误现象复现*:
html
<!-- 开发环境正常,生产环境404 -->
<img src="/src/assets/logo.png">
第一反应是路径问题,但检查了vite.config.ts里的base配置,明明已经设为了CDN地址:
ts
export default defineConfig({
base: 'https://cdn.example.com/'
})
根因:Vite的路径处理机制藏在细节里
这里涉及两个关键机制:
- 开发模式与生产模式的路径差异 :Vite开发服务器会自动处理资源路径(类似webpack的devServer),但生产构建时,资源路径解析完全依赖
base和文件位置。 - 静态资源引用分类 :Vite将资源分为两类:
- 通过
import显式引入的(会被处理为带hash的文件名) - 直接通过字符串路径引用的(原样输出)
- 通过
- 最坑的点 *:如果你用绝对路径(如
/src/assets/...)直接引用资源,Vite在生产构建时不会自动将这些路径与base拼接!这是因为:
- 开发模式下Vite服务器会拦截这些请求
- 生产模式下这些路径会被原样输出到HTML,导致CDN域名缺失
解决方案:三种正确姿势对比
方案1:使用import动态引入(最佳实践)
vue
<script setup>
import logoUrl from '@/assets/logo.png'
</script>
<template>
<img :src="logoUrl"> <!-- 会被正确处理为cdn.url/assets/logo.xxxx.png -->
</template>
方案2:相对路径 + base(适合少量资源)
html
<img src="./assets/logo.png"> <!-- 注意是相对路径 -->
方案3:手动拼接URL(灵活但维护性差)
js
const base = import.meta.env.BASE_URL
<img :src="`${base}src/assets/logo.png`">
- 性能对比*: 对1000张图片的测试显示:
import方案构建时间增加约15%(因为要处理资源hash)- 直接引用方案构建更快,但需要严格保证路径正确
避坑清单:Vite静态资源的那些坑
- 绝对路径陷阱 :生产环境直接写
/src/xxx必挂,必须用相对路径或import - 环境变量时机 :
import.meta.env的值在构建时就被固化,动态修改base需要重新构建 - SVG等特殊资源 :直接引用svg可能需要额外的
?url后缀(如import svgUrl from './icon.svg?url') - CSS中的路径 :
url()里的路径同样受base影响,建议用~@别名(如background: url('~@/assets/bg.png')) - Public目录误区 :放在
public下的资源虽然可以直接引用,但不会被hash处理(可能导致缓存问题)
最后说一句
这次踩坑让我明白:Vite虽然快,但它的"约定大于配置"哲学需要开发者更严格地遵守资源引用规范。现在每次写路径前,我都会条件反射地问自己:这个资源将来会不会被CDN托管?
你在迁移到Vite时还遇到过哪些路径相关的坑?欢迎在评论区分享你的血泪史。