独立域名部署(前台在 A,Halo 在 B)

前提(API)

  • 浏览器只访问前台域名
  • 路径 /plugins/dishes/public/(前台默认)必须由 Nginx 反代到 Halo

域名示例

  • 前台:https://menu.example.com
  • Halo:https://blog.example.com

前端环境变量

构建打包时请把示例中的 blog.example.com 换成你的 Halo 主站根地址(无尾部斜杠)。

VITE_ASSET_BASE=/

# 前台挂在域名根目录(打开即首页)时填 /
VITE_PUBLIC_BASE=/

# 独立站必填:Halo 主站根地址(无尾部斜杠),将接口返回的 /upload/... 解析到主站,避免菜品图片资源 404
VITE_MEDIA_ORIGIN=https://blog.example.com

附件图片 /upload/

接口返回的菜品图等常为站点相对路径 /upload/...。独立部署时若仍用当前前台域名请求,会落在无文件的站点上。请统一在 web-frontend/.env.production 配置 VITE_MEDIA_ORIGIN 为主站根地址(无尾部斜杠),构建后前端会把 /upload/ 资源指向 Halo。

其它说明

  • Nginx 反代示例见下文「Nginx 参考配置」(API /plugins/dishes/public/;附件通过 VITE_MEDIA_ORIGIN 指到主站)。
  • 插件后台「前台域名白名单」仍用于服务端校验请求来源。

场景 B:子路径部署

web-frontend/.env.production

VITE_ASSET_BASE=/dishes/
VITE_PUBLIC_BASE=/dishes/
  • VITE_ASSET_BASEVITE_PUBLIC_BASE 必须以 / 开头并以 / 结尾,并与 Nginx 中前台子路径一致。
  • API 仍须在同一前台域名下反代 /plugins/dishes/public/ 到 Halo。

构建前台

  • 插件内嵌、同域使用:不必单独跑 web-frontend / ui 的构建命令,用上面的 Gradle 即可。
  • 独立域名或子路径单独托管前台:在 web-frontend 目录额外执行:
pnpm install
pnpm build

产物目录:web-frontend/build/dist


Nginx 参考配置

独立前台部署必须通过反向代理:浏览器只访问前台域名,由 Nginx 将 /plugins/dishes/public/ 转发到 Halo,避免跨域与 Cookie 问题。

默认走 /plugins/dishes/public/...(与匿名 RBAC 一致)。独立静态页无 Thymeleaf CSRF 时,代码会在 POST 前先 GET /access/status 以触发 XSRF-TOKEN;若仍 403,请确认反代未丢弃 Set-Cookie

独立域名(根路径)示例

server {
    listen 80;
    server_name menu.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name menu.example.com;

    # 前台静态文件目录(替换为你的实际路径)
    root /var/www/dishes-frontend;
    index index.html;

    # SPA 路由回退
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 代理插件公共 API 到 Halo 主站
    location /plugins/dishes/public/ {
        proxy_pass https://blog.example.com/plugins/dishes/public/;
        proxy_http_version 1.1;
        proxy_set_header Host blog.example.com;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

验证与排错

  • 页面静态资源可正常加载(无 404)。
  • 浏览器网络面板中,API 请求路径为 /plugins/dishes/public/...(默认)。
  • API 请求返回 JSON(不是 HTML 登录页)。若出现 /login?authentication_required 且 404,多为误将 API 指到 /apis/plugins/... 且被 Halo 要求登录;请改回默认前缀并反代 /plugins/dishes/public/。若 POST 403,检查 CSRF Cookie 是否被反代/浏览器拦截。
  • 若出现跨域报错,说明 API 仍指向了 Halo 绝对地址或未配置反代;应确保请求 URL 为前台域名下的上述路径。
  • 若你希望 API 走自定义前缀(如 /dishes-api/),可设置 VITE_API_PREFIX 并同步修改 Nginx location