/** * 环境切换脚本:把 config/env/.js 里的 appid 同步到编译期配置文件 * * 用法: * npm run env:sit 等价于 node scripts/set-env.js sit * npm run env:prod 等价于 node scripts/set-env.js prod * * 说明: * appid 是编译期值(HBuilderX 的编译输入就是 manifest.json),无法像接口地址那样 * 运行时切换,所以这里做“一次命令写回”。改完必须重新编译一次,产物里的 * project.config.json 才会更新。 * * 日常推荐:mp-weixin.appid 保持 null,只让发行脚本回写产物 appid(git 零噪音)。 * 本脚本用于需要在 HBuilderX 里直接运行调试、或要出 App 包(顶层 appid)的场景。 * * 唯一数据源:config/env/.js 中的 UNI_APPID(DCloud 标识)、APPID(小程序 appid) */ const fs = require('fs'); const path = require('path'); const ROOT = path.resolve(__dirname, '..'); const ENV_DIR = path.join(ROOT, 'config', 'env'); // 根目录 project.config.json 不参与 mp-weixin 编译且已不入库,这里只维护 manifest.json const files = { manifest: path.join(ROOT, 'manifest.json') }; function fail(msg) { console.error('[set-env] ' + msg); process.exit(1); } /** 只替换第一处 "appid" : <字符串或 null>,保留原有空格/缩进风格 */ function replaceAppId(text, value) { let done = false; const result = text.replace(/"appid"(\s*:\s*)(?:"[^"]*"|null)/, function(match, sep) { done = true; return '"appid"' + sep + '"' + value + '"'; }); return { text: result, done: done }; } /** 替换 manifest.json 顶层 appid(第一处出现即为顶层) */ function patchManifest(text, env) { // 1) 顶层 appid(DCloud 应用标识) const top = replaceAppId(text, env.UNI_APPID); if (!top.done) fail('manifest.json 中未找到顶层 "appid" 字段'); text = top.text; // 2) mp-weixin 下的 appid(微信小程序 appid),只在该区块内替换第一处 const idx = text.indexOf('"mp-weixin"'); if (idx < 0) fail('manifest.json 中未找到 "mp-weixin" 配置块'); const head = text.slice(0, idx); const body = text.slice(idx); const scoped = replaceAppId(body, env.APPID); if (scoped.done) return head + scoped.text; // 3) 字段被删掉时,按同级子项缩进补一行 const m = body.match(/^("mp-weixin"\s*:\s*\{)(\r?\n)([ \t]*)/); if (!m) fail('manifest.json 的 "mp-weixin" 块格式异常,无法写入 appid'); const nl = m[2]; const indent = m[3]; return head + m[1] + nl + indent + '"appid" : "' + env.APPID + '",' + nl + indent + body.slice(m[0].length); } function writeIfChanged(file, next) { const prev = fs.readFileSync(file, 'utf8'); if (prev === next) { console.log(' - ' + path.relative(ROOT, file) + ' 已是目标值,无需改动'); return false; } fs.writeFileSync(file, next, 'utf8'); console.log(' √ ' + path.relative(ROOT, file) + ' 已更新'); return true; } function main() { const envName = (process.argv[2] || '').trim(); const available = fs.existsSync(ENV_DIR) ? fs.readdirSync(ENV_DIR).filter(f => f.endsWith('.js') && f !== 'index.js').map(f => f.replace(/\.js$/, '')) : []; if (!envName) { fail('请指定环境名,可选:' + available.join(' / ') + '\n 例:npm run env:sit'); } if (available.indexOf(envName) < 0) { fail('未找到 config/env/' + envName + '.js,可选:' + available.join(' / ')); } const env = require(path.join(ENV_DIR, envName + '.js')); if (!env.UNI_APPID || !env.APPID) { fail('config/env/' + envName + '.js 缺少 UNI_APPID 或 APPID'); } console.log('[set-env] 切换到 ' + envName + '(' + env.ENV_NAME + ')'); console.log(' DCloud appid : ' + env.UNI_APPID); console.log(' 小程序 appid : ' + env.APPID); console.log(' 接口地址 : ' + env.HTTP_REQUEST_URL); const changed = writeIfChanged(files.manifest, patchManifest(fs.readFileSync(files.manifest, 'utf8'), env)); console.log(changed ? '[set-env] 完成,请在 HBuilderX 中重新编译一次,并在微信开发者工具中重新打开项目' : '[set-env] 无需改动,当前已是 ' + envName + ' 环境配置'); } main();