场景与现象
- 代码里用
getAssetImage("icons/card_icon.png")生成图标地址,开发环境显示为/icons/card_icon.png正常。 - 生产打包后变成
./icons/card_icon.png,路径前多了./。 - public 目录下的图标确实被拷到
dist/icons,但生成的引用前缀不同导致疑惑。
关键配置与代码
vite.config.ts中的base决定import.meta.env.BASE_URL,构建时所有资源路径都会带上它。getAssetImage逻辑:
export function getAssetImage(url: string) {
if (!url) return "";
const clean = String(url).replace(/^\/+/, ""); // 去掉开头的 /
return `${import.meta.env.BASE_URL}${clean}`;
}开发 vs 构建的 base 行为
开发:Vite Dev Server 始终以根路径
/服务资源,import.meta.env.BASE_URL会被标准化为/,即便配置里写了base: "./",开发时仍然是/。构建:打包阶段严格使用配置的
base。base: "./"会让产物里的资源前缀变成./,base: "/"则是/;子路径部署(如/app/)会写成/app/。
原因拆解
开发环境:Vite Dev Server 默认
base为/,所以import.meta.env.BASE_URL = "/",拼出来/icons/...。传入
/icons/xxx.png时,getAssetImage会把开头的/去掉,最终与传入icons/xxx.png的效果相同。在
base: "./"下,结果是./icons/xxx.png,不会出现.//icons/xxx.png,因为前导/已被移除。生产构建:
vite.config.ts将base设为"./",import.meta.env.BASE_URL = "./",拼出来./icons/...。这是配置预期行为,并非getAssetImagebug。之所以没有出现
.//icons/...,是因为getAssetImage先把传入路径的前导/去掉了。
什么时候改 base
根路径部署(常规 Web 站点):用默认
/,保持开发(开发使用的是 / )、生产一致。子路径部署:把
base设成子路径(如/app/),对应服务器挂载路径。相对路径/嵌入式(file://、被别的页面 inline):才需要
./或空字符串。
处理建议
当前目标是根路径部署,
base已改回/,生成路径会是/icons/...,与开发一致。若必须相对路径发布又不想看到
./,可以在getAssetImage末尾再去一遍开头的./;否则保持base与部署方式一致即可。
快速验证
pnpm build→pnpm run preview。打开预览页,检查侧边栏图标的网络请求路径,应为
/icons/...。若将
base改成子路径或./,重复构建并观察路径变化,验证是否符合部署方式。
参考资料
- Vite 官方静态资源指南:https://cn.vitejs.dev/guide/assets