/** * Expo Config Plugin:自动从 expo.version 派生 Android versionCode * * 单一数据源:app.json.expo.version * * versionName 由 expo prebuild 模板自动从 app.json.expo.version 读取,无需此 plugin 处理。 * versionCode 计算规则:major * 10000 + minor * 100 + patch * 例:0.2.1 → 0*10000 + 2*100 + 1 = 201 * * 使用方式:在 app.json 的 expo.plugins 数组中注册即可。 */ const { withAppBuildGradle } = require('expo/config-plugins'); module.exports = (config) => { const version = config.version; // 缺 version 时静默跳过会让 android 里留着旧 versionCode,发布脚本只能靠 aapt 事后发现 if (!version) { throw new Error('withVersionSync: app.json 缺少 expo.version,无法派生 versionCode'); } const match = version.match(/^(\d+)\.(\d+)\.(\d+)$/); if (!match) { throw new Error(`withVersionSync: app.json.expo.version "${version}" 不符合 X.Y.Z 格式`); } const [, majorStr, minorStr, patchStr] = match; const major = parseInt(majorStr, 10); const minor = parseInt(minorStr, 10); const patch = parseInt(patchStr, 10); if (minor >= 100 || patch >= 100) { throw new Error(`withVersionSync: minor/patch 必须 < 100(当前 ${major}.${minor}.${patch})`); } const versionCode = major * 10000 + minor * 100 + patch; return withAppBuildGradle(config, (config) => { if (!config.modResults?.contents) { throw new Error('withVersionSync: 无法读取 build.gradle 内容'); } let contents = config.modResults.contents; const regex = /versionCode\s*=?\s*\d+/; if (!regex.test(contents)) { throw new Error('withVersionSync: 在 build.gradle 中未找到 versionCode 字段'); } contents = contents.replace(regex, `versionCode ${versionCode}`); config.modResults.contents = contents; return config; }); };