mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 10:16:44 +00:00
* perf(ui): cut forced reflows in chat render path Profiled the Control UI with Chrome DevTools tracing against a real-data gateway: session-switch INP was 367ms with ForcedReflow insights on every load and interaction trace. - chat-thread: per-row stable Lit ref callbacks (keyed by row key) so the virtualizer stops cache-sweeping and re-measuring every visible row on every render; prune callbacks when rows leave the list - chat-composer: stable textarea ref on per-pane state instead of an inline arrow, so the textarea is re-measured only on attach or when the draft changes programmatically, not on every chat render - app-sidebar: coalesce scrollHeight/scrollTop reads from updated() into one rAF per frame instead of a forced layout flush per render After: INP 133-143ms on the same interaction sequence, no ForcedReflow insight in load or interaction traces. * perf(ui): keep Control UI startup under budget after reflow fixes The reflow fixes shifted rolldown's chunk partition: the 400 KiB core maxSize boundary split one core chunk in two (~1.4 KiB gzip compression loss) and re-balancing minted a tiny build-info startup chunk, pushing startup JS to 370.8 KiB over the 370 KiB budget. - pin build-info.ts + build-info-normalizers.ts into control-ui-shared so partition noise stops minting extra startup preload requests - raise core maxSize 400 -> 448 KiB so the core graph packs into fewer, better-compressing chunks Startup JS: 22 requests, 369.1 KiB gzip (main: 23 requests, 369.3 KiB).
88 lines
2.7 KiB
TypeScript
88 lines
2.7 KiB
TypeScript
// Control UI config module wires control ui chunking behavior.
|
|
function normalizeModuleId(id: string): string {
|
|
return id.replace(/\\/g, "/");
|
|
}
|
|
|
|
function moduleIdIncludesPackage(id: string, packageName: string): boolean {
|
|
const normalized = normalizeModuleId(id);
|
|
return (
|
|
normalized.includes(`/node_modules/${packageName}/`) ||
|
|
normalized.includes(`/openclaw-pnpm-node-modules/${packageName}/`)
|
|
);
|
|
}
|
|
|
|
export function controlUiStableChunkName(id: string): string | undefined {
|
|
const normalized = normalizeModuleId(id);
|
|
|
|
// These entry-and-route helpers must stay together; separate shared chunks
|
|
// turn small route-graph changes into extra startup preload requests.
|
|
if (
|
|
normalized.endsWith("/ui/src/components/config-form.shared.ts") ||
|
|
normalized.endsWith("/ui/src/lib/clipboard.ts") ||
|
|
normalized.endsWith("/ui/src/build-info-normalizers.ts") ||
|
|
normalized.endsWith("/ui/src/build-info.ts")
|
|
) {
|
|
return "control-ui-shared";
|
|
}
|
|
|
|
if (normalized.endsWith("/ui/src/lib/gateway-methods.ts")) {
|
|
return "gateway-runtime";
|
|
}
|
|
|
|
if (
|
|
moduleIdIncludesPackage(id, "lit") ||
|
|
moduleIdIncludesPackage(id, "lit-html") ||
|
|
moduleIdIncludesPackage(id, "@lit/reactive-element")
|
|
) {
|
|
return "lit-runtime";
|
|
}
|
|
|
|
if (
|
|
moduleIdIncludesPackage(id, "highlight.js") ||
|
|
moduleIdIncludesPackage(id, "markdown-it") ||
|
|
moduleIdIncludesPackage(id, "markdown-it-task-lists") ||
|
|
moduleIdIncludesPackage(id, "dompurify") ||
|
|
moduleIdIncludesPackage(id, "entities") ||
|
|
moduleIdIncludesPackage(id, "linkify-it") ||
|
|
moduleIdIncludesPackage(id, "mdurl") ||
|
|
moduleIdIncludesPackage(id, "punycode.js") ||
|
|
moduleIdIncludesPackage(id, "uc.micro")
|
|
) {
|
|
return "markdown-runtime";
|
|
}
|
|
|
|
if (moduleIdIncludesPackage(id, "zod") || moduleIdIncludesPackage(id, "json5")) {
|
|
return "config-runtime";
|
|
}
|
|
|
|
if (
|
|
moduleIdIncludesPackage(id, "@noble/ed25519") ||
|
|
moduleIdIncludesPackage(id, "@noble/hashes") ||
|
|
moduleIdIncludesPackage(id, "ipaddr.js")
|
|
) {
|
|
return "gateway-runtime";
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
export const controlUiCodeSplitting = {
|
|
includeDependenciesRecursively: false,
|
|
groups: [
|
|
{
|
|
name: (id: string) => controlUiStableChunkName(id) ?? null,
|
|
test: (id: string) => controlUiStableChunkName(id) !== undefined,
|
|
priority: 20,
|
|
},
|
|
{
|
|
name: (id: string) =>
|
|
normalizeModuleId(id).includes("/ui/src/") ? "control-ui-core" : "control-ui-foundation",
|
|
tags: ["$initial"] as ["$initial"],
|
|
priority: 10,
|
|
// 448 KiB packs the core graph into fewer chunks; the previous 400 KiB
|
|
// boundary split one core chunk in two, costing ~1.4 KiB startup gzip.
|
|
maxSize: 448 * 1024,
|
|
},
|
|
],
|
|
};
|