mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:00:43 +00:00
perf: reduce jiti loader alias work
This commit is contained in:
@@ -82,6 +82,13 @@ function applyVitestCapabilityAliasOverrides(params: {
|
||||
};
|
||||
}
|
||||
|
||||
function shouldApplyVitestCapabilityAliasOverrides(params: {
|
||||
pluginSdkResolution?: PluginSdkResolutionPreference;
|
||||
env?: PluginLoadOptions["env"];
|
||||
}): boolean {
|
||||
return Boolean(params.env?.VITEST && params.pluginSdkResolution === "dist");
|
||||
}
|
||||
|
||||
export function buildBundledCapabilityRuntimeConfig(
|
||||
pluginIds: readonly string[],
|
||||
env?: PluginLoadOptions["env"],
|
||||
@@ -193,22 +200,28 @@ export function loadBundledCapabilityRuntimeRegistry(params: {
|
||||
const getJiti = (modulePath: string) => {
|
||||
const tryNative =
|
||||
shouldPreferNativeJiti(modulePath) && !(env?.VITEST && params.pluginSdkResolution === "dist");
|
||||
const aliasMap = applyVitestCapabilityAliasOverrides({
|
||||
aliasMap: buildPluginLoaderAliasMap(
|
||||
modulePath,
|
||||
process.argv[1],
|
||||
import.meta.url,
|
||||
params.pluginSdkResolution,
|
||||
),
|
||||
const aliasMap = shouldApplyVitestCapabilityAliasOverrides({
|
||||
pluginSdkResolution: params.pluginSdkResolution,
|
||||
env,
|
||||
});
|
||||
})
|
||||
? applyVitestCapabilityAliasOverrides({
|
||||
aliasMap: buildPluginLoaderAliasMap(
|
||||
modulePath,
|
||||
process.argv[1],
|
||||
import.meta.url,
|
||||
params.pluginSdkResolution,
|
||||
),
|
||||
pluginSdkResolution: params.pluginSdkResolution,
|
||||
env,
|
||||
})
|
||||
: undefined;
|
||||
return getCachedPluginJitiLoader({
|
||||
cache: jitiLoaders,
|
||||
modulePath,
|
||||
importerUrl: import.meta.url,
|
||||
jitiFilename: import.meta.url,
|
||||
aliasMap,
|
||||
...(aliasMap ? { aliasMap } : {}),
|
||||
pluginSdkResolution: params.pluginSdkResolution,
|
||||
tryNative,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
buildPluginLoaderJitiOptions,
|
||||
createPluginLoaderJitiCacheKey,
|
||||
resolvePluginLoaderJitiConfig,
|
||||
type PluginSdkResolutionPreference,
|
||||
} from "./sdk-alias.js";
|
||||
|
||||
export type PluginJitiLoader = ReturnType<typeof createJiti>;
|
||||
@@ -19,6 +20,7 @@ export function getCachedPluginJitiLoader(params: {
|
||||
createLoader?: PluginJitiLoaderFactory;
|
||||
aliasMap?: Record<string, string>;
|
||||
tryNative?: boolean;
|
||||
pluginSdkResolution?: PluginSdkResolutionPreference;
|
||||
cacheScopeKey?: string;
|
||||
}): PluginJitiLoader {
|
||||
const jitiFilename = params.jitiFilename ?? params.modulePath;
|
||||
@@ -38,23 +40,27 @@ export function getCachedPluginJitiLoader(params: {
|
||||
argv1: params.argvEntry ?? process.argv[1],
|
||||
moduleUrl: params.importerUrl,
|
||||
...(params.preferBuiltDist ? { preferBuiltDist: true } : {}),
|
||||
...(params.pluginSdkResolution
|
||||
? { pluginSdkResolution: params.pluginSdkResolution }
|
||||
: {}),
|
||||
})
|
||||
: null;
|
||||
const canReuseDefaultCacheKey =
|
||||
defaultConfig !== null &&
|
||||
(!hasAliasOverride || params.aliasMap === defaultConfig.aliasMap) &&
|
||||
(!hasTryNativeOverride || params.tryNative === defaultConfig.tryNative);
|
||||
const resolved = defaultConfig
|
||||
? {
|
||||
tryNative: params.tryNative ?? defaultConfig.tryNative,
|
||||
aliasMap: params.aliasMap ?? defaultConfig.aliasMap,
|
||||
cacheKey:
|
||||
!hasAliasOverride &&
|
||||
(!hasTryNativeOverride || params.tryNative === defaultConfig.tryNative)
|
||||
? defaultConfig.cacheKey
|
||||
: undefined,
|
||||
cacheKey: canReuseDefaultCacheKey ? defaultConfig.cacheKey : undefined,
|
||||
}
|
||||
: resolvePluginLoaderJitiConfig({
|
||||
modulePath: params.modulePath,
|
||||
argv1: params.argvEntry ?? process.argv[1],
|
||||
moduleUrl: params.importerUrl,
|
||||
...(params.preferBuiltDist ? { preferBuiltDist: true } : {}),
|
||||
...(params.pluginSdkResolution ? { pluginSdkResolution: params.pluginSdkResolution } : {}),
|
||||
});
|
||||
const { tryNative, aliasMap } = resolved;
|
||||
const cacheKey =
|
||||
|
||||
@@ -454,18 +454,12 @@ function createPluginJitiLoader(options: Pick<PluginLoadOptions, "pluginSdkResol
|
||||
const jitiLoaders: PluginJitiLoaderCache = new Map();
|
||||
return (modulePath: string) => {
|
||||
const tryNative = shouldPreferNativeJiti(modulePath);
|
||||
const aliasMap = buildPluginLoaderAliasMap(
|
||||
modulePath,
|
||||
process.argv[1],
|
||||
import.meta.url,
|
||||
options.pluginSdkResolution,
|
||||
);
|
||||
return getCachedPluginJitiLoader({
|
||||
cache: jitiLoaders,
|
||||
modulePath,
|
||||
importerUrl: import.meta.url,
|
||||
jitiFilename: import.meta.url,
|
||||
aliasMap,
|
||||
pluginSdkResolution: options.pluginSdkResolution,
|
||||
// Source .ts runtime shims import sibling ".js" specifiers that only exist
|
||||
// after build. Disable native loading for source entries so Jiti rewrites
|
||||
// those imports against the source graph, while keeping native dist/*.js
|
||||
|
||||
@@ -7,7 +7,6 @@ import { resolveBundledPluginsDir } from "./bundled-dir.js";
|
||||
import { getCachedPluginJitiLoader, type PluginJitiLoaderCache } from "./jiti-loader-cache.js";
|
||||
import { resolveBundledPluginPublicSurfacePath } from "./public-surface-runtime.js";
|
||||
import {
|
||||
buildPluginLoaderAliasMap,
|
||||
isBundledPluginExtensionPath,
|
||||
resolvePluginLoaderJitiTryNative,
|
||||
resolveLoaderPackageRoot,
|
||||
@@ -129,14 +128,12 @@ function getSharedBundledPublicSurfaceJiti(modulePath: string, tryNative: boolea
|
||||
return null;
|
||||
}
|
||||
const cacheKey = tryNative ? "bundled:native" : "bundled:source";
|
||||
const aliasMap = buildPluginLoaderAliasMap(modulePath, process.argv[1], import.meta.url);
|
||||
return getCachedPluginJitiLoader({
|
||||
cache: sharedBundledPublicSurfaceJitiLoaders,
|
||||
modulePath,
|
||||
importerUrl: import.meta.url,
|
||||
jitiFilename: import.meta.url,
|
||||
cacheScopeKey: cacheKey,
|
||||
aliasMap,
|
||||
tryNative,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import path from "node:path";
|
||||
import { loadConfig } from "../../config/config.js";
|
||||
import { getCachedPluginJitiLoader, type PluginJitiLoaderCache } from "../jiti-loader-cache.js";
|
||||
import { loadPluginManifestRegistry } from "../manifest-registry.js";
|
||||
import { buildPluginLoaderAliasMap, shouldPreferNativeJiti } from "../sdk-alias.js";
|
||||
import { shouldPreferNativeJiti } from "../sdk-alias.js";
|
||||
|
||||
type PluginRuntimeRecord = {
|
||||
origin?: string;
|
||||
@@ -116,13 +116,11 @@ export function resolvePluginRuntimeModulePath(
|
||||
|
||||
export function getPluginBoundaryJiti(modulePath: string, loaders: PluginJitiLoaderCache) {
|
||||
const tryNative = shouldPreferNativeJiti(modulePath);
|
||||
const aliasMap = buildPluginLoaderAliasMap(modulePath);
|
||||
return getCachedPluginJitiLoader({
|
||||
cache: loaders,
|
||||
modulePath,
|
||||
importerUrl: import.meta.url,
|
||||
jitiFilename: import.meta.url,
|
||||
aliasMap,
|
||||
tryNative,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -699,6 +699,35 @@ describe("plugin sdk alias helpers", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("falls back to source plugin-sdk subpath aliases when dist chunks are stale", () => {
|
||||
const fixture = createPluginSdkAliasFixture({
|
||||
srcFile: "provider-entry.ts",
|
||||
distFile: "provider-entry.js",
|
||||
distBody: 'import { entry } from "../missing-provider-entry-chunk.js";\nexport { entry };\n',
|
||||
packageExports: {
|
||||
"./plugin-sdk/provider-entry": { default: "./dist/plugin-sdk/provider-entry.js" },
|
||||
},
|
||||
});
|
||||
const sourceProviderEntryPath = path.join(
|
||||
fixture.root,
|
||||
"src",
|
||||
"plugin-sdk",
|
||||
"provider-entry.ts",
|
||||
);
|
||||
const sourcePluginEntry = writePluginEntry(
|
||||
fixture.root,
|
||||
bundledPluginFile("demo", "src/index.ts"),
|
||||
);
|
||||
|
||||
const distAliases = withEnv({ NODE_ENV: undefined }, () =>
|
||||
buildPluginLoaderAliasMap(sourcePluginEntry, undefined, undefined, "dist"),
|
||||
);
|
||||
|
||||
expect(fs.realpathSync(distAliases["openclaw/plugin-sdk/provider-entry"] ?? "")).toBe(
|
||||
fs.realpathSync(sourceProviderEntryPath),
|
||||
);
|
||||
});
|
||||
|
||||
it("builds source plugin-sdk subpath aliases through the wider source extension family", () => {
|
||||
const { fixture, sourceRootAlias, sourceChannelRuntimePath } =
|
||||
createPluginSdkAliasTargetFixture({
|
||||
@@ -939,7 +968,45 @@ describe("plugin sdk alias helpers", () => {
|
||||
preferBuiltDist: true,
|
||||
});
|
||||
|
||||
expect(second).toEqual(first);
|
||||
expect(second).toBe(first);
|
||||
});
|
||||
|
||||
it("scopes plugin loader Jiti config by plugin-sdk resolution", () => {
|
||||
const { fixture, sourceRootAlias, distRootAlias } = createPluginSdkAliasTargetFixture();
|
||||
const sourcePluginEntry = writePluginEntry(
|
||||
fixture.root,
|
||||
bundledPluginFile("demo", "src/index.ts"),
|
||||
);
|
||||
|
||||
const { auto, dist, distAgain } = withEnv({ NODE_ENV: undefined }, () => ({
|
||||
auto: resolvePluginLoaderJitiConfig({
|
||||
modulePath: sourcePluginEntry,
|
||||
argv1: path.join(fixture.root, "openclaw.mjs"),
|
||||
moduleUrl: pathToFileURL(path.join(fixture.root, "src/plugins/loader.ts")).href,
|
||||
pluginSdkResolution: "auto",
|
||||
}),
|
||||
dist: resolvePluginLoaderJitiConfig({
|
||||
modulePath: sourcePluginEntry,
|
||||
argv1: path.join(fixture.root, "openclaw.mjs"),
|
||||
moduleUrl: pathToFileURL(path.join(fixture.root, "src/plugins/loader.ts")).href,
|
||||
pluginSdkResolution: "dist",
|
||||
}),
|
||||
distAgain: resolvePluginLoaderJitiConfig({
|
||||
modulePath: sourcePluginEntry,
|
||||
argv1: path.join(fixture.root, "openclaw.mjs"),
|
||||
moduleUrl: pathToFileURL(path.join(fixture.root, "src/plugins/loader.ts")).href,
|
||||
pluginSdkResolution: "dist",
|
||||
}),
|
||||
}));
|
||||
|
||||
expect(distAgain).toBe(dist);
|
||||
expect(auto).not.toBe(dist);
|
||||
expect(fs.realpathSync(auto.aliasMap["openclaw/plugin-sdk"] ?? "")).toBe(
|
||||
fs.realpathSync(sourceRootAlias),
|
||||
);
|
||||
expect(fs.realpathSync(dist.aliasMap["openclaw/plugin-sdk"] ?? "")).toBe(
|
||||
fs.realpathSync(distRootAlias),
|
||||
);
|
||||
});
|
||||
|
||||
it("detects bundled plugin extension paths across source and dist roots", () => {
|
||||
|
||||
@@ -260,6 +260,35 @@ const PLUGIN_SDK_SOURCE_CANDIDATE_EXTENSIONS = [
|
||||
".cts",
|
||||
".cjs",
|
||||
] as const;
|
||||
const JS_STATIC_RELATIVE_DEPENDENCY_PATTERN =
|
||||
/(?:\bfrom\s*["']|\bimport\s*\(\s*["']|\brequire\s*\(\s*["'])(\.{1,2}\/[^"']+)["']/g;
|
||||
|
||||
function isUsableDistPluginSdkArtifact(candidate: string): boolean {
|
||||
if (!fs.existsSync(candidate)) {
|
||||
return false;
|
||||
}
|
||||
switch (normalizeLowercaseStringOrEmpty(path.extname(candidate))) {
|
||||
case ".js":
|
||||
case ".mjs":
|
||||
case ".cjs":
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
const source = fs.readFileSync(candidate, "utf-8");
|
||||
for (const match of source.matchAll(JS_STATIC_RELATIVE_DEPENDENCY_PATTERN)) {
|
||||
const specifier = match[1];
|
||||
if (!specifier || fs.existsSync(path.resolve(path.dirname(candidate), specifier))) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function readPrivateLocalOnlyPluginSdkSubpaths(packageRoot: string): string[] {
|
||||
try {
|
||||
@@ -283,7 +312,7 @@ function shouldIncludePrivateLocalOnlyPluginSdkSubpaths() {
|
||||
|
||||
function hasPluginSdkSubpathArtifact(packageRoot: string, subpath: string) {
|
||||
const distPath = path.join(packageRoot, "dist", "plugin-sdk", `${subpath}.js`);
|
||||
if (fs.existsSync(distPath)) {
|
||||
if (isUsableDistPluginSdkArtifact(distPath)) {
|
||||
return true;
|
||||
}
|
||||
return PLUGIN_SDK_SOURCE_CANDIDATE_EXTENSIONS.some((ext) =>
|
||||
@@ -369,7 +398,7 @@ export function resolvePluginSdkScopedAliasMap(
|
||||
for (const kind of orderedKinds) {
|
||||
if (kind === "dist") {
|
||||
const candidate = path.join(packageRoot, "dist", "plugin-sdk", `${subpath}.js`);
|
||||
if (fs.existsSync(candidate)) {
|
||||
if (isUsableDistPluginSdkArtifact(candidate)) {
|
||||
for (const packageName of PLUGIN_SDK_PACKAGE_NAMES) {
|
||||
aliasMap[`${packageName}/${subpath}`] = candidate;
|
||||
}
|
||||
@@ -482,13 +511,14 @@ function buildPluginLoaderJitiConfigCacheKey(params: {
|
||||
argv1?: string;
|
||||
moduleUrl: string;
|
||||
preferBuiltDist?: boolean;
|
||||
pluginSdkResolution?: PluginSdkResolutionPreference;
|
||||
}) {
|
||||
return [
|
||||
buildPluginLoaderAliasMapCacheKey({
|
||||
modulePath: params.modulePath,
|
||||
argv1: params.argv1,
|
||||
moduleUrl: params.moduleUrl,
|
||||
pluginSdkResolution: "auto",
|
||||
pluginSdkResolution: params.pluginSdkResolution ?? "auto",
|
||||
}),
|
||||
params.preferBuiltDist === true ? "prefer-built-dist" : "default-dist",
|
||||
].join("\0");
|
||||
@@ -647,6 +677,7 @@ export function resolvePluginLoaderJitiConfig(params: {
|
||||
argv1?: string;
|
||||
moduleUrl: string;
|
||||
preferBuiltDist?: boolean;
|
||||
pluginSdkResolution?: PluginSdkResolutionPreference;
|
||||
}): {
|
||||
tryNative: boolean;
|
||||
aliasMap: Record<string, string>;
|
||||
@@ -662,7 +693,12 @@ export function resolvePluginLoaderJitiConfig(params: {
|
||||
params.modulePath,
|
||||
params.preferBuiltDist ? { preferBuiltDist: true } : {},
|
||||
);
|
||||
const aliasMap = buildPluginLoaderAliasMap(params.modulePath, params.argv1, params.moduleUrl);
|
||||
const aliasMap = buildPluginLoaderAliasMap(
|
||||
params.modulePath,
|
||||
params.argv1,
|
||||
params.moduleUrl,
|
||||
params.pluginSdkResolution,
|
||||
);
|
||||
const result = {
|
||||
tryNative,
|
||||
aliasMap,
|
||||
|
||||
Reference in New Issue
Block a user