Move the lifecycle labels out of the lazily loaded monitor page
The overlay is mounted from __root.tsx and imported two label helpers from the page, so the page and its dependency graph were pulled into the eagerly loaded bundle and the route's lazyRouteComponent bought nothing: every route paid for the monitor page even when it was never opened. Measured on a production vite build, the async api-monitor chunk was 0.20 kB, meaning the implementation had landed in the main bundle. The helpers now live in their own module. The same build gives an 18.83 kB api-monitor chunk and a main bundle 18 kB smaller (3.9 kB gzipped).
This commit is contained in:
parent
88bf2eacfb
commit
221b810d52
4 changed files with 66 additions and 35 deletions
|
|
@ -24,7 +24,7 @@ import {
|
|||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { isLifecycleEntry, lifecycleLabel } from "./api-monitor-page";
|
||||
import { isLifecycleEntry, lifecycleLabel } from "./lifecycle";
|
||||
import { useApiMonitorOverlayStore } from "./overlay-store";
|
||||
import { computeStats } from "./use-api-monitor";
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import {
|
|||
import { HugeiconsIcon } from "@hugeicons/react";
|
||||
import { type ReactElement, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { SavedModelSettingsPanel } from "./components/saved-model-settings";
|
||||
import { isLifecycleEntry, lifecycleLabel } from "./lifecycle";
|
||||
import {
|
||||
type MonitorStatusFilter,
|
||||
filterEntries,
|
||||
|
|
@ -86,40 +87,6 @@ function compactEndpoint(endpoint: string): string {
|
|||
.replace(V1_PREFIX_RE, "/");
|
||||
}
|
||||
|
||||
// A lifecycle row is a model load/unload/download, not an HTTP call: it carries
|
||||
// an event and reason instead of a prompt, so there is no payload to expand.
|
||||
export function isLifecycleEntry(entry: ApiMonitorEntry): boolean {
|
||||
return entry.kind === "lifecycle";
|
||||
}
|
||||
|
||||
export function lifecycleLabel(entry: ApiMonitorEntry): string {
|
||||
if (entry.event === "unload") {
|
||||
return entry.reason === "idle" ? "Model unloaded (idle)" : "Model unloaded";
|
||||
}
|
||||
if (entry.event === "download") {
|
||||
if (entry.status === "running") {
|
||||
const pct = entry.progress;
|
||||
return typeof pct === "number"
|
||||
? `Downloading model (${Math.round(pct)}%)`
|
||||
: "Downloading model";
|
||||
}
|
||||
if (entry.status === "completed") {
|
||||
return "Model downloaded";
|
||||
}
|
||||
// A cancel is deliberate, so saying it failed misreads the user's own action.
|
||||
return entry.status === "cancelled"
|
||||
? "Model download cancelled"
|
||||
: "Model download failed";
|
||||
}
|
||||
if (entry.status === "running") {
|
||||
return "Loading model";
|
||||
}
|
||||
if (entry.status === "completed") {
|
||||
return "Model loaded";
|
||||
}
|
||||
return "Model load failed";
|
||||
}
|
||||
|
||||
function statusDotClass(status: ApiMonitorEntry["status"]): string {
|
||||
switch (status) {
|
||||
case "running":
|
||||
|
|
|
|||
47
studio/frontend/src/features/api-monitor/lifecycle.ts
Normal file
47
studio/frontend/src/features/api-monitor/lifecycle.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
// Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
|
||||
|
||||
// Labels for model load/unload/download rows, shared by the overlay and the
|
||||
// full page.
|
||||
//
|
||||
// They live here rather than on the page because the overlay is mounted from
|
||||
// __root.tsx, so importing them from the page would pull the whole page and its
|
||||
// dependency graph into the eagerly loaded bundle and undo the route's
|
||||
// lazyRouteComponent: every route would pay for the monitor page even when it
|
||||
// is never opened.
|
||||
|
||||
import type { ApiMonitorEntry } from "@/features/chat/types/api";
|
||||
|
||||
// A lifecycle row is a model load/unload/download, not an HTTP call: it carries
|
||||
// an event and reason instead of a prompt, so there is no payload to expand.
|
||||
export function isLifecycleEntry(entry: ApiMonitorEntry): boolean {
|
||||
return entry.kind === "lifecycle";
|
||||
}
|
||||
|
||||
export function lifecycleLabel(entry: ApiMonitorEntry): string {
|
||||
if (entry.event === "unload") {
|
||||
return entry.reason === "idle" ? "Model unloaded (idle)" : "Model unloaded";
|
||||
}
|
||||
if (entry.event === "download") {
|
||||
if (entry.status === "running") {
|
||||
const pct = entry.progress;
|
||||
return typeof pct === "number"
|
||||
? `Downloading model (${Math.round(pct)}%)`
|
||||
: "Downloading model";
|
||||
}
|
||||
if (entry.status === "completed") {
|
||||
return "Model downloaded";
|
||||
}
|
||||
// A cancel is deliberate, so saying it failed misreads the user's own action.
|
||||
return entry.status === "cancelled"
|
||||
? "Model download cancelled"
|
||||
: "Model download failed";
|
||||
}
|
||||
if (entry.status === "running") {
|
||||
return "Loading model";
|
||||
}
|
||||
if (entry.status === "completed") {
|
||||
return "Model loaded";
|
||||
}
|
||||
return "Model load failed";
|
||||
}
|
||||
|
|
@ -746,3 +746,20 @@ def test_backfill_includes_a_standalone_gguf_with_no_variant():
|
|||
assert 'entry.modelId.toLowerCase().endsWith(".gguf")' in src
|
||||
# Still excluded for safetensors, which auto-switch does not resolve.
|
||||
assert "entry.ggufVariant != null ||" in src
|
||||
|
||||
|
||||
def test_monitor_overlay_does_not_pull_in_the_lazy_page():
|
||||
"""The overlay is mounted from __root.tsx, so a static import of the page
|
||||
for two label helpers drags the whole 900-line page and its dependency
|
||||
graph into the eagerly loaded bundle and undoes the route's
|
||||
lazyRouteComponent. Measured: the async api-monitor chunk was 0.20 kB with
|
||||
the page in the main bundle, and 18.83 kB after the helpers moved, with the
|
||||
main bundle 18 kB smaller.
|
||||
"""
|
||||
overlay = _read("features/api-monitor/api-monitor-overlay.tsx")
|
||||
assert 'from "./lifecycle"' in overlay
|
||||
assert "api-monitor-page" not in overlay, "the overlay must not reach the page"
|
||||
# The helpers live in their own module, not re-exported through the page.
|
||||
shared = _read("features/api-monitor/lifecycle.ts")
|
||||
assert "export function isLifecycleEntry(" in shared
|
||||
assert "export function lifecycleLabel(" in shared
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue