feat(h5): H5 交给后端托管 + 修掉"相对地址在 uni.request 下失败"
背景:配好了花生壳穿透 http://394nb68658le.vicp.fun → 本机 8080。 但 H5 原来跑在 127.0.0.1:5174,手机访问不到 —— 所以把 H5 静态文件 交给后端一起服务(同一个域名)。这样顺带也不再需要 CORS, 而且正是正式部署的形态。 改动: · application-dev.yml 加 spring.web.resources.static-locations, 默认指向 frontend-mp/dist/build/h5/,可用 H5_STATIC_DIR 覆盖。 ⚠️ 前缀必须是 spring.(我一开始写成了 fill.,表现是"页面 404 而应用 照常启动、没有任何报错")。 · fill.mp-h5.callback-url / h5-base-url 改成穿透域名。 · config/index.ts:API 地址按端区分(api 地址两端策略不同,写死一个值 一定会在某一边出错): H5 → location.origin(绝对同源) 小程序 → http://localhost:8080(没有"同域"概念,必须绝对地址) 用 uni-app 条件编译区分,而不是运行期判断(后者会把两套地址都打进包里)。 ⚠️ 修掉一个只在真实穿透下才会暴露的 bug: · 原来 H5 硬编码 http://localhost:8080。从公网域名打开时变成跨域请求 → 被 CORS 拦 → 页面显示"网络请求失败",而**从本机打开却是好的**。这个 bug 只有走真实 穿透/真机才会暴露 —— 这正是"要在真环境验证"的价值。 · 改成相对路径后**仍然失败**(request:fail),但同样地址用原生 XHR / fetch 都是 200。也就是说这是 uni.request 自身对相对路径的处理差异,不是服务端 或跨域问题 —— 而它长得像"网络不通",很容易往 CORS / 域名 / 后端去查,白绕一大圈。 最终用 location.origin(绝对同源)绕开。 验证:经公网 http://394nb68658le.vicp.fun/?scene=t1-k17 → 显示「示范职业学校 / 2026年9月机电专业认定材料收集 / 尚未发布」, 无头浏览器截图确认(不依赖人工)。 ※ 首次加载约 27 秒 —— 穿透的带宽限制(花生壳免费档),不是代码问题。
This commit is contained in:
@@ -1,23 +1,40 @@
|
||||
/**
|
||||
* 小程序端配置。
|
||||
* API 地址。
|
||||
*
|
||||
* ⚠️ API 地址在三种场景下不一样,写死会导致"开发者工具里好好的,真机打不开":
|
||||
* ⚠️ **H5 与小程序必须用不同的策略**,写死一个值一定会在某一边出错:
|
||||
*
|
||||
* 1. 微信开发者工具:可以用 http://localhost:8080,
|
||||
* 但必须在「详情 → 本地设置」里勾上 **「不校验合法域名、web-view、TLS 版本以及 HTTPS 证书」**。
|
||||
* 不勾的话请求会被拦,报错是「不在以下 request 合法域名列表中」——
|
||||
* 而那句话看起来像"域名没配",会让人跑去小程序后台白改一通。
|
||||
* · **H5**:与接口**同域**(后端直接托管 H5 静态文件,见 application-dev.yml 的
|
||||
* static-locations),所以用**相对路径(空串)**。这样:
|
||||
* ① 完全不经过 CORS —— 换域名也不用改配置;
|
||||
* ② 不会出现"手机能从 A 域名加载页面、却向后端 B 域名发请求"这种毛病。
|
||||
* ⚠️ 曾经的写法是硬编码 `http://localhost:8080`,于是从公网域名打开时
|
||||
* 变成了跨域请求 → 被 CORS 拦 → 页面显示"网络请求失败",
|
||||
* 而**从本机打开却是好的**。这个 bug 只有走真实穿透/真机才会暴露。
|
||||
*
|
||||
* 2. 真机预览/体验版:localhost 是**手机自己**,不是你的电脑。
|
||||
* 要把地址换成电脑的局域网 IP(如 http://192.168.1.5:8080),
|
||||
* 并确保手机与电脑在同一网络、电脑防火墙放行 8080。
|
||||
* · **小程序**:没有"同域"这个概念,必须写绝对地址。
|
||||
* 开发者工具里可以用 `http://localhost:8080`(需勾"不校验合法域名");
|
||||
* 真机要用局域网 IP;正式版必须是 HTTPS + 已在小程序后台配好的域名。
|
||||
*
|
||||
* 3. 正式发布:必须是 **HTTPS + 已在微信后台配好 request 合法域名**(见待办:域名白名单),
|
||||
* 且域名不能带端口、不能是 IP。
|
||||
*
|
||||
* 所以这里留成一处配置,而不是散在请求代码里。
|
||||
* 用 uni-app 的条件编译区分两端,而不是运行期判断 —— 后者会把两套地址都打进包里。
|
||||
*/
|
||||
// #ifdef H5
|
||||
/**
|
||||
* H5:用**绝对的同源地址**(`location.origin`),不要用相对路径。
|
||||
*
|
||||
* ⚠️ 实测:`uni.request` 传相对路径(`/api/v1/...`)会以 `request:fail` 失败,
|
||||
* 而**同样地址用原生 XHR / fetch 是成功的**(都是 200)。也就是说这是 uni-app
|
||||
* 自身的处理差异,不是服务端或跨域问题 —— 但排查时它长得像"网络不通",
|
||||
* 很容易往 CORS / 域名 / 后端去查,白绕一大圈。
|
||||
*
|
||||
* 用 `location.origin` 而不是 `''`:既绕开这个差异,又保持**同源**
|
||||
* (不经过 CORS),换域名也不用改配置。
|
||||
*/
|
||||
export const API_BASE_URL = typeof location !== 'undefined' ? location.origin : ''
|
||||
// #endif
|
||||
|
||||
// #ifndef H5
|
||||
export const API_BASE_URL = 'http://localhost:8080'
|
||||
// #endif
|
||||
|
||||
/** 主题色(与 PC 管理端同一套腾讯云 TDesign 色板,两端视觉要一致)。 */
|
||||
export const THEME = {
|
||||
|
||||
Reference in New Issue
Block a user