6.0 KiB
6.0 KiB
✅ 解决 SPA 路由刷新 404 问题
🐛 问题描述
症状:
- 访问
https://sports.rucky.cn/music-rhythm正常 - 刷新页面后出现 404 Not Found 错误
- 可能出现双斜杠:
https://sports.rucky.cn//music-rhythm
🔍 问题原因
1. SPA 路由原理
单页应用(SPA)的路由是由前端 JavaScript 控制的:
首次访问 https://sports.rucky.cn
↓
服务器返回 index.html
↓
Vue Router 加载,解析路由
↓
点击链接 /music-rhythm
↓
Vue Router 更新 URL(不刷新页面)
↓
渲染 MusicRhythm 组件 ✅
2. 刷新页面时的问题
刷新 https://sports.rucky.cn/music-rhythm
↓
浏览器向服务器请求 /music-rhythm
↓
服务器找不到 music-rhythm 文件夹或文件
↓
返回 404 错误 ❌
✅ 解决方案
方案 1:Nginx 配置(推荐)
已创建配置文件:nginx.conf.example
关键配置:
location / {
try_files $uri $uri/ /index.html;
}
含义:
- 先尝试访问实际文件
$uri - 如果不存在,尝试访问目录
$uri/ - 如果还不存在,返回
index.html - 让 Vue Router 处理路由
完整配置步骤:
- 打开 Nginx 配置文件:
sudo nano /etc/nginx/sites-available/sports.rucky.cn
- 添加/修改配置:
server {
listen 443 ssl http2;
server_name sports.rucky.cn;
root /var/www/sports.rucky.cn;
index index.html;
# 关键:SPA 路由支持
location / {
try_files $uri $uri/ /index.html;
}
}
- 测试配置:
sudo nginx -t
- 重启 Nginx:
sudo systemctl restart nginx
方案 2:Apache 配置
已创建配置文件:public/.htaccess
关键配置:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
使用方法:
- 确保 Apache 启用了
mod_rewrite:
sudo a2enmod rewrite
sudo systemctl restart apache2
.htaccess文件会自动包含在构建中:
npm run build
# dist/public/.htaccess 会自动复制到 dist/
- 部署时确保
.htaccess文件在网站根目录
方案 3:Vercel/Netlify(自动处理)
如果使用这些平台,已创建 public/_redirects 文件:
/* /index.html 200
Vercel: 自动识别,无需额外配置
Netlify: 自动识别 _redirects 文件
🔧 前端优化
1. 路由配置已优化
const router = createRouter({
history: createWebHistory('/'), // 明确指定 base path
routes: [...],
})
2. 避免双斜杠问题
确保路由跳转时使用规范路径:
// ✅ 正确
router.push({ name: 'MusicRhythm' })
router.push('/music-rhythm')
// ❌ 避免
router.push('//music-rhythm')
🧪 测试步骤
本地测试
- 构建生产版本:
npm run build
- 使用本地服务器测试(模拟生产环境):
# 安装 serve
npm install -g serve
# 运行(支持 SPA)
serve -s dist
# 或使用 http-server
npm install -g http-server
http-server dist -p 8080 --proxy http://localhost:8080?
- 测试路由:
- 访问
http://localhost:3000/ - 点击进入音乐律动页面
- 刷新页面,应该正常显示,不会 404
- 访问
生产环境测试
- 部署到服务器
- 访问各个页面:
https://sports.rucky.cn/✅https://sports.rucky.cn/music-rhythm✅https://sports.rucky.cn/callback✅
- 在每个页面刷新,都应该正常显示
📋 检查清单
部署前确认:
- ✅ 服务器配置了 fallback 到 index.html
- ✅ 所有路由路径以
/开头,没有双斜杠 - ✅
vite.config.js没有错误的base配置 - ✅ 构建产物在正确的目录
- ✅ 测试了所有主要路由的刷新
🔍 调试技巧
1. 检查服务器日志
Nginx:
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log
Apache:
sudo tail -f /var/log/apache2/access.log
sudo tail -f /var/log/apache2/error.log
2. 浏览器开发者工具
- 打开 Network 标签
- 刷新页面
- 查看请求:
- 应该看到请求
/music-rhythm - 服务器应该返回
index.html(状态码 200) - 而不是 404
- 应该看到请求
3. 测试 curl
# 应该返回 index.html 内容
curl -I https://sports.rucky.cn/music-rhythm
# 检查响应头
HTTP/1.1 200 OK
Content-Type: text/html
🎯 常见错误
错误 1:双斜杠
问题: https://sports.rucky.cn//music-rhythm
原因: 代码中拼接路径时多加了斜杠
解决:
// ❌ 错误
const url = origin + '/' + path
// ✅ 正确
const url = origin + path // path 已经包含 /
// 或
const url = new URL(path, origin).href
错误 2:404 但本地正常
问题: 本地开发正常,生产环境 404
原因: Vite Dev Server 自动处理 SPA 路由,但生产服务器没有配置
解决: 按照上面的方案配置 Nginx/Apache
错误 3:子目录部署
问题: 部署在 https://example.com/app/ 子目录下
解决:
// vite.config.js
export default defineConfig({
base: '/app/',
})
// router.ts
const router = createRouter({
history: createWebHistory('/app/'),
})
📚 相关文档
✅ 总结
已完成:
- ✅ 优化前端路由配置
- ✅ 创建
.htaccess(Apache) - ✅ 创建
_redirects(Vercel/Netlify) - ✅ 提供
nginx.conf.example
你需要做:
- 根据你使用的服务器(Nginx/Apache)配置 fallback
- 重启服务器
- 测试刷新功能
完成后,所有路由刷新都应该正常工作!🎉