From 27709a99b1a2d3f1e58ab77d5a0e6b48d4626bc1 Mon Sep 17 00:00:00 2001 From: Devin Foley Date: Sun, 18 Oct 2026 12:16:13 -0700 Subject: [PATCH] perf(scripts): emit a server module beside the runtime bundle entry (#16765) The runtime bundle now also has a server entry point, dist-runtime/server.mjs: the bundled dist/index.js without the argv shim. index.mjs loads it, so importing server.mjs loads the server code without starting it, and a compile cache warmed from it covers exactly the files a boot loads. bundleRuntime reports it as serverModule. Co-Authored-By: Paperclip --- server/scripts/bundle-runtime.mjs | 9 +++++++-- server/scripts/bundle-runtime.test.mjs | 13 +++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/server/scripts/bundle-runtime.mjs b/server/scripts/bundle-runtime.mjs index 84ed23a92b6..7e36010e2d1 100644 --- a/server/scripts/bundle-runtime.mjs +++ b/server/scripts/bundle-runtime.mjs @@ -74,7 +74,7 @@ function externalizeThirdParty(isBundled, runtimeDir) { export async function bundleRuntime({ entry, outdir, isBundled = (specifier) => specifier.startsWith("@paperclipai/") }) { await rm(outdir, { recursive: true, force: true }); const result = await build({ - entryPoints: { index: "paperclip-runtime-entry" }, + entryPoints: { index: "paperclip-runtime-entry", server: entry }, outdir, outExtension: { ".js": ".mjs" }, chunkNames: "chunk-[hash]", @@ -92,7 +92,12 @@ export async function bundleRuntime({ entry, outdir, isBundled = (specifier) => plugins: [runtimeEntry(entry), keepModuleLocations, externalizeThirdParty(isBundled, dirname(entry))], }); const outputs = Object.keys(result.metafile.outputs).filter((file) => file.endsWith(".mjs")); - return { outfile: join(outdir, "index.mjs"), inputs: Object.keys(result.metafile.inputs).length, chunks: outputs.length }; + return { + outfile: join(outdir, "index.mjs"), + serverModule: join(outdir, "server.mjs"), + inputs: Object.keys(result.metafile.inputs).length, + chunks: outputs.length, + }; } async function main() { diff --git a/server/scripts/bundle-runtime.test.mjs b/server/scripts/bundle-runtime.test.mjs index 95e8abf4bfa..14b0d46c681 100644 --- a/server/scripts/bundle-runtime.test.mjs +++ b/server/scripts/bundle-runtime.test.mjs @@ -2,6 +2,7 @@ import { execFile } from "node:child_process"; import { mkdirSync, mkdtempSync, realpathSync, rmSync, symlinkSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import path from "node:path"; +import { pathToFileURL } from "node:url"; import { promisify } from "node:util"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; @@ -84,6 +85,18 @@ describe("bundleRuntime", () => { expect(output.entryDir).toBe(path.join(root, "server", "dist")); }); + it("emits a server module that loads without starting the server", async () => { + const outdir = path.join(root, "server", "dist-runtime"); + const summary = await bundleRuntime({ entry: path.join(root, "server", "dist", "index.js"), outdir }); + expect(summary.serverModule).toBe(path.join(outdir, "server.mjs")); + const probe = path.join(root, "server", "probe.mjs"); + write(probe, `await import(${JSON.stringify(pathToFileURL(summary.serverModule).href)});\nconsole.log("loaded");\n`); + const loaded = await execFileAsync(process.execPath, [probe], { cwd: path.join(root, "server"), timeout: 30_000 }); + expect(loaded.stdout.trim()).toBe("loaded"); + const started = await execFileAsync(process.execPath, [summary.outfile], { cwd: path.join(root, "server"), timeout: 30_000 }); + expect(JSON.parse(started.stdout).late).toBe(43); + }); + it("leaves the server's own dependencies to runtime resolution", async () => { const outdir = path.join(root, "server", "dist-runtime"); const summary = await bundleRuntime({ entry: path.join(root, "server", "dist", "index.js"), outdir });