核心思路是:Vue3 构建后的静态文件放到 Laravel 的 public/ 目录下,通过 Laravel 路由的 catch-all 机制让 SPA 的前端路由正常工作。
方案说明
以 xx.com/admin 为例,整体架构如下:
请求流程:
xx.com/admin/* → Laravel 路由 catch-all → 返回 public/admin/index.html
xx.com/api/* → Laravel API 路由 → 正常返回 JSON
具体实施步骤
1. Vue3 项目构建配置
在 Vue3 项目的 vite.config.js(或 vue.config.js)中,设置 base 路径为 /admin/:
// vite.config.js (Vue3 项目)
export default defineConfig({
base: '/admin/', // 关键:让所有静态资源引用路径都以 /admin/ 开头
build: {
outDir: 'dist', // 构建输出目录
}
})
2. 将构建产物复制到 Laravel
执行 npm run build 后,将 dist/ 目录下的所有文件复制到 Laravel 项目的 public/admin/ 目录:
public/
├── admin/ ← Vue3 构建产物
│ ├── index.html
│ ├── assets/
│ │ ├── index-xxx.js
│ │ └── index-xxx.css
│ └── ...
├── index.php ← Laravel 入口
├── api/ ← (不需要,API 走路由)
└── ...
3. Laravel 路由配置(关键)
在 routes/web.php 中添加一个 catch-all 路由,将所有 /admin/* 请求指向 Vue 的 index.html:
// routes/web.php
// /admin 首页
Route::get('/admin', function () {
return file_get_contents(public_path('admin/index.html'));
});
// /admin 下的所有子路由(SPA 前端路由)
Route::get('/admin/{any}', function () {
return file_get_contents(public_path('admin/index.html'));
})->where('any', '.*');
这样做的效果:
xx.com/admin→ 返回 Vue 的index.htmlxx.com/admin/dashboard→ 同样返回index.html,由 Vue Router 在前端处理路由xx.com/admin/users/list→ 同样返回index.htmlxx.com/api/*→ 走 Laravel 正常 API 路由,不受影响
4. Vue3 中的 API 请求配置
在 Vue3 项目中,确保 API 请求指向同域的 /api/ 路径:
// axios 配置示例
const api = axios.create({
baseURL: '/api', // 同域名,无需跨域
withCredentials: true, // 携带 cookie/token
});
5. Nginx 配置(生产环境推荐)
如果你使用 Nginx,可以更高效地直接返回静态文件,而不经过 PHP:
# /admin 静态文件直接由 Nginx 处理(性能更好)
location /admin {
alias /path/to/jzcms-laravel/public/admin;
try_files $uri $uri/ /admin/index.html;
}
# /api 仍然走 PHP-FPM
location /api {
try_files $uri /index.php?$query_string;
}
优缺点对比
| 对比项 | 同域名(/admin) | 独立域名(admin.xx.com) |
|---|---|---|
| 跨域问题 | 无 | 需要配置 CORS |
| Cookie/Token | 天然共享 | 需要额外配置 |
| 部署复杂度 | 简单,一个项目 | 需要额外域名和 Nginx 配置 |
| 静态资源性能 | 可用 Nginx alias 优化 | 独立部署,天然高效 |
| SEO | 无影响(后台不需要 SEO) | 无影响 |
注意事项
- 路由优先级:确保
/admin的 catch-all 路由放在routes/web.php的最后,不要覆盖了 API 路由 - API 路由不受影响:Laravel 的 API 路由注册在
routes/api.php中,天然带/api前缀,和/admin不会冲突 - 404 处理:未匹配的
/admin/xxx路径应由 Vue Router 处理 404,而非 Laravel - CSRF 问题:如果你的 API 用的是 token 认证(如 Sanctum token),而非 session,则不会有 CSRF 问题
总结:同域名方案(xx.com/admin)完全可行且更简单,推荐使用。不需要给静态文件单独分配域名。