diff --git a/.changeset/polite-llamas-notice.md b/.changeset/polite-llamas-notice.md new file mode 100644 index 00000000..425821f9 --- /dev/null +++ b/.changeset/polite-llamas-notice.md @@ -0,0 +1,5 @@ +--- +"vinxi": patch +--- + +perf: run each router build in separate node processes diff --git a/packages/vinxi/bin/cli.mjs b/packages/vinxi/bin/cli.mjs index ca5506d3..d11ac0e8 100755 --- a/packages/vinxi/bin/cli.mjs +++ b/packages/vinxi/bin/cli.mjs @@ -203,6 +203,10 @@ const command = defineCommand({ type: "string", description: "Server preset (default: node-server)", }, + router: { + type: "string", + description: "Router to build (by default, vinxi builds all your routers in separate processed and then into an app bundle, use this option to just build a single router", + }, version: { type: "boolean", description: "Print the versions of Vinxi core dependencies", @@ -224,7 +228,7 @@ const command = defineCommand({ } process.env.NODE_ENV = "production"; const { createBuild } = await import("../lib/build.js"); - await createBuild(app, { preset: args.preset }); + await createBuild(app, { preset: args.preset, router: args.router }); }, }, start: { diff --git a/packages/vinxi/lib/build.js b/packages/vinxi/lib/build.js index 381bcb1d..66d611dd 100644 --- a/packages/vinxi/lib/build.js +++ b/packages/vinxi/lib/build.js @@ -29,12 +29,35 @@ const require = createRequire(import.meta.url); * @param {BuildConfig} buildConfig */ export async function createBuild(app, buildConfig) { - console.log("\n"); - console.log(`⚙ ${c.green("Building your app...")}`); - await app.hooks.callHook("app:build:start", { app, buildConfig }); const { existsSync, promises: fsPromises, readFileSync } = await import("fs"); const { join } = await import("./path.js"); const { fileURLToPath } = await import("url"); + + if (buildConfig.router) { + console.log("\n"); + console.log(`⚙ ${c.green(`Building your router ${buildConfig.router}...`)}`); + let router = app.config.routers.find((r) => r.name === buildConfig.router); + if (router.build !== false) { + if (existsSync(router.outDir)) { + await withLogger({ router, requestId: "clean" }, async () => { + console.log(`removing ${router.outDir}`); + await fsPromises.rm(router.outDir, { recursive: true }); + }); + } + + await withLogger({ router, requestId: "build" }, async () => { + await createRouterBuild(app, router); + }); + } + + console.log(`⚙ ${c.green(`Built your router ${buildConfig.router} successfully`)}`); + return + } + + console.log("\n"); + console.log(`⚙ ${c.green("Building your app...")}`); + await app.hooks.callHook("app:build:start", { app, buildConfig }); + app.config.routers = app.config.routers.filter( (router) => router.build !== false, ); @@ -56,7 +79,7 @@ export async function createBuild(app, buildConfig) { for (const router of app.config.routers) { if (router.type !== "static" && router.build !== false) { await withLogger({ router, requestId: "build" }, async () => { - await createRouterBuild(app, router); + await createRouterBuildInWorker(app, router); }); } } @@ -323,6 +346,11 @@ async function createViteBuild(config) { return output; } +async function createRouterBuildInWorker(app, router) { + const sh = await import("../runtime/sh.js"); + const { fileURLToPath } = await import("url"); + await sh.default`node ${fileURLToPath(new URL("../bin/cli.mjs", import.meta.url).href)} build --router=${router.name}`; +} /** * * @param {import("./app.js").App} app