【微信小程序】分别解决H5的跨域代理问题 和小程序正常不需要代理问题
——总问:何为跨域和代理?
🔹什么叫跨域?
前端在浏览器里发请求时,如果 域名 / 协议 / 端口 三个中有一个不一样,就会触发 跨域问题。
例子:
- 页面跑在 http://localhost:5173
- 你要请求接口 http://100.100.1.60:29083/api/xxx
因为 端口号不一样(5173 ≠ 29083),所以就跨域了。
浏览器出于 安全机制(同源策略),会拦截掉不合法的请求,报 CORS 错误。
🔹什么叫代理?
代理(proxy)就是在前端本地开发环境下,给你“搭个中转站”。
比如 vite / vue-cli 里,可以这样写:
// vite.config.js
export default defineConfig({server: {proxy: {'/api': {target: 'http://100.100.1.60:29083', // 真实后端地址changeOrigin: true, // 修改请求头的来源rewrite: (path) => path.replace(/^\/api/, '') // 去掉/api前缀(可选)}}}
})
这样你前端调用:
fetch('/api/system/hospital/list')
浏览器看到 /api
觉得是本地的,不会跨域。
Vite 开发服务器帮你偷偷转发到:
http://100.100.1.60:29083/system/hospital/list
所以 代理的本质就是前端开发服务器代你转发请求,骗过浏览器,绕开跨域。
🔹其他结论:
—— 写法:
1.配置
配置写在 manifest.json
的源码视图 里面
- 什么是 manifest.json:
在 Uni-App 项目里,manifest.json 就是一个 全局配置清单,决定了你项目在不同端(H5、小程序、App)的打包、运行、权限、启动页等核心信息。
🔹因为 不同端(H5、App、小程序)有各自的差异化设置,官方就统一放在 manifest.json 里:
1.App打包:图标、启动页、签名、权限(camera、storage、gps)等
2.小程序:appid、是否校验 URL、分包配置
3.H5:路由模式(hash/history)、发布路径
4.公共信息:应用名称、版本号、appid
👉 所以如果你需要:
1.配置 App 权限(比如用到相机、麦克风)
2.配置 小程序 appid
3.配置 打包图标、启动页
4.配置 H5 发布路径
🔹这些都要写在 manifest.json 的源码视图里。
- 为什么不写在
request
里:
- 为什么写在
manifest.json
🔹如图:
/* H5端配置 */"h5": {"devServer": {"proxy": {"/api": {"target": "http://100.100.1.60:29083", // 👉 你的后端地址"changeOrigin": true,"secure": false,"pathRewrite": {"^/api": "" // 去掉前缀 /api}}}}},
🔑
secure
的意思:
1.secure: true
(默认) → 代理的时候 只接受有效HTTPS 证书
。
2.secure: false
→ 即使后端用的是自签名证书 / 无效证书
,也允许代理过去。
👉 一般 本地开发环境 或者 测试服务器用自签名证书 时会写 false,不然代理会报错。
👉 如果你们后端是 http://,写不写 secure:false都无所谓,因为只在 https:// 后端生效。
2. 区分使用
🔹request:
区分使用 h5 和 小程序
// utils/request.js// 后端服务地址(App 和小程序直连时用)
const BASE_URL = 'http://127.0.0.1:8080'// 统一请求封装
export default function request(options = {}) {let url = options.url// 判断环境// H5:支持 devServer 代理,直接走 /api// 非 H5(App、小程序):拼接完整 BASE_URL// #ifdef H5if (!url.startsWith('/api')) {url = '/api' + url}// #endif// #ifndef H5if (!url.startsWith('http')) {url = BASE_URL + url}// #endifreturn new Promise((resolve, reject) => {uni.request({url: url,method: options.method || 'GET',data: options.data || {},header: options.header || {'Content-Type': 'application/json',},success: (res) => {if (res.statusCode === 200) {resolve(res.data)} else {reject(res)}},fail: (err) => {reject(err)},})})
}
🔹解释:
// #ifdef H5
if (!url.startsWith('/api')) {url = '/api' + url
}
// #endif
👉 只在 H5 环境生效(浏览器开发)。
因为浏览器有跨域问题,这里会强制给你的请求地址加上 /api 前缀。
这样就能配合 Vite 或 Vue CLI 的代理(/api → http://127.0.0.1:8080),解决跨域。
// #ifndef H5
if (!url.startsWith('http')) {url = BASE_URL + url
}
// #endif
👉 非 H5 环境生效(App / 小程序)。
它们没跨域问题,所以直接拼接真实的 BASE_URL。
比如:
/system/hospital/list → http://127.0.0.1:8080/system/hospital/list
🔹整体逻辑
- 在 H5(浏览器)环境:
请求统一走 /api,通过 代理转发到后端。 - 在 App / 小程序环境:
直接拼上 BASE_URL,直连后端。
这样,你在项目里调用:
request({ url: '/system/hospital/list', method: 'POST' })
在不同环境下会自动处理:
- H5:发的是 /api/system/hospital/list(再被代理转发)
- 小程序:发的是 http://127.0.0.1:8080/system/hospital/list