2024-09-08 23:46:15 +08:00

264 lines
6.1 KiB
TypeScript

process.env.NODE_ENV = "development";
import electron from "electron";
import chalk from "chalk";
import {join} from "path";
import {watch} from "rollup";
import Portfinder from "portfinder";
import config from "../config";
import {say} from "cfonts";
import {spawn} from "child_process";
import type {ChildProcess} from "child_process";
import rollupOptions from "./rollup.config";
const mainOpt = rollupOptions(process.env.NODE_ENV, "main");
const preloadOpt = rollupOptions(process.env.NODE_ENV, "preload");
let electronProcess: ChildProcess | null = null;
let manualRestart = false;
function logStats(proc: string, data: any) {
let log = "";
log += chalk.yellow.bold(
`${proc} ${config.dev.chineseLog ? "编译过程" : "Process"} ${new Array(
19 - proc.length + 1
).join("-")}`
);
log += "\n\n";
if (typeof data === "object") {
data
.toString({
colors: true,
chunks: false,
})
.split(/\r?\n/)
.forEach((line) => {
log += " " + line + "\n";
});
} else {
log += ` ${data}\n`;
}
log += "\n" + chalk.yellow.bold(`${new Array(28 + 1).join("-")}`) + "\n";
console.log(log);
}
function removeJunk(chunk: string) {
if (config.dev.removeElectronJunk) {
// Example: 2018-08-10 22:48:42.866 Electron[90311:4883863] *** WARNING: Textured window <AtomNSWindow: 0x7fb75f68a770>
if (
/\d+-\d+-\d+ \d+:\d+:\d+\.\d+ Electron(?: Helper)?\[\d+:\d+] /.test(chunk)
) {
return false;
}
// Example: [90789:0810/225804.894349:ERROR:CONSOLE(105)] "Uncaught (in promise) Error: Could not instantiate: ProductRegistryImpl.Registry", source: chrome-devtools://devtools/bundled/inspector.js (105)
if (/\[\d+:\d+\/|\d+\.\d+:ERROR:CONSOLE\(\d+\)\]/.test(chunk)) {
return false;
}
// Example: ALSA lib confmisc.c:767:(parse_card) cannot find card '0'
if (/ALSA lib [a-z]+\.c:\d+:\([a-z_]+\)/.test(chunk)) {
return false;
}
}
return chunk;
}
function startRenderer(): Promise<void> {
return new Promise((resolve, reject) => {
Portfinder.basePort = config.dev.port || 9080;
Portfinder.getPort(async (err, port) => {
if (err) {
reject("PortError:" + err);
} else {
const {createServer} = await import("vite");
const server = await createServer({
configFile: join(__dirname, "vite.config.mts"),
});
process.env.PORT = String(port);
await server.listen(port);
console.log(
"\n\n" +
chalk.blue(
`${
config.dev.chineseLog
? " 正在准备主进程,请等待..."
: " Preparing main process, please wait..."
}`
) +
"\n\n"
);
resolve();
}
});
});
}
function startMain(): Promise<void> {
return new Promise((resolve, reject) => {
const MainWatcher = watch(mainOpt);
MainWatcher.on("change", (filename) => {
// 主进程日志部分
logStats(
`${config.dev.chineseLog ? "主进程文件变更" : "Main-FileChange"}`,
filename
);
});
MainWatcher.on("event", (event) => {
if (event.code === "END") {
if (electronProcess) {
manualRestart = true;
electronProcess.pid && process.kill(electronProcess.pid);
electronProcess = null;
startElectron();
setTimeout(() => {
manualRestart = false;
}, 5000);
}
resolve();
} else if (event.code === "ERROR") {
reject(event.error);
}
});
});
}
function startPreload(): Promise<void> {
console.log(
"\n\n" +
chalk.blue(
`${
config.dev.chineseLog
? " 正在准备预加载脚本,请等待..."
: " Preparing preLoad File, please wait..."
}`
) +
"\n\n"
);
return new Promise((resolve, reject) => {
const PreloadWatcher = watch(preloadOpt);
PreloadWatcher.on("change", (filename) => {
// 预加载脚本日志部分
logStats(
`${
config.dev.chineseLog ? "预加载脚本文件变更" : "preLoad-FileChange"
}`,
filename
);
});
PreloadWatcher.on("event", (event) => {
if (event.code === "END") {
if (electronProcess) {
manualRestart = true;
electronProcess.pid && process.kill(electronProcess.pid);
electronProcess = null;
startElectron();
setTimeout(() => {
manualRestart = false;
}, 5000);
}
resolve();
} else if (event.code === "ERROR") {
reject(event.error);
}
});
});
}
function startElectron() {
let args = [
"--inspect=5858",
join(__dirname, "../dist/electron/main/main.js"),
];
// detect yarn or npm and process commandline args accordingly
if (process.env.npm_execpath?.endsWith("yarn.js")) {
args = args.concat(process.argv.slice(3));
} else if (process.env.npm_execpath?.endsWith("npm-cli.js")) {
args = args.concat(process.argv.slice(2));
}
electronProcess = spawn(electron as any, args);
electronProcess.stdout?.on("data", (data: string) => {
electronLog(removeJunk(data), "blue");
});
electronProcess.stderr?.on("data", (data: string) => {
electronLog(removeJunk(data), "red");
});
electronProcess.on("close", () => {
if (!manualRestart) process.exit();
});
}
function electronLog(data: any, color: string) {
if (data) {
let log = "";
data = data.toString().split(/\r?\n/);
data.forEach((line) => {
log += ` ${line}\n`;
});
console.log(
chalk[color].bold(
`${
config.dev.chineseLog ? "主程序日志" : "Electron"
} -------------------`
) +
"\n\n" +
log +
chalk[color].bold("┗ ----------------------------") +
"\n"
);
}
}
function greeting(arg: string) {
const cols = process.stdout.columns;
let text: string;
text = arg ? arg : "Hi-Sass";
let length = text ? text.length : 0;
if (cols > 104) {
text = length > 104 ? text.slice(0, 103) : text;
} else if (cols > 76) {
text = length > 76 ? text.slice(0, 75) : text;
} else text = "";
if (text) {
say(text, {
colors: ["yellow"],
font: "simple3d",
space: false,
});
} else console.log(chalk.yellow.bold("\n electron-vite"));
console.log(
chalk.blue(
`${config.dev.chineseLog ? " 准备启动..." : " getting ready..."}`
) + "\n"
);
}
async function init() {
greeting("Hi-Sass");
try {
await startRenderer();
await startMain();
await startPreload();
startElectron();
} catch (error) {
console.error(error);
process.exit(1);
}
}
init();