/**
|
* 命令行发行(不上传)+ 自动用微信开发者工具打开产物
|
*
|
* 用法:
|
* node scripts/publish.js sit # 发行 SIT 版本并打开微信开发者工具
|
* node scripts/publish.js prod # 发行 PROD 版本并打开微信开发者工具
|
* node scripts/publish.js sit --sync # 同时把 appid 同步进 manifest.json(默认不动 manifest)
|
* node scripts/publish.js sit --no-open # 只编译,不打开微信开发者工具
|
* node scripts/publish.js sit --dry-run # 只打印将要执行的命令
|
*
|
* 环境值统一取自 config/env/<env>.js(唯一数据源),接口地址等运行时参数由包内自动识别,
|
* 本脚本只负责让“编译期 appid”与目标环境一致 —— 微信开发者工具打开的产物 appid,
|
* 就是 unpackage/dist/build/mp-weixin/project.config.json 里的 appid(构建时由 manifest 生成)。
|
*
|
* 默认策略:不动 manifest.json(仓库保持 prod 基线,git 无噪音),只回写未跟踪的产物文件。
|
*/
|
const { spawnSync } = require('child_process');
|
const fs = require('fs');
|
const path = require('path');
|
|
const ROOT = path.resolve(__dirname, '..');
|
const ENV_DIR = path.join(ROOT, 'config', 'env');
|
const DIST_DIR = path.join(ROOT, 'unpackage', 'dist', 'build', 'mp-weixin');
|
const DIST_CONFIG = path.join(DIST_DIR, 'project.config.json');
|
|
// 外部工具路径:可用环境变量覆盖,便于换机器
|
const HX_CLI = process.env.HBUILDERX_CLI || 'C:\\Users\\Administrator\\Desktop\\HBuilderX\\cli.exe';
|
const WX_CLI = process.env.WX_DEVTOOLS_CLI || 'D:\\Program Files (x86)\\Tencent\\微信web开发者工具\\cli.bat';
|
|
const argv = process.argv.slice(2);
|
const envName = (argv.find(function(a) { return a.charAt(0) !== '-'; }) || '').trim();
|
const syncManifest = argv.indexOf('--sync') > -1;
|
const noOpen = argv.indexOf('--no-open') > -1;
|
const dryRun = argv.indexOf('--dry-run') > -1;
|
|
const OWN_ARGS = ['--sync', '--no-open', '--dry-run'];
|
// 透传给 HBuilderX cli 的额外参数(保留 "参数 值" 成对关系)
|
const passthrough = [];
|
let envNameSkipped = false;
|
argv.forEach(function(a) {
|
if (OWN_ARGS.indexOf(a) > -1) return;
|
if (!envNameSkipped && a === envName) {
|
envNameSkipped = true;
|
return;
|
}
|
passthrough.push(a);
|
});
|
|
function fail(msg) {
|
console.error('[release] ' + msg);
|
process.exit(1);
|
}
|
|
function readAppId(file) {
|
try {
|
return JSON.parse(fs.readFileSync(file, 'utf8')).appid || '';
|
} catch (e) {
|
return '';
|
}
|
}
|
|
/** 回写 appid(正则替换,保留原格式) */
|
function writeAppId(file, appid) {
|
const prev = fs.readFileSync(file, 'utf8');
|
const next = prev.replace(/"appid"(\s*:\s*)"[^"]*"/, function(m, sep) {
|
return '"appid"' + sep + '"' + appid + '"';
|
});
|
if (next !== prev) fs.writeFileSync(file, next, 'utf8');
|
return readAppId(file);
|
}
|
|
function main() {
|
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 例:node scripts/publish.js sit');
|
if (available.indexOf(envName) < 0) fail('未找到 config/env/' + envName + '.js,可选:' + available.join(' / '));
|
|
const env = require(path.join(ENV_DIR, envName + '.js'));
|
|
if (!fs.existsSync(HX_CLI)) {
|
fail('未找到 HBuilderX cli.exe:' + HX_CLI +
|
'\n 请确认安装路径,或设置环境变量 HBUILDERX_CLI 指向 cli.exe');
|
}
|
if (!noOpen && !fs.existsSync(WX_CLI)) {
|
fail('未找到微信开发者工具 cli.bat:' + WX_CLI +
|
'\n 请设置环境变量 WX_DEVTOOLS_CLI,或加 --no-open 自行打开产物目录');
|
}
|
|
console.log('[release] 环境 : ' + envName + '(' + env.ENV_NAME + ')');
|
console.log('[release] 小程序appid : ' + env.APPID);
|
console.log('[release] 接口地址 : ' + env.HTTP_REQUEST_URL);
|
console.log('[release] 产物目录 : ' + DIST_DIR);
|
console.log('[release] manifest.json: ' + (syncManifest ? '同步为 ' + envName + ' 的 appid(会产生 git 改动)' : '保持不动(仓库维持基线,无 git 改动)'));
|
|
const cliArgs = ['publish', '--platform', 'mp-weixin', '--project', ROOT].concat(passthrough);
|
// 路径含空格/中文,交给 cmd 解析更稳
|
const openCmd = '"' + WX_CLI + '" open --project "' + DIST_DIR + '"';
|
|
if (dryRun) {
|
console.log('[release] 1) 编译: "' + HX_CLI + '" ' + cliArgs.join(' '));
|
console.log('[release] 2) 产物 appid 回写为 ' + env.APPID + ' → ' + DIST_CONFIG);
|
if (!noOpen) console.log('[release] 3) 打开: ' + openCmd);
|
console.log('[release] --dry-run,未执行');
|
return;
|
}
|
|
// 1) 可选:同步 manifest.json(会让被跟踪文件产生改动,默认不做)
|
if (syncManifest) {
|
console.log('[release] 同步 manifest.json 的 appid…');
|
const sync = spawnSync(process.execPath, [path.join(__dirname, 'set-env.js'), envName], { cwd: ROOT, stdio: 'inherit' });
|
if (sync.status !== 0) fail('同步 manifest.json 失败');
|
}
|
|
// 2) 发行编译(产物:unpackage/dist/build/mp-weixin)
|
console.log('[release] 开始发行编译,日志见 HBuilderX 控制台…');
|
const build = spawnSync(HX_CLI, cliArgs, { cwd: ROOT, stdio: 'inherit' });
|
if (build.error) fail('调用 cli.exe 失败:' + build.error.message);
|
if (build.status !== 0) fail('cli.exe 退出码 ' + build.status + ',请查看 HBuilderX 控制台输出');
|
|
// 3) 校正产物 appid(--sync 时通常已一致,这里兜底保证)
|
if (!fs.existsSync(DIST_CONFIG)) {
|
fail('发行产物缺少 project.config.json:' + DIST_CONFIG + '\n 请确认 HBuilderX 编译是否成功');
|
}
|
const before = readAppId(DIST_CONFIG);
|
const after = writeAppId(DIST_CONFIG, env.APPID);
|
if (!after) fail('回写产物 appid 失败:' + DIST_CONFIG);
|
console.log('[release] 产物 appid : ' + before + (before === after ? '(无需调整)' : ' → ' + after));
|
|
// 4) 用微信开发者工具打开产物(首次需在「设置-安全设置」中开启服务端口)
|
if (!noOpen) {
|
console.log('[release] 打开微信开发者工具…');
|
const open = spawnSync(openCmd, { cwd: ROOT, stdio: 'inherit', shell: true });
|
if (open.error || open.status !== 0) {
|
console.log('[release] 自动打开失败(常见原因:未开启服务端口、微信开发者工具版本较旧)');
|
console.log('[release] 请手动打开微信开发者工具 → 导入项目 → 选择目录:' + DIST_DIR);
|
}
|
}
|
|
console.log('[release] 完成。微信开发者工具中的项目 appid = ' + after + ',包内会自动使用 ' + env.HTTP_REQUEST_URL);
|
}
|
|
main();
|