DCloud (UniCloud) 为开发者提供了一套非常便捷的云开发一体化解决方案,涵盖了前端开发、云函数、数据库、对象存储 (OSS)、内容分发网络 (CDN) 以及 Redis 缓存等。其中,“前端网页托管”功能允许开发者轻松部署静态网站或 H5 应用。
然而,在实际项目中,我们常常有这样的需求:在同一个 DCloud 服务空间内托管多个不同的前端项目(例如,不同的 H5 应用、管理后台等),并且希望通过不同的域名或路径来访问它们。虽然 DCloud 的前端网页托管本身提供了一个统一的访问地址(通常是 *.cloudstatic.cn),但直接使用这个地址来区分不同项目显得不够灵活和专业。
本文将介绍一种常见的解决方案:利用 Nginx 作为反向代理,将不同的域名请求转发到 DCloud 前端网页托管空间内的指定子目录,从而实现在单一 DCloud 空间下部署和访问多个独立前端项目。
挑战
- 单一入口: DCloud 前端网页托管提供一个根访问 URL,默认情况下所有内容都从根目录提供。
- 项目隔离: 需要一种机制将不同项目的构建产物(HTML, JS, CSS, 静态资源)隔离在不同的目录中。
- 域名映射: 需要将用户访问的不同域名(如
project-a.yourdomain.com,project-b.yourdomain.com)或路径(yourdomain.com/project-a/,yourdomain.com/project-b/)精确地指向 DCloud 空间中的对应项目目录。 - 资源路径: 前端应用(尤其是 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_passURL 末尾的/和location路径(这里是/)的组合决定了 URL 如何拼接。如果proxy_pass末尾没有/,行为会不同。对于代理到子目录的场景,通常location和proxy_pass都带/或都不带/(但带/更常见且清晰)。
proxy_set_header: 将原始请求的一些重要头部信息(如 Host, 客户端 IP)传递给后端(DCloud),这对于日志记录和某些后端逻辑可能很重要。
为其他项目(如 project-a.yourdomain.com)创建类似的 server 块,只需修改 server_name 和 proxy_pass URL 中的子目录名即可。
流程总结
- 在 DCloud 前端网页托管中为每个项目创建子目录。
- 配置 UniApp 项目的
manifest.json,设置正确的h5.router.base(根据需要) 和h5.publicPath(指向最终域名)。 - 构建 UniApp H5 项目。
- 将构建产物上传到 DCloud 对应的子目录。
- 在 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 提供的一体化托管服务,同时灵活地部署和管理多个独立的前端项目,满足更复杂的业务需求。