Vue项目引入vue-router后无法访问public文件夹静态资源
问题背景
项目public目录下存储了音频文件,未配置vue-router时,通过相对路径可以正常播放音频:
原有可运行代码如下:
path = 'recordings/Behar/weekday/1.mp3' this.audio = new Audio(path); this.audio.play()
添加history模式的vue-router配置后,访问嵌套路由页面播放音频时报错Uncaught (in promise) DOMException: Failed to load because no supported source was found.,路由配置如下:
const routes = [ { path: '/', component: Controller }, { path: '/date/:date', component: Controller }, { path: '/date/:date/aliyah/:aliyah', component: Controller }, { path: '/date/:date/aliyah/:aliyah/verse/:verse', component: Controller }, ] const router = new VueRouter({ mode: 'history', routes }) Vue.use(VueRouter) Vue.config.productionTip = false new Vue({ router, vuetify, render: h => h(App) }).$mount('#app')
故障原因
vue-router本身不会拦截或修改静态资源的访问路径,问题根源是相对路径的解析规则与history嵌套路由共同作用导致资源地址错误:
- 未配置路由时,页面始终在站点根路径
/下打开,相对路径recordings/xxx.mp3会被浏览器解析为/recordings/xxx.mp3,刚好匹配public目录下的文件路径,因此可以正常加载。 - 配置多层嵌套路由后,比如打开地址
/date/20240520/aliyah/2/verse/5时,浏览器会以当前路由路径为基准解析相对路径,最终请求的地址变成/date/20240520/aliyah/2/verse/recordings/Behar/weekday/1.mp3,该路径下不存在对应音频文件,因此加载失败抛出错误。
修复方案
根据项目部署场景选择对应写法即可:
- 如果项目固定部署在站点根目录,直接把资源路径改成根路径开头的绝对路径,这是最简单的修复方式:
// 路径前加/,强制从站点根目录解析资源 path = '/recordings/Behar/weekday/1.mp3' this.audio = new Audio(path); this.audio.play()
- 如果项目可能部署在域名的子路径下(比如
https://xxx.com/my-vue-app/),不要硬编码根斜杠,用框架提供的基础路径常量拼接,适配不同部署场景:- Vue CLI创建的项目用
process.env.BASE_URL拼接:
path = `${process.env.BASE_URL}recordings/Behar/weekday/1.mp3`- Vite创建的Vue项目用
import.meta.env.BASE_URL拼接:
path = `${import.meta.env.BASE_URL}recordings/Behar/weekday/1.mp3` - Vue CLI创建的项目用
补充说明:history模式需要后端配置将所有页面请求重定向到
index.html,但该规则不会影响public目录下真实存在的静态资源请求,只要资源路径书写正确,后端会直接返回对应文件,不会进入前端路由逻辑。
内容的提问来源于stack exchange,提问作者etayluz
相关产品推荐
相关产品推荐

