前端工程化部署入门:Windows + Nginx 实现多项目独立托管与跨域解决方案

windows+nginx配置自己的前端项目

文章目录

前言

我在日常前端开发中,我常常会遇到一个令人头疼的问题:本地运行得好好的项目,一旦打包交给后端部署到 Nginx 上,就各种"水土不服"------页面白屏、静态资源 404、路由刷新 404、接口跨域......排查起来费时又费力。

为了减少前后端联调时的沟通成本,也为了避免反复打扰后端同事帮忙验证部署效果,我决定在自己的 Windows 开发机上搭建一套本地 Nginx 环境。这样,在将 dist 包交付给后端之前,我可以先在本地模拟真实的生产部署场景,提前发现并解决配置问题。

实践下来,这一招不仅大大缩短了上线前的调试时间,也让我对前端项目在 Nginx 中的部署机制有了更深入的理解。本文就来分享一下我在 Windows 上安装、配置 Nginx 并部署 Vue/React 等前端项目的完整流程,希望能帮助同样被部署问题困扰的你。

什么是 Nginx

Nginx(发音为 "engine-x")是一个开源的、高性能的 HTTP 服务器和反向代理服务器,同时也支持 IMAP/POP3/SMTP 等协议。 它最初由俄罗斯工程师 Igor Sysoev2004 年开发,旨在解决 C10K(并发连接一万)问题,如今已成为全球最流行的 Web 服务器之一【来源于百度】。

为什么前端项目要使用 Nginx 部署?

在现代Web 开发中,前端项目(如 Vue、React、Angular 等构建出的静态资源)虽然本质上只是一堆 HTML、CSS、JavaScript和图片文件,但直接通过浏览器打开 index.html 或用简单的本地服务器运行,并不能满足生产环境的需求。而 Nginx 凭借其高性能、轻量级和灵活的配置能力,成为了部署前端应用的事实标准。那么,为什么我们普遍选择 Nginx 来部署前端项目?主要有以下几个关键原因:

高效地提供静态资源服务

Nginx 是一个高性能的 HTTP 服务器,专为高并发、低内存消耗设计。它能以极快的速度响应对静态文件(如 .js、.css、.png 等)的请求,远优于 Node.js 的简易服务器(如 http-server)或开发服务器(如 Vite Dev Server),非常适合生产环境。

支持前端路由(History 模式)

Vue RouterReact Router 在使用 history 模式时,URL 不带 #,看起来更干净(如 /about)。但这类路由在用户直接访问或刷新页面时,会向服务器请求 /about 路径。

如果没有后端配合,服务器会返回 404
Nginx 可通过简单配置(如 try_files 指令),将所有未知路径 fallbackindex.html,让前端路由接管,从而完美支持 SPA(单页应用)。

javascript 复制代码
location / {
    try_files $uri $uri/ /index.html;
}

轻松实现反向代理,解决跨域问题

开发阶段,前端常因跨域无法直接调用后端 API。虽然可以通过 CORS 或代理解决,但在生产环境,我们通常希望前端和后端共用同一个域名。Nginx 可以将 /api 开头的请求代理到真正的后端服务,既隐藏了后端地址,又避免了跨域:

javascript 复制代码
location /api {
    proxy_pass http://backend-server:8080;
}

这样,前端只需请求 /api/userNginx 自动转发,浏览器认为是同源请求。

支持 HTTPS、Gzip 压缩、缓存等优化

  • HTTPSNginx 可轻松集成 SSL 证书,启用安全连接。
  • Gzip 压缩:自动压缩文本资源,减少传输体积,提升加载速度。
  • 缓存控制:通过设置 Cache-Control 头,合理利用浏览器缓存,提高二次访问性能。

轻量、稳定、社区成熟

Nginx 占用资源少,稳定性高,被全球数百万网站使用(包括 NetflixDropbox 等)。无论是小型项目还是高流量应用,它都能胜任。

前端根据Nginx部署web项目

第一步、下载

地址:https://nginx.org/en/download.html

选择windownginx进行点击下载,下载完成后建立一个nginx的目录,注意路径中不能包含中文。

第二步、目录解读

  • confignginx的配置文件,其中nginx.confnginx主配置文件,它包含了所有全局的nginx配置项。
  • contrib: 提供了nginx语法支持脚本。
  • docs:存放 nginx 服务器的主要文档资料。
  • htmlnginx默认静态资源路径。
  • logsnginx记录访问成功与失败日志。
  • temp:用于缓存用户上传或代理服务器接收的数据。
  • nginx.exewindows启动nginx可执行文件。

第三步、对部署项目进行打包

执行npm run build:prod后得到一个dist的包

第四步、配置nginxconf文件


完整代码

javascript 复制代码
#user  nobody;
worker_processes  1;
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#pid        logs/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';
    #access_log  logs/access.log  main;
    sendfile        on;
    #tcp_nopush     on;
    #keepalive_timeout  0;
    keepalive_timeout  65;
    #gzip  on;
    server {
        listen       8088;
        server_name  192.168.80.32; # 配置页面中访问的域名本机IP
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        # 配置页面中发送请求代理到后端接口
        location /api {
            # 需要代理访问的后端服务器地址
            proxy_pass http://192.168.80.31:8080;
            #重写以/api为baseURL的接口地址
            rewrite "^/api/(.*)$" /$1 break;
        }
        location / {
            root   E:\\Nginx\\nginx-1.28.0\\html; # 配置页面中访问的静态资源路径
            index  index.html index.htm; # 配置页面中访问的静态资源文件
            try_files $uri $uri/ /index.html; # 防止刷新404问题
        }
        #error_page  404              /404.html;
        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

配置好后,运行nginx,浏览器输入你的ip地址:端口号,就会出现如下界面,表示配置nginx成功

第五步、将上面dist的包解压到html文件夹中


第六步、启动Nginx查看效果

进入nginx-1.28.0目录下,使用 start nginx.exe或者双击nginx.exe图标即可部署完成查看效果,效果如下代表部署成功,浏览器输入【IP地址:端口号】即可访问。

nginx常见命令

javascript 复制代码
nginx -t                # 测试配置
nginx -s reload         # 重载配置(改完必用!)
nginx -s stop           # 停止服务
nginx -v                # 查看版本
tail -f logs/error.log  # 实时看错误日志

nginx.conf配置说明

nginx.confNginx 的主配置文件,它采用分层块结构(block-based),通过一系列指令(directives) 控制 Nginx 的行为。下面为你系统、清晰地梳理 nginx.conf 中所有关键参数的说明,特别聚焦于前端开发者最常接触和需要理解的部分。

javascript 复制代码
main → events / http → server → location

全局块(main)

作用于整个 Nginx实例,对于前端开发来说通常无需修改

参数 说明 示例
user Nginx 工作进程运行的用户(Linux/macOS user nginx;
worker_processes 工作进程数,建议设为 auto(等于 CPU 核心数 worker_processes auto;
error_log 全局错误日志路径和级别(debug/info/notice/warn/error/crit error_log /var/log/nginx/error.log warn;
pid 主进程 PID 文件路径 pid /run/nginx.pid;
include 引入其他配置文件 include /etc/nginx/modules-enabled/*.conf;

events 块(网络连接处)

参数 说明
worker_conections 单个工作进程可同时处理的最大连接数(默认512~1024
use 事件模型(如epoll(linux)kqueue(macOs)),一般情况下自动选择
javascript 复制代码
events {
    worker_connections  1024;
}

http 块(最重要)

日志相关(调试必备)

javascript 复制代码
$remote_addr:客户端 IP
$time_local:请求时间
$request:完整请求行(如 GET /index.html HTTP/1.1)
$status:HTTP 状态码(200, 404, 502...)
$body_bytes_sent:发送字节数
$http_referer:来源页面
$http_user_agent:浏览器标识

server 块(虚拟主机)

每个 server 对应一个网站(可基于端口或域名区分)。

location 块(URL 路由匹配)前端部署的核心!

  • 匹配规则:

  • 关键指令:

  • 真实部署案例

    javascript 复制代码
    # 支持 Vue/React History 路由
    location / {
        root /dist;
        try_files $uri $uri/ /index.html;
    }
    
    # 代理 API 解决跨域
    location /api {
        proxy_pass http://backend:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    # 静态资源长期缓存
    location ~* \.(js|css|png|jpg|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

常用内置变量(可在配置中使用)

总结

nginx.conf 虽然看起来复杂,但作为前端,你只需重点关注:

http 块中的 gzip、log、sendfile

server 块中的 listen、server_name、root

location 块中的 try_files、proxy_pass、expires

Vue/React 项目专用 nginx.conf 模板

通用模板

javascript 复制代码
# ======================
# 全局配置
# ======================
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /run/nginx.pid;

# ======================
# events 块
# ======================
events {
    worker_connections  1024;
}

# ======================
# HTTP 配置(核心)
# ======================
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    # 日志格式
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    # 高性能传输
    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;
    keepalive_timeout  65;

    # ======================
    # Gzip 压缩(大幅提升加载速度)
    # ======================
    gzip  on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/json
        application/javascript
        application/xml+rss
        application/rss+xml
        application/atom+xml
        application/x-javascript
        font/ttf
        font/otf
        font/x-woff
        font/woff
        font/woff2
        image/svg+xml;

    # ======================
    # 安全与缓存优化
    # ======================
    # 隐藏 Nginx 版本号
    server_tokens off;

    # 添加安全头(可选)
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    # 注意:CSP 头建议按需添加,避免阻断资源

    # ======================
    # 前端项目 Server 配置
    # ======================
    server {
        listen       80;
        server_name  localhost;  # 替换为你的域名,如 example.com

        #  替换为你项目的 dist 目录绝对路径
        root   /usr/share/nginx/html;  # Vue: dist, React: build
        index  index.html;

        # ======================
        # 静态资源长期缓存(适用于带 hash 的文件)
        # 如:app.a1b2c3.js → 可安全缓存 1 年
        # ======================
        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
        }

        # ======================
        # API 反向代理(解决开发/生产跨域)
        # 前端请求 /api/xxx → 代理到后端 http://backend:8080/xxx
        # ======================
        location /api {
            proxy_pass http://localhost:8080;  #  替换为你的后端地址
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            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_cache_bypass $http_upgrade;
        }

        # ======================
        # SPA 路由支持(Vue Router history 模式 / React Router)
        # 所有非静态资源请求 fallback 到 index.html
        # ======================
        location / {
            try_files $uri $uri/ /index.html;
        }

        # ======================
        # 可选:强制 HTTPS(取消注释并配置 SSL 后使用)
        # ======================
        # listen 443 ssl;
        # ssl_certificate /path/to/fullchain.pem;
        # ssl_certificate_key /path/to/privkey.pem;
        # ssl_protocols TLSv1.2 TLSv1.3;
        # ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
        # ssl_prefer_server_ciphers off;
    }
}

使用说明

  • 修改关键路径root /usr/share/nginx/html;

    javascript 复制代码
    → 替换为你的项目构建输出目录,例如:
    Windows: root C:/my-project/dist;
    macOS: root /Users/yourname/project/build;
    Linux: root /home/user/my-react-app/build;
  • 修改 API 代理地址proxy_pass http://localhost:8080;

    javascript 复制代码
    → 改为你的后端服务地址(如 http://192.168.1.100:3000 或 http://backend-service)
  • 部署步骤

    javascript 复制代码
    # 1. 测试配置是否正确
    nginx -t
    
    # 2. 重载配置(无需重启)
    nginx -s reload
  • 我使用windos部署出现的问题

    javascript 复制代码
    1. 路径使用正斜杠 / 或双反斜杠 \\
    2. 示例:root C:/nginx/html/my-vue-app;
    3. 日志路径也需调整(默认在 nginx/logs/)
  • 如果你用Docker,可在 Dockerfile 中复制此配置:

    javascript 复制代码
    FROM nginx:alpine
    COPY nginx.conf /etc/nginx/nginx.conf
    COPY dist/ /usr/share/nginx/html
    EXPOSE 80

ngxin多项目路径共存配置(如 /app1, /app2)区分项目

其实在实际开发或企业环境中,多个前端项目共用一个 Nginx 服务器(甚至同一个域名) 是非常常见的需求。例如:

javascript 复制代码
https://example.com/app1 → 项目 A(Vue)
https://example.com/app2 → 项目 B(React)
https://example.com/admin → 后台管理系统

假设你有以下三个前端项目,均已构建(dist 或 build 目录):

路径 项目类型 构建输出目录
/app1 Vue 3 (Vite) /var/www/app1/dist
/app2 React (CRA) /var/www/app2/build
/admin Angular /var/www/admin/dist

目标:通过 https://your-domain.com/app1 等路径访问各自应用,且各自支持 History 路由。

javascript 复制代码
# ======================
# 全局 & events(略,同前)
# ======================
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    access_log /var/log/nginx/access.log main;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;

    # Gzip 压缩(略,可复用前文配置)
    gzip on;
    gzip_types text/css application/javascript application/json image/svg+xml;

    # 安全头
    server_tokens off;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;

    # ======================
    # HTTP → HTTPS 强制跳转
    # ======================
    server {
        listen 80;
        server_name example.com;  # 替换为你的域名

        location /.well-known/acme-challenge/ {
            root /var/www/certbot;
        }

        location / {
            return 301 https://$host$request_uri;
        }
    }

    # ======================
    # HTTPS 主服务器(多项目共存)
    # ======================
    server {
        listen 443 ssl http2;
        server_name example.com;  # 替换为你的域名

        # SSL 证书(Let's Encrypt 示例)
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
        ssl_prefer_server_ciphers off;

        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

        # ======================
        # 项目 1: /app1 (Vue)
        # ======================
        location /app1 {
            alias /var/www/app1/dist;  # 注意:用 alias,不是 root!

            # 静态资源缓存
            location ~* \.(js|css|png|jpg|woff2)$ {
                expires 1y;
                add_header Cache-Control "public, immutable";
            }

            # SPA 路由支持
            try_files $uri $uri/ /app1/index.html;
        }

        # ======================
        # 项目 2: /app2 (React)
        # ======================
        location /app2 {
            alias /var/www/app2/build;

            location ~* \.(js|css|png|jpg|woff2)$ {
                expires 1y;
                add_header Cache-Control "public, immutable";
            }

            try_files $uri $uri/ /app2/index.html;
        }

        # ======================
        # 项目 3: /admin (Angular)
        # ======================
        location /admin {
            alias /var/www/admin/dist;

            location ~* \.(js|css|png|jpg|woff2)$ {
                expires 1y;
                add_header Cache-Control "public, immutable";
            }

            try_files $uri $uri/ /admin/index.html;
        }

        # ======================
        # 可选:根路径跳转到某个项目
        # ======================
        location = / {
            return 302 /app1;
        }

        # ======================
        # 可选:全局 API 代理(如 /api → 后端)
        # ======================
        location /api {
            proxy_pass http://backend:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

为什么用 alias 而不是 root?

  • root会拼接完整路径:

    javascript 复制代码
    root /a; location /app1 → /a/app1/file
  • alias 会替换前缀:

    javascript 复制代码
    alias /a; location /app1 → /a/file

如果你用 root,会导致 Nginx 去找/var/www/app1/dist/app1/index.html(多了一层),从而 404!

try_files 中的路径必须带前缀

try_files $uri $uri/ /app1/index.html;因为请求 /app1/aboutNginx 需要 fallback/app1/index.html,而不是根目录的 index.html

嵌套 location 实现资源缓存

/app1 内部再定义 location ~* \.(js|css),确保只对该项目资源生效

路径设计建议

所有前端项目构建时,设置正确的 base 路径:

  • Vue (Vite): base: '/app1/' in vite.config.js
  • React (CRA): "homepage": "/app2" in package.json
  • Angular: base href="/admin/" in index.html

否则,JS/CSS 资源会请求根路径(如 /assets/app.js),导致 404

通过 子域名(a.example.com / b.example.com)来隔离多个前端项目

通过 子域名(如 app1.example.comapp2.example.com) 来隔离多个前端项目,是实现完全独立部署、品牌隔离、权限分离和 SEO 优化的常用方案。每个子域名可视为一个独立站点,拥有自己的:

  • 根路径(root
  • SSL 证书(或共享通配符证书)
  • 日志文件
  • 缓存策略
  • 安全头配置

案例模板

你有以下三个前端项目:

子域名 项目类型 构建输出目录
app1.example.com Vue 3 /var/www/app1/dist
app2.example.com React /var/www/app2/build
admin.example.com Angular /var/www/admin/dist

目标:每个子域名独立访问,互不影响。

javascript 复制代码
# ======================
# 全局 & events(略)
# ======================
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    log_format main '$host $remote_addr - [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent"';

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;

    gzip on;
    gzip_types text/css application/javascript application/json image/svg+xml;

    server_tokens off;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;

    # ======================
    # HTTP → HTTPS 跳转(通用)
    # ======================
    server {
        listen 80;
        server_name ~^(.+\.)*example\.com$;  # 匹配所有 *.example.com

        location /.well-known/acme-challenge/ {
            root /var/www/certbot;
        }

        location / {
            return 301 https://$host$request_uri;
        }
    }

    # ======================
    # 子域名 1: app1.example.com (Vue)
    # ======================
    server {
        listen 443 ssl http2;
        server_name app1.example.com;

        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;      # 通配符或 SAN 证书
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
        ssl_prefer_server_ciphers off;

        add_header Strict-Transport-Security "max-age=31536000" always;

        # 独立日志(便于排查)
        access_log /var/log/nginx/app1.access.log main;
        error_log  /var/log/nginx/app1.error.log warn;

        # 根目录(直接指向 dist)
        root /var/www/app1/dist;
        index index.html;

        # 静态资源缓存
        location ~* \.(js|css|png|jpg|woff2|svg)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
        }

        # SPA 路由支持
        location / {
            try_files $uri $uri/ /index.html;
        }

        # 可选:专属 API 代理
        location /api {
            proxy_pass http://backend-app1:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }

    # ======================
    # 子域名 2: app2.example.com (React)
    # ======================
    server {
        listen 443 ssl http2;
        server_name app2.example.com;

        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
        ssl_prefer_server_ciphers off;

        add_header Strict-Transport-Security "max-age=31536000" always;

        access_log /var/log/nginx/app2.access.log main;
        error_log  /var/log/nginx/app2.error.log warn;

        root /var/www/app2/build;
        index index.html;

        location ~* \.(js|css|png|jpg|woff2|svg)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
        }

        location / {
            try_files $uri $uri/ /index.html;
        }

        location /api {
            proxy_pass http://backend-app2:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }

    # ======================
    # 子域名 3: admin.example.com (Angular)
    # ======================
    server {
        listen 443 ssl http2;
        server_name admin.example.com;

        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
        ssl_prefer_server_ciphers off;

        add_header Strict-Transport-Security "max-age=31536000" always;

        access_log /var/log/nginx/admin.access.log main;
        error_log  /var/log/nginx/admin.error.log warn;

        root /var/www/admin/dist;
        index index.html;

        location ~* \.(js|css|png|jpg|woff2|svg)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
        }

        location / {
            try_files $uri $uri/ /index.html;
        }
    }
}

子域名的优点

  • 完全独立

    每个 server 块独立配置 root、日志、代理、缓存策略,一个项目出问题,不影响其他子域名

  • SSL 证书方案

    推荐使用通配符证书:*.example.com,一张证书覆盖所有子域名,Let's Encrypt 支持(需 DNS 验证)或使用 SAN(Subject Alternative Name)证书,手动添加多个子域名Let's Encrypt 通配符申请示例:

    javascript 复制代码
    certbot certonly --manual --preferred-challenges=dns -d '*.example.com' -d example.com
  • 前端构建无需 base 路径因为每个子域名是"根站点",所以:

    javascript 复制代码
    Vue: base: '/'(默认)
    React: "homepage": "." 或省略
    Angular: <base href="/">

    资源路径如 /assets/app.js 直接生效

  • 独立日志
    /var/log/nginx/app1.access.log 只记录 app1.example.com 的请求,便于监控、审计和故障排查

  • SEO 与品牌友好
    app1.example.com 可作为独立产品品牌,搜索引擎视为独立站点,利于 SEO

子域名部署前提

  • DNS 解析

    javascript 复制代码
    在域名服务商添加 A 记录:
    app1    → 你的服务器 IP
    app2    → 你的服务器 IP
    admin   → 你的服务器 IP
    或使用通配符记录:`*.example.com → IP`
  • 防火墙:开放 80443 端口

  • 文件权限:确保 Nginx 用户(如 nginxwww-data)有权限读取 /var/www/... 目录

路径 vs 子域名【对比】

特性 路径隔离(/app1) 子域名隔离(app1.example.com
部署复杂度 简单 中等(需 DNS + 证书)
SSL 证书 单张即可 需通配符或 SAN
前端构建 需设置 base 无需特殊配置
品牌独立性
Cookie 隔离 同域共享(需 path 自动隔离
SEO 视为同一站点 独立站点
适用场景 内部系统、管理后台 多产品线、SaaS、客户门户

如上一大堆总结

小团队可用路径方案快速上线;中大型产品建议用子域名。

常见问题【含解决方案】


相关推荐
江城开朗的豌豆2 小时前
阿里邮件下载器使用说明
前端
半兽先生2 小时前
Web 项目地图选型指南:从 Leaflet 到 MapTalks,如何选择合适的地图引擎?
前端
hssfscv2 小时前
Javaweb 学习笔记——html+css
前端·笔记·学习
Mr.Jessy2 小时前
JavaScript高级:深浅拷贝、异常处理、防抖及节流
开发语言·前端·javascript·学习
唐叔在学习3 小时前
30s让ai编写「跳过外链中转页」的油猴脚本
前端·javascript
酸菜土狗3 小时前
🔥 纯 JS 实现 SQL 字段智能解析工具类,前端也能玩转 SQL 解析
前端
wo不是黄蓉3 小时前
脚手架步骤流程
前端
Evan芙3 小时前
nginx核心配置总结,并实现nginx多虚拟主机
运维·数据库·nginx