Reference Card

环境变量键:谁写入,谁消费

源码里用到约 50 个 VITE_*.env 文件只定义 11 个。 这张卡讲清楚差额从哪来。

基线:2026-08-12 的 gameboxclient 工作区快照。 键名清单由 grep -rhoE "VITE_[A-Z0-9_]+" src/ electron/ 全量提取。

一句话版本

.env 里的键是构建期的兜底; 真正在用的绝大多数键由登录接口 /user/info 下发, 经 src/utils/extend/envOption.ts:8initEnv() 写进 Pinia 的 GameEvn.ENV, 再由 watch 落进 localStorage 的 GameENV 键。

排障第一条命令: JSON.parse(localStorage.getItem('GameENV'))

三个来源

来源 什么时候产生 怎么读到
A. .env* 文件 构建期,Vite 打进包里 渲染层 import.meta.env.X; 主进程在 ready.ts:11-13 把它们灌进 process.env
B. 主进程算出来的路径 应用启动时 ready.ts:14-19DIST_ELECTRON / DIST_EXTEND / DIST / PUBLIC
C. 登录接口下发 登录成功那一刻 initEnv() 写进 GameEvn.ENV, 用 gameEnv.getEnvKey('X')

A. .env* 里真正定义的 11 个

这是 .env.env.base.env.dev.env.pro 四个文件的键名并集:

作用
NODE_ENV 决定主进程要不要初始化 electron-log
VITE_APP_TITLE 窗口标题,经 EJS 插件注入 index.html
VITE_BASE_PATH Vite 的 base,资源路径前缀
VITE_BASEPATH axios 的 baseURL 初始值service.ts)。 注意和上一个只差一个下划线
VITE_OUT_DIR 构建输出目录
VITE_SOURCEMAP 要不要出 sourcemap
VITE_DROP_CONSOLE · VITE_DROP_DEBUGGER terser 压缩时去不去掉 console / debugger
VITE_DEBUG 主进程在 onAppReady.ts 里打日志用
VITE_JENKINS_APP 构建 APP 的 job 名兜底。唯一一个在 .env 里的 Jenkins 键
VITE_SHOW_UI ⚠️ 在 .env 里定义了,但 src/electron/搜不到任何消费方,疑似遗留

❌ 别学

VITE_BASE_PATHVITE_BASEPATH 是两个不同的键, 含义也完全不同。前者是 Vite 的资源基路径,后者是接口的 baseURL。

改配置时看漏一个下划线,症状会是「资源 404」或「所有接口打到了根路径」—— 而且两个症状都跟你以为的原因无关。

规范做法:命名要拉开距离,比如 VITE_ASSET_BASEVITE_API_BASE_URL

B. 主进程算出来的路径键

算法 谁用
DIST_ELECTRON join(__dirname, '..') 下面三个的基准
DIST DIST_ELECTRON/../dist 打包后加载 index.html 的位置
DIST_EXTEND DIST_ELECTRON/../extend 所有外挂工具的根目录
PUBLIC 打包后 = DIST,开发时 = ../public 图标等静态资源
VITE_DIST_EXTEND src/utils/extend/electron.ts:4DIST_EXTEND 里的 app.asar 替换成 app.asar.unpacked SVN / Python / 7-Zip 全靠它拼路径。 打包后二进制不在 asar 里,必须走 unpacked
VITE_DEV_SERVER_URL vite-plugin-electron 注入 开发时窗口加载哪个地址;打包后为空
为什么 VITE_DIST_EXTEND 要做 asar 替换: Electron 打包会把代码塞进一个叫 app.asar 的归档文件里, 归档内的文件不能被当作可执行程序运行。 所以 electron-builder.json5asarUnpackextend 解出来放在 app.asar.unpacked, 代码再把路径替换过去。这是打包后「找不到 svn / python」类问题的根源所在

C. 登录下发的键(占绝大多数)

initEnv(gameConfig, cosConfig)userInfo.game 解构出 pcodechannelgm_urlgm_url_devsvn_urlsvn_accountsvn_passwordjenkins_urljenkins_accountjenkins_token,映射成下面这些键。

GM 接口

来自 消费方 缺了会怎样
VITE_API_BASE_PCODE gameConfig.pcode 选服时用它拼各种派生 pcode 选服后各模块 pcode 全是 undefined_dev 之类
VITE_API_PCODE 同上 service.ts:30getPcode() 所有 1000y 请求鉴权失败; 而且 getBaseURL() 会因为没有 _dev 把请求打到正式服
VITE_API_GM_PCODE 选服时按版本计算 service.ts:38currentRouter === '/GM' 时)、 GM 工具、错误日志 GM 请求带不上正确 pcode,服务端拒
VITE_API_SCRIPT_PCODE 脚本管理页自己算 views/GameEditor/NewScript/index.vue 脚本管理读不到数据
VITE_API_SECTCONFIG_PCODE · VITE_API_SECTCONFIG_PATH 全局数据页自己算 views/GameEditor/GlobalData/index.vue 门派等全局配置读不到
VITE_API_BASEPATH · VITE_API_BASEPATH_DEV gm_url / gm_url_dev ⚠️ 下发了,但 getBaseURL() 并不用它 —— 那里的域名是硬编码 目前影响有限,但这说明「配置下发」这条路只走了一半
VITE_API_PATH 初始等于 VITE_API_BASEPATH_DEV 选服组件会改写它

渠道

来自 消费方
VITE_API_CHANNEL gameConfig.channel Jenkins job 名里的 channel 占位会被它替换envOption.tsreplaceChannelInUrls
VITE_API_CHANNEL_SVN gameConfig.assetsUrl,没有则拼成 qn{channel} utils/extend/svn.ts 拼工作副本路径

⚠️ 高频故障点

Jenkins job 名是「模板 + 渠道替换」拼出来的。 utils/extend/jenkins/config.ts 里的 JOB_TYPES 存的是键名模板,initEnv() 再把里面的 channel 字样换成实际渠道。

后果:渠道值不对 → job 名不对 → Jenkins 返回 404 → 但客户端的轮询还在转。用户看到的是「发布卡住了」。

排查:在控制台看 JSON.parse(localStorage.getItem('GameENV')).VITE_JENKINS_RES 之类的最终 job 名,拿去 Jenkins 上搜一下存不存在。

SVN

来自 缺了会怎样
VITE_SVN_URL gameConfig.svn_url,没有则保留原值 找不到仓库地址
VITE_SVN_EXCEL_URL svn_url 里的 onlineAssets 替换成 online 配置表相关的 SVN 操作找错路径
VITE_SVN_USER · VITE_SVN_PASSWORD svn_account / svn_password SVN 命令行认证失败。 ⚠️ 密码明文存进 localStorage

Jenkins

说明
VITE_JENKINS_URL · VITE_JENKINS_USER · VITE_JENKINS_TOKEN 连接凭据,喂给 initConfig()jenkins/config.ts:125)。 缺了 Jenkins 客户端根本不会被创建,之后所有发布操作静默无反应
VITE_JENKINS_RES · VITE_JENKINS_DEV · VITE_JENKINS_ALPHA · VITE_JENKINS_PROD 资源编译、测试同步、测试热更、正式同步的 job 名
VITE_JENKINS_PUBLISH_WEB_DEV · VITE_JENKINS_PUBLISH_HOT_ALPHA · VITE_JENKINS_PUBLISH_HOT_PROD 发布开发版 / 测试热更 / 正式热更
VITE_JENKINS_APP 构建 APP,唯一在 .env 里有兜底的
VITE_JENKINS_STOP · VITE_JENKINS_AUTO · VITE_JENKINS_CHECK 不是真的 job 名,是 JOB_TYPES 里的动作标记 ('STOP' / 'ATUO' / 'CHECK')。 注意 ATUOAUTO 的拼写错误
VITE_JENKINS_PUBLISH_WEB_ALPHA · VITE_JENKINS_PUBLISH_WEB_PROD · VITE_JENKINS_PUBLISH_HOT_COMPARE ⚠️ 在 JOB_TYPES 里被注释掉了, 但 initEnv() 的渠道替换列表里还在 —— 会对 undefined.replace()

对象存储与其他

消费方 说明
VITE_COS_ACCESSKEYID · VITE_COS_ACCESSKEYSECRET src/App.vue:41COS_Handler.init() 缺了 init()catch 掉并 return false没有任何提示
VITE_COS_BUCKET · VITE_COS_REGION src/api/shop/index.ts 资源商城相关
VITE_ENDPOINT utils/extend/cos.ts COS 访问域名。有一个硬编码的默认值写在源码里
VITE_OSS_ACCESSKEYID 等四个 OSS 键 utils/extend/oss.ts 阿里云 OSS,与 COS 并存,疑似历史遗留
VITE_DEV_WEB · VITE_ALPHA_WEB · VITE_PROD_WEB utils/extend/third.ts 三套环境的网页版地址
VITE_STORE src/api/shop/index.ts 资源商城地址

排查流程

JSON.parse(localStorage.getItem('GameENV')) —— 整个包在不在

目标键有没有值。空的 → 服务端没下发, 不是前端的问题,去问后端 /user/info 返回了什么

有值但不对 → 看 envOption.ts 里这个键的赋值来源, 以及有没有页面在选服时改写它

pcode 类问题额外查 localStorage.getItem('pCode') —— getPcode() 会优先用它