写在最前

有时候,我们会把多个前端项目部署在同一个域名下,通过不同的路径后缀来访问。

但这样做往往会遇到一个问题,每个前端组件在打包后请求的静态资源路径都很相似,比如都是 /js/app.js/css/style.css,结果不同项目之间的资源可能会互相冲突或被错误加载。
要解决这个问题,就需要在 Nginx 层 根据访问路径制定规则,把不同的 URL 前缀(例如 /shop//user//report/)分别转发到对应的前端组件目录。
听起来简单,但如果没有在构建阶段区分好各项目的资源前缀,确实会让人头疼。

1. 解决思路

构建时修改每个项目的 publicPath(或 base)让每个项目的静态资源带上前缀路径。这样打包出来的资源会以 /shop/ 开头,不会和 /user/ 混淆。

// vite.config.ts
export default defineConfig({
  base: '/shop/',
})

2. Nginx 配置示例

适合纯主机方式部署

server {
    listen 80;
    server_name test.tanqidi.com;

    # 采购系统
    location /shop/ {
        alias /data/frontend/shop/;
        try_files $uri $uri/ /shop/index.html;
    }

    # 用户中心
    location /user/ {
        alias /data/frontend/user/;
        try_files $uri $uri/ /user/index.html;
    }

    # 报表系统
    location /report/ {
        alias /data/frontend/report/;
        try_files $uri $uri/ /report/index.html;
    }

    # 默认跳转
    location / {
        return 302 /shop/;
    }
}

3. Ingress 配置示例

kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: demo-ingress
  namespace: demo
  annotations:
    kubernetes.io/ingress.class: nginx
    kubesphere.io/creator: admin
    nginx.ingress.kubernetes.io/server-snippet: |
      # 通过不同的api前缀来转发请求到后端java服务
      location /api-user/ {
        rewrite ^/api-user/(.*)$ /$1 break;
        proxy_pass http://user-service.demo.svc.cluster.local:80;
        proxy_set_header Host $host;
      }
spec:
  tls:
    - hosts:
        - demo.example.com
      secretName: example-ssl-secret
  rules:
    - host: demo.example.com
      http:
        paths:
          - path: /web
            pathType: ImplementationSpecific
            backend:
              service:
                name: web-frontend
                port:
                  number: 80
          - path: /app
            pathType: ImplementationSpecific
            backend:
              service:
                name: app-frontend
                port:
                  number: 80
          - path: /
            pathType: ImplementationSpecific
            backend:
              service:
                name: admin-portal
                port:
                  number: 80

写在最后