使用 Nginx 代理 DCloud 前端网页托管实现多项目部署

475 阅读5分钟

DCloud (UniCloud) 为开发者提供了一套非常便捷的云开发一体化解决方案,涵盖了前端开发、云函数、数据库、对象存储 (OSS)、内容分发网络 (CDN) 以及 Redis 缓存等。其中,“前端网页托管”功能允许开发者轻松部署静态网站或 H5 应用。

然而,在实际项目中,我们常常有这样的需求:在同一个 DCloud 服务空间内托管多个不同的前端项目(例如,不同的 H5 应用、管理后台等),并且希望通过不同的域名或路径来访问它们。虽然 DCloud 的前端网页托管本身提供了一个统一的访问地址(通常是 *.cloudstatic.cn),但直接使用这个地址来区分不同项目显得不够灵活和专业。

本文将介绍一种常见的解决方案:利用 Nginx 作为反向代理,将不同的域名请求转发到 DCloud 前端网页托管空间内的指定子目录,从而实现在单一 DCloud 空间下部署和访问多个独立前端项目。

挑战

  1. 单一入口: DCloud 前端网页托管提供一个根访问 URL,默认情况下所有内容都从根目录提供。
  2. 项目隔离: 需要一种机制将不同项目的构建产物(HTML, JS, CSS, 静态资源)隔离在不同的目录中。
  3. 域名映射: 需要将用户访问的不同域名(如 project-a.yourdomain.com, project-b.yourdomain.com)或路径(yourdomain.com/project-a/, yourdomain.com/project-b/)精确地指向 DCloud 空间中的对应项目目录。
  4. 资源路径: 前端应用(尤其是 SPA 单页应用)需要正确配置其资源加载路径 (publicPath) 和路由基准路径 (router base),以确保在代理后能正常工作。

解决方案:Nginx 反向代理

Nginx 是一款高性能的 Web 服务器和反向代理服务器。通过配置 Nginx,我们可以拦截指向特定域名的 HTTP/HTTPS 请求,并将这些请求智能地转发给后端的 DCloud 前端网页托管地址,同时重写 URL,使其指向正确的子目录。

实现步骤

1. DCloud 前端网页托管目录规划

首先,在你的 DCloud 服务空间的“前端网页托管”中规划好目录结构。为每个项目创建一个独立的子目录。例如:

/
|-- project-a/
|   |-- index.html
|   |-- static/
|   |-- ... (其他构建文件)
|-- project-b/
|   |-- index.html
|   |-- static/
|   |-- ... (其他构建文件)

2. UniApp/H5 项目配置 (manifest.json)

对于使用 HBuilderX 开发的 UniApp 项目,需要修改 manifest.json 文件,以确保应用在部署后能正确处理路由和资源加载。关键配置项位于 h5 节点下:

project-a 项目为例,配置如下:

// manifest.json
{
    // ... 其他配置 ...
    "h5" : {
        "router" : {
            // 重要:设置路由模式为 hash 。
            //   并设置 base,使其与你在 DCloud 托管的子目录名一致
            // 注意:这里的 base 是给前端路由使用的,尤其是 hash 模式下的 # 后面的部分。
            // 如果你的 Nginx 配置是将域名直接映射到子目录,并且应用内部路由不依赖特定 base
            // 例子中 base 设置为 "/project-a",意味着访问路径会是 https://project-a.yourdomain.com/#/project-a/your-route
            "base" : "/project-a", // 根据实际路由需求调整
            "mode" : "hash"     // hash 模式通常更容易在子目录下部署
        },
        // 重要:设置 publicPath 为你的 Nginx 代理域名
        // 这样,应用请求 JS、CSS、图片等资源时会使用正确的域名。末尾的 "/" 很重要。
        "publicPath" : "https://project-a.yourdomain.com/",
        "optimization" : {
            "treeShaking" : {
                "enable" : false
            }
        },
        // ... 其他 H5 配置 ...
    }
    // ... 其他配置 ...
}

关键点解释:

  • router.mode: 推荐使用 hash 模式。History 模式在子目录下部署时,Nginx 需要额外配置 try_files 来处理刷新页面时 404 的问题。Hash 模式相对简单。
  • router.base: 这个值会影响 Vue Router (或其他路由库) 生成的 URL 基路径。如果 Nginx 将 yourdomain.com/ 代理到 DCloud 的 /your-project/ 目录,并且你希望应用的内部路由从 / 开始(如 yourdomain.com/#/home),那么 base 通常应设为 /。如果设为 /your-project,则路由会变成 yourdomain.com/#/your-project/home。你需要根据应用的实际路由逻辑和 Nginx 配置来决定。
  • publicPath: 极其重要。它告诉 Webpack (UniApp 使用的打包工具) 构建后静态资源(JS, CSS, 图片等)的最终访问路径前缀。这里必须设置为你通过 Nginx 暴露给用户的最终访问域名,并以 / 结尾。

配置完成后,使用 HBuilderX 发行 H5 包,并将构建产物上传到 DCloud 前端网页托管对应的子目录(例如,partorgs 目录)。确保在 HBuilderX 的发行配置中,正确设置了“网站域名”为你的最终访问域名(如 partorgs.listlive.cn),但这主要影响 publicPath,我们已经在 manifest.json 中手动指定了。上传时,选择正确的服务空间,并指定上传到对应的子目录

3. Nginx 配置

在你的 Nginx 服务器上,为每个项目配置一个 server 块。以下我们同样以 project-a.yourdomain.com 的配置示例,并稍作解释:

server {
    listen 443 ssl http2; # 建议启用 http2
    server_name project-a.yourdomain.com; # 监听的域名

    # 核心代理配置
    location / { 
        rewrite ^/$ /index.html permanent;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # 保持 Host 头,让 DCloud (如果需要) 知道原始请求域名,
        # 如果你没做重写,这个 host 可能就需要写死使用你云空间本身
        域名的了。
        proxy_set_header Host $host;

        proxy_socket_keepalive on; 
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        # 它表示将 Nginx location 的 `/` 映射到 proxy_pass URL 的 `/project-a/`
        # 例如:请求 /a/b 会被代理到 .../partorgs/a/b
        # 这个域名是云空间的地址
        proxy_pass https://env-test-static.normal.cloudstatic.cn/project-a/;
    }

    # 因为打包上传都加了目前名, 所以访问起来域名会变成
    # https://yourdomain.com/project-a/文件
    # 所以我们需要直接代理它就行了。
    location /project-a { 
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host; # 同上

        proxy_socket_keepalive on; 
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass https://env-test-static.normal.cloudstatic.cn; # 同上
    }
}

关键点解释:

  • listen 443 ssl http2;: 监听 HTTPS 端口 443,并启用 SSL 和 HTTP/2。
  • server_name: 必须与你的域名完全匹配。
  • ssl_certificate & ssl_certificate_key: 指定你的 SSL 证书和私钥文件路径。你需要事先获取并配置好证书(例如使用 Let's Encrypt)。
  • location /: 匹配此域名的所有请求。
  • proxy_pass https://env-....cloudstatic.cn/project-a/;: 核心指令
    • 将请求转发给 DCloud 前端托管地址。
    • URL 末尾的项目子目录 /project-a/ 至关重要。它告诉 Nginx 将 location / 匹配到的路径附加到这个 URL 后面。例如,访问 project-a.yourdomain.com/static/js/app.js 会被 Nginx 代理到 https://env-....cloudstatic.cn/project-a/static/js/app.js
    • proxy_pass URL 末尾的 /location 路径(这里是 /)的组合决定了 URL 如何拼接。如果 proxy_pass 末尾没有 /,行为会不同。对于代理到子目录的场景,通常 locationproxy_pass 都带 / 或都不带 /(但带 / 更常见且清晰)。
  • proxy_set_header: 将原始请求的一些重要头部信息(如 Host, 客户端 IP)传递给后端(DCloud),这对于日志记录和某些后端逻辑可能很重要。

为其他项目(如 project-a.yourdomain.com)创建类似的 server 块,只需修改 server_nameproxy_pass URL 中的子目录名即可。

流程总结

  1. 在 DCloud 前端网页托管中为每个项目创建子目录。
  2. 配置 UniApp 项目的 manifest.json,设置正确的 h5.router.base (根据需要) 和 h5.publicPath (指向最终域名)。
  3. 构建 UniApp H5 项目。
  4. 将构建产物上传到 DCloud 对应的子目录。
  5. 在 Nginx 中为每个项目配置 server 块,使用 proxy_pass 指向 DCloud 托管地址的相应子目录。

优点

  • 专业性: 使用自定义域名访问项目,更显专业。
  • 成本效益: 无需为每个小项目单独购买和管理 DCloud 服务空间。
  • 管理集中: 在一个 Nginx 实例中管理多个前端项目的入口。
  • 灵活性: Nginx 提供了强大的路由、重写、缓存、限流等功能,可以按需配置。

注意事项

  • SSL 证书: 需要为你的域名配置有效的 SSL 证书。
  • Nginx 性能: 确保 Nginx 服务器有足够的资源处理并发请求。
  • 缓存: 浏览器或 CDN 缓存可能会导致更新不及时,必要时需要清理缓存。
  • DCloud 地址: DCloud 的 *.cloudstatic.cn 地址可能会变化(尽管通常比较稳定),如果发生变化,需要同步更新 Nginx 配置。
  • History 模式路由: 如果使用 History 模式,Nginx 需要额外配置 try_files $uri $uri/ /index.html; (或类似规则) 来确保刷新页面时能正确加载 index.html

通过这种 Nginx 反向代理的方式,你可以有效地利用 DCloud 提供的一体化托管服务,同时灵活地部署和管理多个独立的前端项目,满足更复杂的业务需求。