Files
xk-admin/build-antd-desktop.mjs

156 lines
4.6 KiB
JavaScript
Raw Permalink Normal View History

/**
* 根目录一键打包:web-antd 生产构建 + 桌面端 Electron 安装包
*
* 为什么不能真正并行 pack:
* electron-builder 会把 apps/web-antd/dist 拷进安装包(extraResources),
* 所以必须先有 web dist,再打桌面包。turbo 构建阶段可按依赖图并行。
*
* 用法(在仓库根目录):
* node build-antd-desktop.mjs
* node build-antd-desktop.mjs --only=web
* node build-antd-desktop.mjs --only=desktop
* pnpm build:antd-desktop
*/
import { spawn } from 'node:child_process';
import { existsSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const rootDir = __dirname;
const webDistDir = join(rootDir, 'apps/web-antd/dist');
const desktopReleaseDir = join(rootDir, 'apps/desktop/release');
/** 解析 --only=web|desktop|all,默认 all */
function parseOnly() {
const arg = process.argv.find((item) => item.startsWith('--only='));
if (!arg) {
return 'all';
}
const value = arg.slice('--only='.length).trim().toLowerCase();
if (value === 'web' || value === 'antd' || value === 'web-antd') {
return 'web';
}
if (value === 'desktop' || value === 'electron') {
return 'desktop';
}
if (value === 'all') {
return 'all';
}
console.error(`未知 --only 取值: ${value}(支持 web / desktop / all)`);
process.exit(1);
}
/**
* 在仓库根目录执行命令;Windows 下 pnpm 是 .cmd,必须 shell:true
* @param {string} label 日志步骤名
* @param {string} command 完整 shell 命令
*/
function run(label, command) {
const startedAt = Date.now();
console.log(`\n========== ${label} ==========`);
console.log(`$ ${command}\n`);
return new Promise((resolve, reject) => {
const child = spawn(command, {
cwd: rootDir,
env: {
...process.env,
// web / electron 构建都偏吃内存,对齐根 package.json 的 build 配置
NODE_OPTIONS:
process.env.NODE_OPTIONS || '--max-old-space-size=8192',
},
shell: true,
stdio: 'inherit',
});
child.on('error', reject);
child.on('close', (code) => {
const seconds = ((Date.now() - startedAt) / 1000).toFixed(1);
if (code === 0) {
console.log(`\n✅ ${label} 完成(${seconds}s)`);
resolve();
return;
}
reject(new Error(`${label} 失败,退出码 ${code}`));
});
});
}
/** 仅打 web-antd(产物:apps/web-antd/dist) */
async function buildWebOnly() {
await run('构建 Web(@vben/web-antd)', 'pnpm run build:antd');
assertWebDist();
}
/**
* 仅打桌面:依赖已有 web dist(turbo ^build 仍可能按缓存跳过 web)
* 对应根脚本 build:desktop
*/
async function buildDesktopOnly() {
assertWebDist(
`桌面端打包需要 web 产物,但未找到 ${webDistDir}。请先执行 web 构建,或去掉 --only=desktop`,
);
await run('构建并打包桌面端(@vben/desktop)', 'pnpm run build:desktop');
}
/**
* Web + 桌面一次搞定:turbo 同时 filter 两端(共享包只编一次),再 pack 安装包
* 避免「先 build:antd 再 build:desktop」导致 web 被无必要打两遍
*/
async function buildAll() {
await run(
'构建 Web + 桌面主进程(turbo)',
'pnpm run build --filter=@vben/web-antd --filter=@vben/desktop',
);
assertWebDist();
await run(
'打包桌面安装包(electron-builder)',
'pnpm -F @vben/desktop run pack',
);
}
/** @param {string} [message] */
function assertWebDist(message) {
if (!existsSync(webDistDir)) {
throw new Error(message || `未找到 web 产物目录: ${webDistDir}`);
}
}
function printSummary(only) {
console.log('\n========== 打包结果 ==========');
if (only === 'web' || only === 'all') {
console.log(`Web 产物: ${webDistDir}`);
}
if (only === 'desktop' || only === 'all') {
console.log(`桌面安装包: ${desktopReleaseDir}`);
}
console.log('');
}
async function main() {
const only = parseOnly();
const totalStartedAt = Date.now();
console.log('萧康云医一键打包');
console.log(`模式: ${only}`);
console.log(`根目录: ${rootDir}`);
if (only === 'web') {
await buildWebOnly();
} else if (only === 'desktop') {
await buildDesktopOnly();
} else {
await buildAll();
}
printSummary(only);
const totalSeconds = ((Date.now() - totalStartedAt) / 1000).toFixed(1);
console.log(`全部完成,总耗时 ${totalSeconds}s`);
}
main().catch((error) => {
console.error(`\n❌ ${error.message || error}`);
process.exit(1);
});