mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
perf(cli): defer Playwright and isomorphic-git until a command needs them
Load browser composition after CLI scenario validation and load Git support only for local reference trees with Git metadata. Preserve default outputs and actual command behavior. Refs #1065. Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
This commit is contained in:
1 parent
bb6fa1c6f5
commit
eeb83f6581
3 files changed
+81
-3
No files matched your search
@@ -2,8 +2,6 @@ import fs from "node:fs";
|
||||
import { lstat, readFile } from "node:fs/promises";
|
||||
import { join, resolve } from "node:path";
|
||||
|
||||
import { resolveRef } from "isomorphic-git";
|
||||
|
||||
export type ReferenceSourceVcsInfo =
|
||||
| {
|
||||
readonly kind: "git";
|
||||
@@ -42,6 +40,8 @@ export const readReferenceSourceVcs = async (
|
||||
};
|
||||
|
||||
const resolveSourceHead = async (root: string): Promise<string> => {
|
||||
// isomorphic-git is loaded on first use so CLI and MCP startup skip it.
|
||||
const { resolveRef } = await import("isomorphic-git");
|
||||
const dotgit = join(root, ".git");
|
||||
if (!(await lstat(dotgit)).isFile())
|
||||
return resolveRef({ fs, dir: root, ref: "HEAD" });
|
||||
|
||||
@@ -2,7 +2,6 @@ import { Cli } from "incur";
|
||||
import { z } from "zod";
|
||||
|
||||
import { captureBrowserScenario } from "./application/BrowserScenarioCaptureService.js";
|
||||
import { createBrowserScenarioProvider } from "./composition/browserScenario.js";
|
||||
import { CLI_COMMANDS } from "./cliCommandNames.js";
|
||||
import { parseCliJsonInput, resolveCliJsonPaths } from "./cliJsonInput.js";
|
||||
import { logCliCommand } from "./cliLogging.js";
|
||||
@@ -44,6 +43,9 @@ export const registerBrowserScenarioCommands = (
|
||||
projectInputIssues(scenario.error.issues, input.value),
|
||||
),
|
||||
);
|
||||
// Load Playwright only for this command, not during CLI startup.
|
||||
const { createBrowserScenarioProvider } =
|
||||
await import("./composition/browserScenario.js");
|
||||
const result = await captureBrowserScenario(
|
||||
createBrowserScenarioProvider(environment),
|
||||
scenario.data,
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import { execFile } from "node:child_process";
|
||||
import { mkdir } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { promisify } from "node:util";
|
||||
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
||||
|
||||
const execute = promisify(execFile);
|
||||
const MARKER = "REA_TEST_RESOLVED ";
|
||||
// Dependencies that only one command uses; startup must not resolve them.
|
||||
const DEFERRED_PACKAGES = ["playwright-core", "isomorphic-git"] as const;
|
||||
// Report each resolved deferred package on stderr without changing resolution.
|
||||
const RESOLUTION_HOOK = `data:text/javascript,${encodeURIComponent(`
|
||||
import { registerHooks } from "node:module";
|
||||
const packages = ${JSON.stringify(DEFERRED_PACKAGES)};
|
||||
registerHooks({
|
||||
resolve(specifier, context, next) {
|
||||
const resolved = next(specifier, context);
|
||||
const name = packages.find((item) =>
|
||||
resolved.url.includes("/node_modules/" + item + "/"),
|
||||
);
|
||||
if (name !== undefined)
|
||||
process.stderr.write(${JSON.stringify(MARKER)} + name + "\\n");
|
||||
return resolved;
|
||||
},
|
||||
});
|
||||
`)}`;
|
||||
|
||||
const resolvedPackages = async (
|
||||
arguments_: readonly string[],
|
||||
): Promise<ReadonlySet<string>> => {
|
||||
const { stderr } = await execute(
|
||||
process.execPath,
|
||||
[`--import=${RESOLUTION_HOOK}`, ...arguments_],
|
||||
{ cwd: process.cwd(), maxBuffer: 16 * 1_024 * 1_024 },
|
||||
);
|
||||
return new Set(
|
||||
stderr
|
||||
.split("\n")
|
||||
.filter((line) => line.startsWith(MARKER))
|
||||
.map((line) => line.slice(MARKER.length)),
|
||||
);
|
||||
};
|
||||
|
||||
const evaluate = (source: string): readonly string[] => [
|
||||
"--input-type=module",
|
||||
"--eval",
|
||||
source,
|
||||
];
|
||||
|
||||
describe("CLI startup imports", () => {
|
||||
it("detects each deferred package when its command code loads", async () => {
|
||||
await expect(
|
||||
resolvedPackages(
|
||||
evaluate('await import("./dist/composition/browserScenario.js");'),
|
||||
),
|
||||
).resolves.toContain("playwright-core");
|
||||
const source = await createTestTempDirectory("rea-startup-imports-");
|
||||
await mkdir(join(source, ".git"));
|
||||
await expect(
|
||||
resolvedPackages(
|
||||
evaluate(
|
||||
`const { readReferenceSourceVcs } = await import("./dist/application/ReferenceSourceVcsAdapter.js"); await readReferenceSourceVcs(${JSON.stringify(source)});`,
|
||||
),
|
||||
),
|
||||
).resolves.toContain("isomorphic-git");
|
||||
});
|
||||
|
||||
it("does not load command-specific packages to register commands", async () => {
|
||||
await expect(
|
||||
resolvedPackages(["scripts/rea.mjs", "--help"]),
|
||||
).resolves.toEqual(new Set());
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user