跳到主要内容

二级目录部署

二级目录部署是指通过 https://example.com/survey/ 访问 SurveyKing。它不仅是 Nginx 路径调整,还要求前端构建时同时使用匹配的路由前缀和资源前缀。

普通前端包不能直接改成二级目录

根目录版本默认使用 /pub//adm/。只在 Nginx 前增加 /survey/ 会导致 JavaScript、CSS、登录跳转和分享链接指向错误路径。请获取官方二级目录交付包,或在源码中按下表重新构建。

路径约定

下面以 /survey/ 为例:

内容路径
系统入口/survey/
public 构建资源/survey/pub/
admin 构建资源/survey/adm/
后端接口/survey/admin-api/
验证码接口/survey/captcha/

前端两个构建入口必须分别使用:

构建入口Umi baseUmi publicPath
public/survey//survey/pub/
admin/survey//survey/adm/

路径必须以 / 开头和结尾。修改目录名后重新构建,不能通过运行时字符串替换修改已生成文件。

部署前检查

假设前端文件位于:

/usr/local/nginx/html/dist/
├── public/index.html
└── admin/index.html

检查生成的 HTML 是否引用二级目录资源:

grep -Eo '/survey/(pub|adm)/' /usr/local/nginx/html/dist/public/index.html | head
grep -Eo '/survey/(pub|adm)/' /usr/local/nginx/html/dist/admin/index.html | head

如果没有输出,不要继续配置 Nginx,应先更换或重新构建前端包。

Nginx 生产配置

以下配置根据 nginx-survey-prod.conf 整理。将域名、二级目录、前端绝对路径和后端地址替换为实际值。map 必须放在 http {} 中。

map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

server {
listen 80;
server_name survey.example.com;
index index.html;
client_max_body_size 100m;

location = /survey {
return 301 /survey/;
}

location = /survey/pub {
return 301 /survey/pub/;
}

location = /survey/adm {
return 301 /survey/adm/;
}

# 入口 HTML 不缓存,避免升级后引用旧版资源。
location = /survey/pub/index.html {
root /usr/local/nginx/html/dist/public;
etag off;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
try_files /index.html =404;
}

location = /survey/adm/index.html {
root /usr/local/nginx/html/dist/admin;
etag off;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
try_files /index.html =404;
}

# 带 hash 的构建资源可以长期缓存。
location ^~ /survey/pub/ {
alias /usr/local/nginx/html/dist/public/;
expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable";
}

location ^~ /survey/adm/ {
alias /usr/local/nginx/html/dist/admin/;
expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable";
}

# 答题、练习、公开查询、数据分享和兑换页面使用 public 入口。
location ~ ^/survey/(e|s|t|q|share|redeem)(/|$) {
root /usr/local/nginx/html/dist/public;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
try_files /index.html =404;
}

# 登录、注册和绑定页面使用 public 入口。
location ~ ^/survey/user/(login|register|binding)/?$ {
root /usr/local/nginx/html/dist/public;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
try_files /index.html =404;
}

# 删除外部 /survey 前缀后转发给后端。
location ^~ /survey/captcha {
proxy_pass http://127.0.0.1:48080/captcha;
proxy_set_header Host $host;
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;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 1800s;
}

location ^~ /survey/admin-api {
proxy_pass http://127.0.0.1:48080/admin-api;
proxy_buffering off;
proxy_cache off;
proxy_set_header Host $host;
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;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_connect_timeout 60s;
proxy_read_timeout 1800s;
proxy_send_timeout 1800s;
}

# 其他二级目录页面使用 admin 入口。
location /survey/ {
root /usr/local/nginx/html/dist/admin;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
try_files /index.html =404;
}
}

配置 HTTPS 时复用同一组 location。不要分别维护内容不同的 HTTP 和 HTTPS 路由。

上游网关转发

如果统一门户或总行网关再转发到 SurveyKing Nginx,应保留 /survey/ 前缀:

location /survey/ {
proxy_pass http://192.168.10.20:58001;
proxy_set_header Host $host;
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;
}

proxy_pass 目标后不要添加 /。添加尾斜杠会删除匹配到的 /survey/ 前缀,导致下游路由失效。

下游 Nginx 已经处理 /survey/admin-api/survey/captcha 时,上游不需要再为接口创建另一套路径规则。

验证部署

nginx -t
systemctl reload nginx

curl -I http://127.0.0.1/survey/
curl -I http://127.0.0.1/survey/pub/index.html
curl -I http://127.0.0.1/survey/adm/index.html
curl -I http://127.0.0.1/survey/e/route-check
curl -I http://127.0.0.1/survey/s/route-check
curl -I http://127.0.0.1/survey/t/route-check
curl -I http://127.0.0.1/survey/q/route-check
curl -I http://127.0.0.1/survey/share/route-check
curl -I http://127.0.0.1/survey/redeem/route-check
curl -I http://127.0.0.1/survey/user/login

上述 public 页面应返回 HTTP 200。二级目录和根目录的路由归属相同,只是每个路径都增加 /survey 前缀:estqshareredeem 使用 public 入口,/survey/user/login|register|binding 也使用 public 入口,其他页面使用 admin 入口。

浏览器中继续验证:

  • 登录和退出后仍停留在 /survey/ 下。
  • 管理后台刷新不会返回 404。
  • 问卷、考试、练习、公开查询和分享链接都包含 /survey/
  • /survey/admin-api/ 请求能够到达后端。
  • 上传、预览和下载文件的域名及路径正确。

常见问题

页面能打开,但 JavaScript 和 CSS 返回 404

前端构建产物仍在引用 /pub//adm/。重新获取二级目录包或使用正确的 basepublicPath 构建。

登录后跳回域名根目录

检查前端路由 base、登录回调地址和第三方平台中的回调 URL,三者都必须包含 /survey/

接口请求出现双重 /survey/survey/

检查上游 proxy_pass 是否重复添加路径,以及前端 API 前缀是否已经包含 /survey

修改 Nginx 后仍显示旧页面

确认 index.html 禁止缓存,并清理浏览器、CDN 或统一门户缓存。带 hash 的 /survey/pub//survey/adm/ 资源可以保留长期缓存。