Files
mnote/scripts/prepare-desktop-next.js
T
2026-02-01 08:47:40 +08:00

122 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
/**
* 生成桌面端内置的 Next standalone 产物到 `desktop-electron/desktop-next`。
*
* 目标:
* - 打包时不依赖用户机器上的 pnpm / node 环境即可运行(Electron 自身携带 Node)。
* - 运行期文件读写落到安装目录的 data/(由 Electron 注入 MNOTE_DATA_DIR)。
*
* 注意:需要 wolai-frontend 的 next.config.ts 开启 output: "standalone"。
*/
const { spawnSync } = require("child_process");
const fs = require("fs");
const path = require("path");
const rootDir = path.resolve(__dirname, "..");
const frontendDir = path.join(rootDir, "wolai-frontend");
const outDir = path.join(rootDir, "desktop-electron", "desktop-next");
function parseDotenv(filePath) {
if (!fs.existsSync(filePath)) return {};
const raw = fs.readFileSync(filePath, { encoding: "utf8" });
const out = {};
for (const line of raw.split(/\r?\n/)) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith("#")) continue;
const idx = trimmed.indexOf("=");
if (idx === -1) continue;
const key = trimmed.slice(0, idx).trim();
const value = trimmed.slice(idx + 1).trim();
if (!key) continue;
out[key] = value;
}
return out;
}
function ensureDir(dir) {
fs.mkdirSync(dir, { recursive: true });
}
function rmDir(dir) {
fs.rmSync(dir, { recursive: true, force: true });
}
function run(command, cwd, env) {
const r = spawnSync(command, {
cwd,
env: { ...process.env, ...env },
stdio: "inherit",
shell: true,
});
if (r.status !== 0) {
process.exit(r.status ?? 1);
}
}
function assertExists(filePath, hint) {
if (!fs.existsSync(filePath)) {
console.error(`\n[prepare-desktop-next] 缺少:${filePath}`);
if (hint) console.error(`[prepare-desktop-next] 提示:${hint}`);
process.exit(1);
}
}
function copyDir(from, to) {
// 关键:Next standalone 在 pnpm 环境下可能包含大量 symlink/junction。
// electron-builder 在复制 extraResources 时对链接目录处理不稳定,
// 因此这里强制“解引用复制”,把真实文件复制出来,确保运行期能 require('next')。
fs.cpSync(from, to, { recursive: true, force: true, dereference: true });
}
function main() {
console.log("[prepare-desktop-next] 开始构建 wolai-frontendstandalone)…");
// 约定:全局仅使用仓库根目录的 .env.all 作为配置来源(生产优先)。
// 桌面端如需覆盖,可通过系统环境变量注入(例如在启动命令前临时设置)。
const envAllPath = path.join(rootDir, ".env.all");
assertExists(envAllPath, "请先在仓库根目录创建 .env.all(全局唯一 env 文件)。");
const desktopEnv = {
...parseDotenv(envAllPath),
};
console.log("[prepare-desktop-next] 桌面端 env 摘要:", {
NEXT_PUBLIC_BACKEND_URL: desktopEnv.NEXT_PUBLIC_BACKEND_URL,
NEXT_PUBLIC_ONLYOFFICE_BASE_URL: desktopEnv.NEXT_PUBLIC_ONLYOFFICE_BASE_URL,
});
run("pnpm -C wolai-frontend build", rootDir, {
NODE_ENV: "production",
NEXT_TELEMETRY_DISABLED: "1",
...desktopEnv,
});
const standaloneDir = path.join(frontendDir, ".next", "standalone");
const staticDir = path.join(frontendDir, ".next", "static");
const publicDir = path.join(frontendDir, "public");
assertExists(
path.join(standaloneDir, "server.js"),
'请在 wolai-frontend/next.config.ts 增加 `output: "standalone"` 后重试。',
);
assertExists(staticDir, "Next build 未生成 .next/static(可能构建失败或目录异常)。");
assertExists(publicDir, "wolai-frontend/public 不存在。");
console.log(`[prepare-desktop-next] 清理旧产物:${outDir}`);
rmDir(outDir);
ensureDir(outDir);
console.log("[prepare-desktop-next] 复制 standalone …");
copyDir(standaloneDir, outDir);
console.log("[prepare-desktop-next] 补齐 .next/static …");
ensureDir(path.join(outDir, ".next"));
copyDir(staticDir, path.join(outDir, ".next", "static"));
console.log("[prepare-desktop-next] 补齐 public …");
copyDir(publicDir, path.join(outDir, "public"));
console.log("[prepare-desktop-next] 完成。");
}
main();