GitHub 托管 API 地址配置文件:实现零成本云配置托管
这是一种「无自建服务器」的轻量级配置中心方案,核心优势是无需自己维护稳定服务器,仅通过 GitHub 托管一个静态 JSON 文件,APP 启动时拉取该文件获取最新 API 地址,完美解决 API 地址硬编码导致的变更无法适配问题。
需求分析
当我的app链接的服务器api地址发生变化时,由于地址内容是通过硬编码的,此时我的app就链接不到服务器,只能通过开发者传输的新apk文件文件来进行更新。
下面我们将通过一个 uni-app 的代码实例通过请求 GitHub 稳定托管的配置来解决这个问题
一、方案核心思路
- GitHub 端:创建公开仓库,托管一个 JSON 配置文件,存放最新的 API 基础地址;
- APP 端:启动时优先请求 GitHub 上的这个静态 JSON 文件,获取最新 API 地址;
- 缓存兜底:将获取到的最新 API 地址缓存到本地,同时设置本地兜底地址,避免 GitHub 无法访问时 APP 无法运行;
- 无感更新:后续 API 地址变更时,只需修改 GitHub 上的 JSON 文件,APP 下次启动会自动拉取最新配置,无需重新打包发布。
二、分步实现(详细可落地)
步骤 1:GitHub 端创建并托管 API 配置文件
-
创建公开仓库 :
- 打开 GitHub,新建一个公开仓库(如
app-api-config,仓库名自定义); - 无需初始化 README(也可初始化,不影响核心功能)。
- 打开 GitHub,新建一个公开仓库(如
-
创建 API 配置 JSON 文件 :
-
点击仓库页面的「Add file」->「Create new file」,创建文件(命名如
api-config.json,后缀必须为.json); -
写入配置内容(仅存放核心 API 地址,格式简洁),示例:
json{ "updateTime": "2026-01-09", "baseApiUrl": "http://新服务器IP:8080", // 最新的 API 基础地址 "backupApiUrl": "http://备用服务器IP:8080" // 可选:备用地址,防止主地址不可用 }
-
-
提交文件 :
- 下拉到页面底部,填写提交信息(如「update api config v1.0」),点击「Commit new file」完成提交;
-
获取 JSON 文件的「原始访问链接」(关键步骤) :
- 进入仓库,点击已创建的
api-config.json文件,打开文件详情页; - 点击文件右上角的「Raw」按钮(纯文本原始访问入口),此时浏览器地址栏的链接即为可直接请求的 JSON 链接;
- 复制该链接(格式示例:
https://raw.githubusercontent.com/你的GitHub用户名/app-api-config/main/api-config.json),后续 APP 端将请求该链接。
- 进入仓库,点击已创建的
注意:GitHub 公开仓库的静态文件支持跨域请求,无需额外配置,可直接被 Uniapp APP 调用。
步骤 2:Uniapp 端实现「拉取 GitHub 配置 + 缓存 + 兜底」
核心逻辑:APP 启动时(App.vue 的 onLaunch)拉取 GitHub 上的配置文件,缓存最新 API 地址到本地,后续所有接口请求都使用「本地缓存的最新地址」,无缓存时使用兜底地址。
1. 封装全局配置工具(utils/api-config.js)
javascript
/**
* API 配置工具类:拉取 GitHub 配置 + 本地缓存 + 兜底
*/
// 1. 配置常量(GitHub 配置文件原始链接 + 本地兜底地址)
const GITHUB_CONFIG_URL = "https://raw.githubusercontent.com/你的GitHub用户名/app-api-config/main/api-config.json"; // 替换为你的 Raw 链接
const DEFAULT_BASE_API = "http://旧服务器IP:3000"; // 兜底地址:防止 GitHub 无法访问
// 2. 拉取 GitHub 上的最新 API 配置
export function fetchGithubApiConfig() {
return new Promise((resolve, reject) => {
uni.request({
url: GITHUB_CONFIG_URL,
method: "GET",
timeout: 10000, // 超时时间:10 秒(避免 GitHub 访问缓慢阻塞 APP 启动)
success: (res) => {
if (res.statusCode === 200 && res.data && res.data.baseApiUrl) {
// 3. 拉取成功:缓存到本地存储(永久缓存,直到下次拉取更新)
const latestConfig = res.data;
uni.setStorageSync("latestApiConfig", latestConfig);
console.log("拉取 GitHub API 配置成功", latestConfig);
resolve(latestConfig);
} else {
reject("GitHub 配置文件格式错误");
}
},
fail: (err) => {
console.warn("拉取 GitHub 配置失败(可能网络问题)", err);
reject("拉取远程配置失败");
}
});
});
}
// 4. 获取当前生效的 API 基础地址(优先缓存 -> 兜底)
export function getEffectiveApiBaseUrl() {
try {
// 优先读取本地缓存的最新配置
const cachedConfig = uni.getStorageSync("latestApiConfig");
if (cachedConfig && cachedConfig.baseApiUrl) {
return cachedConfig.baseApiUrl;
}
// 无缓存:返回本地兜底地址
return DEFAULT_BASE_API;
} catch (e) {
// 异常情况:返回本地兜底地址
return DEFAULT_BASE_API;
}
}
2. APP 启动时拉取配置(App.vue)
javascript
<script>
import { fetchGithubApiConfig, getEffectiveApiBaseUrl } from "@/utils/api-config.js";
export default {
onLaunch() {
console.log("APP 启动");
// 1. 优先拉取 GitHub 最新配置(异步执行,不阻塞 APP 启动)
fetchGithubApiConfig().then(() => {
// 拉取成功后,后续请求自动使用最新地址
console.log("最新 API 配置已生效");
}).catch(() => {
// 拉取失败:使用本地缓存/兜底地址,不影响 APP 正常运行
console.log("使用本地兜底 API 地址");
});
// 2. 验证当前生效的 API 地址
const currentApiUrl = getEffectiveApiBaseUrl();
console.log("当前生效的 API 地址:", currentApiUrl);
}
};
</script>
3. 封装全局请求工具(utils/request.js)
后续所有接口请求都通过该工具类,自动拼接「当前生效的 API 地址」,无需手动修改:
javascript
import { getEffectiveApiBaseUrl } from "@/utils/api-config.js";
/**
* 全局请求封装:自动拼接最新 API 地址
*/
export function request(options) {
// 1. 获取当前生效的 API 基础地址
const baseApiUrl = getEffectiveApiBaseUrl();
// 2. 拼接完整请求地址
const fullUrl = baseApiUrl + options.url;
return new Promise((resolve, reject) => {
uni.request({
url: fullUrl,
method: options.method || "GET",
data: options.data || {},
header: options.header || { "Content-Type": "application/json" },
success: (res) => {
resolve(res.data);
},
fail: (err) => {
uni.showToast({
title: "服务器连接失败",
icon: "none",
duration: 3000
});
console.error("接口请求失败:", err);
reject(err);
}
});
});
}
4. 接口调用示例(正常使用即可,自动适配最新 API 地址)
javascript
import { request } from "@/utils/request.js";
// 调用版本更新接口(无需关心 API 地址,自动拼接最新配置)
function getAppUpdateInfo(localVersionCode) {
return request({
url: "/app_update", // 仅传入接口路径,基础地址自动拼接
method: "GET",
data: {
local_version_code: localVersionCode
}
});
}
三、关键注意事项(确保方案稳定落地)
-
GitHub 原始链接正确性:
- 必须使用
raw.githubusercontent.com开头的链接,不能使用仓库文件的页面链接(如github.com/xxx/xxx/blob/main/xxx.json),后者返回的是 HTML 页面,而非纯 JSON 数据; - 若仓库分支不是
main(如master),需修改链接中的分支名称(如.../master/xxx.json)。
- 必须使用
-
GitHub 访问稳定性(国内环境):
- 国内部分网络环境可能无法访问 GitHub(
raw.githubusercontent.com被屏蔽),此时方案会自动降级到「本地兜底地址」; - 替代方案:使用 Gitee 托管配置文件(国内访问更稳定),操作逻辑与 GitHub 完全一致,仅需替换配置文件的 Raw 链接。
- 国内部分网络环境可能无法访问 GitHub(
-
配置更新后生效方式:
- API 地址修改后,只需更新 GitHub 上的
api-config.json文件,APP 下次启动时会自动拉取最新配置并缓存,无需用户更新 APP; - 若需实现「无需重启 APP 即可生效」,可在 APP 内增加「手动刷新配置」按钮(调用
fetchGithubApiConfig()方法)。
- API 地址修改后,只需更新 GitHub 上的
-
敏感信息保护:
- 该方案仅适合托管「公开的 API 基础地址」,不适合存储敏感信息(如接口密钥、数据库配置等),因为 GitHub 公开仓库的内容可被任何人查看。
-
超时与兜底优化:
- 拉取 GitHub 配置时设置合理超时时间(5-10 秒),避免阻塞 APP 启动;
- 配置文件中增加
backupApiUrl备用地址,可在getEffectiveApiBaseUrl()中增加逻辑:当主地址请求失败时,自动切换到备用地址。
四、方案优势总结
- 零成本搭建:无需自建服务器、无需备案域名,仅使用 GitHub 公开仓库即可实现配置托管;
- 无需重新打包:API 地址变更时,仅修改 GitHub 上的 JSON 文件,APP 下次启动自动适配,解决硬编码痛点;
- 高可用兜底:结合本地缓存 + 兜底地址,即使 GitHub 无法访问,APP 仍能正常运行;
- 易扩展 :后续可在
api-config.json中增加其他配置项(如 APP 更新地址、全局开关等),实现更多配置的远程更新。
五、后续 API 地址变更操作(超简单)
- 打开 GitHub 仓库,编辑
api-config.json文件; - 将
baseApiUrl的值修改为新的 API 地址; - 提交修改(填写提交信息,点击「Commit changes」);
- APP 下次启动时,会自动拉取并缓存新的 API 地址,无需其他操作,实现无感更新。