文章目录
项目部署到子目录,路由跳转却到主域名下?正常能访问一刷新就404?——路由模式的困扰
今天在做项目部署到一个服务器子目录时,遇到了两个问题,这里做下记录
一、路由模式介绍
这里以Vue Router v4版本为例
在Vue Router v4版本有三种模式,官网已经做了详细介绍
Hash 模式
hash 模式是用 createWebHashHistory()
创建的:
import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
history: createWebHashHistory(),
routes: [
//...
],
})
它在内部传递的实际 URL 之前使用了一个哈希字符(#
)。由于这部分 URL 从未被发送到服务器,所以它不需要在服务器层面上进行任何特殊处理。不过,它在 SEO 中确实有不好的影响。如果你担心这个问题,可以使用 HTML5 模式。
Memory 模式
Memory 模式不会假定自己处于浏览器环境,因此不会与 URL 交互也不会自动触发初始导航。这使得它非常适合 Node 环境和 SSR。它是用 createMemoryHistory()
创建的,并且需要你在调用 app.use(router)
之后手动 push 到初始导航。
import { createRouter, createMemoryHistory } from 'vue-router'
const router = createRouter({
history: createMemoryHistory(),
routes: [
//...
],
})
虽然不推荐,你仍可以在浏览器应用程序中使用此模式,但请注意它不会有历史记录,这意味着你无法后退或前进。
HTML5 模式(v3版本中称为History模式)
用 createWebHistory()
创建 HTML5 模式,推荐使用这个模式:
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [
//...
],
})
当使用这种历史模式时,URL 会看起来很 “正常”,例如 https://example.com/user/id
。漂亮!
不过,问题来了。由于我们的应用是一个单页的客户端应用,如果没有适当的服务器配置,用户在浏览器中直接访问 https://example.com/user/id
,就会得到一个 404 错误。这就尴尬了。
不用担心:要解决这个问题,你需要做的就是在你的服务器上添加一个简单的回退路由。如果 URL 不匹配任何静态资源,它应提供与你的应用程序中的 index.html
相同的页面。漂亮依旧!
更详细参考官网介绍
二、遇到的问题
1.项目部署到子目录,路由跳转却到主域名下解决方法
如果是history模式,需要加上当前部署的子目录,
createWebHistory()方法可以传入base参数,官网如下介绍:
base:基准路径,它被预置到每个 URL 上。这允许在一个域名子文件夹中托管 SPA,例如将 base
设置为 /sub-folder
使得其托管在 example.com/sub-folder
。
所以代码如下:
//获取当前路径
let path = location.pathname.substring(0, location.pathname.lastIndexOf('/') + 1)
const router = createRouter({
history: createWebHistory(path),
routes: [
//...
],
});
!打包配置这里路径也需要注意下
这里我用的是vite
defineConfig中的base配置路径,有三种写法如下
- 绝对 URL 路径名,例如
/foo/
- 完整的 URL,例如
https://foo.com/
(原始的部分在开发环境中不会被使用) - 空字符串或
./
(用于嵌入形式的开发)
举例:
如果你的应用被部署在 https://www.xxxx/admin/,则设置 base可以设为为
'/admin/'
''
'./'
这三种其一即可
2.正常能访问一刷新就404解决方法
这个是因为没后端没进行配置,加载单页应用后路由改变均由浏览器处理,而刷新时将会请求当前的链接,而Nginx无法找到对应的页面
这时候需要在在Nginx配置文件nginx.conf中加入如下配置:
try_files $uri $uri/ /index.html;
这里做下举例:
location ^~/xxxx/ {
root /xx
try_files $uri $uri/ /index.html;
}
还有另一种方法可以同时解决上述两个问题,比如说就不想操作Nginx配置了,那就是更换称为hash模式
const router = createRouter({
history: createWebHashHistory(path),
routes: [
//...
],
});
但是会有一些缺点,如上面介绍,自行选择
更换称为hash模式
const router = createRouter({
history: createWebHashHistory(path),
routes: [
//...
],
});
但是会有一些缺点,如上面介绍,自行选择