核心思路是: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.html
  • xx.com/admin/dashboard → 同样返回 index.html,由 Vue Router 在前端处理路由
  • xx.com/admin/users/list → 同样返回 index.html
  • xx.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) 无影响

注意事项

  1. 路由优先级:确保 /admin 的 catch-all 路由放在 routes/web.php最后,不要覆盖了 API 路由
  2. API 路由不受影响:Laravel 的 API 路由注册在 routes/api.php 中,天然带 /api 前缀,和 /admin 不会冲突
  3. 404 处理:未匹配的 /admin/xxx 路径应由 Vue Router 处理 404,而非 Laravel
  4. CSRF 问题:如果你的 API 用的是 token 认证(如 Sanctum token),而非 session,则不会有 CSRF 问题

总结:同域名方案(xx.com/admin)完全可行且更简单,推荐使用。不需要给静态文件单独分配域名。