feat(tree): close rust family shell cutover

This commit is contained in:
lix-2026
2026-04-28 16:30:51 +08:00
parent 4ab36a9386
commit 7965c6c107
75 changed files with 9721 additions and 1174 deletions
@@ -0,0 +1,122 @@
#!/usr/bin/env node
"use strict";
const fs = require("fs/promises");
const path = require("path");
const { spawnSync } = require("child_process");
const REPO_ROOT = path.resolve(__dirname, "..", "..");
const RUST_ROOT = path.join(REPO_ROOT, "rust");
const CRATE_ROOT = path.join(RUST_ROOT, "crates", "tree-shell-runtime-wasm");
const GENERATED_ROOT = path.join(CRATE_ROOT, "generated");
const TOOLCHAIN = "1.89.0-x86_64-unknown-linux-gnu";
const TARGET = "wasm32-unknown-unknown";
const OUT_NAME = "mnote-tree-shell-runtime";
const MANIFEST_PATH = path.join(CRATE_ROOT, "Cargo.toml");
const WASM_PATH = path.join(
RUST_ROOT,
"target",
TARGET,
"debug",
"tree_shell_runtime_wasm.wasm",
);
const ENTRY_PATH = path.join(GENERATED_ROOT, `${OUT_NAME}.js`);
const OUTPUT_WASM_PATH = path.join(GENERATED_ROOT, `${OUT_NAME}_bg.wasm`);
const GITIGNORE_PATH = path.join(GENERATED_ROOT, ".gitignore");
function run(command, args, options = {}) {
const result = spawnSync(command, args, {
cwd: options.cwd ?? REPO_ROOT,
env: process.env,
encoding: "utf8",
stdio: "pipe",
});
if (result.status === 0) {
return result;
}
const stdout = (result.stdout || "").trim();
const stderr = (result.stderr || "").trim();
const details = [stdout, stderr].filter(Boolean).join("\n");
throw new Error(
[`命令失败:${command} ${args.join(" ")}`, details].filter(Boolean).join("\n"),
);
}
async function ensureGeneratedDir() {
await fs.rm(GENERATED_ROOT, { recursive: true, force: true });
await fs.mkdir(GENERATED_ROOT, { recursive: true });
await fs.writeFile(GITIGNORE_PATH, "*\n!.gitignore\n", "utf8");
}
async function verifyOutput() {
const entrySource = await fs.readFile(ENTRY_PATH, "utf8");
await fs.access(OUTPUT_WASM_PATH);
if (!entrySource.includes("export function reduceTreeShellRuntime")) {
throw new Error("tree shell runtime js glue 缺少 reduceTreeShellRuntime 导出");
}
}
async function buildTreeShellRuntime() {
// 说明:tree shell iframe 主链直接加载固定 wasm/js 产物,因此在 Next 启动前先生成正式 artifact。
run("rustup", ["target", "add", TARGET, "--toolchain", TOOLCHAIN], { cwd: RUST_ROOT });
run(
"cargo",
[
`+${TOOLCHAIN}`,
"build",
"--manifest-path",
MANIFEST_PATH,
"--package",
"tree-shell-runtime-wasm",
"--lib",
"--target",
TARGET,
"--locked",
],
{ cwd: RUST_ROOT },
);
await ensureGeneratedDir();
run(
"wasm-bindgen",
[
WASM_PATH,
"--target",
"web",
"--out-dir",
GENERATED_ROOT,
"--out-name",
OUT_NAME,
],
{ cwd: RUST_ROOT },
);
await verifyOutput();
return {
generatedRoot: GENERATED_ROOT,
entryPath: ENTRY_PATH,
wasmPath: OUTPUT_WASM_PATH,
};
}
module.exports = {
buildTreeShellRuntime,
GENERATED_ROOT,
OUT_NAME,
};
if (require.main === module) {
buildTreeShellRuntime()
.then(({ generatedRoot }) => {
process.stdout.write(`tree shell runtime 已生成:${generatedRoot}\n`);
})
.catch((error) => {
process.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
process.exit(1);
});
}
+4
View File
@@ -17,6 +17,7 @@ const net = require("net");
const path = require("path");
const next = require("next");
const { parse: parseUrl } = require("url");
const { buildTreeShellRuntime } = require("./build-tree-shell-runtime");
const { buildLeptosTiptapIsland } = require("./build-leptos-tiptap-island");
const ONLYOFFICE_PREFIX = "/onlyoffice-server";
@@ -390,6 +391,9 @@ async function main() {
const hostname = resolveHostname();
const dev = true;
// 说明:tree shell iframe 通过 3000 同源 js glue + wasm 直接调用 reducer,因此 dev 启动前先生成正式 artifact。
await buildTreeShellRuntime();
// 说明:3000 主链需要直接挂载正式 Leptos island,因此在 Next dev 启动前先生成 lib.rs 的 wasm-bindgen 产物。
await buildLeptosTiptapIsland();