156 lines
4.6 KiB
JavaScript
156 lines
4.6 KiB
JavaScript
/**
|
||
* 根目录一键打包: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);
|
||
});
|