Skip to content

Commit b35565b

Browse files
committed
feat(performance): add performance overview and component details
- Introduced ComponentCard for displaying individual component performance metrics. - Added HookDetailsPanel to show detailed hook performance data. - Created PerformanceOverview to summarize overall performance metrics. - Implemented StatCard for displaying individual statistics in a card format. - Added utility function formatMs for formatting milliseconds into human-readable strings. - Enhanced RenderTree with new components for better state and code visualization. - Introduced filtering capabilities for hooks in the RenderTree. - Created utility functions for determining code language and filtering hook trees. - Refactored existing components to improve code organization and readability.
1 parent 97d2dbd commit b35565b

61 files changed

Lines changed: 2356 additions & 1231 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
File renamed without changes.
File renamed without changes.

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,6 @@ Thumbs.db
6666
.vite-inspect
6767
.pnpm-store/*
6868
qwik/*
69-
.cursor/skills/*
69+
.cursor/skills/*
70+
**/build-analysis/**/*
71+
related-folder/**

packages/kit/src/client.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1-
import SuperJSON from 'superjson';
21
import { ClientFunctions, ServerFunctions } from './types';
3-
import { createBirpc } from 'birpc';
42
import { DEVTOOLS_VITE_MESSAGING_EVENT } from './constants';
53
import { getViteClientContext, setViteClientRpc } from './context';
4+
import { createSerializedRpc } from './rpc-core';
65

76
export function createClientRpc(functions: ClientFunctions) {
87
const client = getViteClientContext();
98

10-
const rpc = createBirpc<ServerFunctions, ClientFunctions>(functions, {
11-
post: (data) =>
12-
client.send(DEVTOOLS_VITE_MESSAGING_EVENT, SuperJSON.stringify(data)),
13-
on: (fn) =>
9+
const rpc = createSerializedRpc<ServerFunctions, ClientFunctions>(functions, {
10+
post: (data) => client.send(DEVTOOLS_VITE_MESSAGING_EVENT, data),
11+
on: (handler) =>
1412
client.on(DEVTOOLS_VITE_MESSAGING_EVENT, (data) => {
15-
fn(SuperJSON.parse(data));
13+
handler(data);
1614
}),
17-
timeout: 120_000,
1815
});
1916

2017
setViteClientRpc(rpc);

packages/kit/src/constants.ts

Lines changed: 40 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,42 @@
11
export const DEVTOOLS_VITE_MESSAGING_EVENT = 'qwik_tools:vite_messaging_event';
2-
export const USE_HOOK_LIST = [
3-
'useAsyncComputed',
4-
'useComputed',
5-
'useConstant',
6-
'useContext',
7-
'useContextProvider',
8-
'useErrorBoundary',
9-
'useId',
10-
'useOn',
11-
'useOnDocument',
12-
'useOnWindow',
13-
'useResource',
14-
'useSerializer',
15-
'useServerData',
16-
'useSignal',
17-
'useStore',
18-
'useStyles',
19-
'useStylesScoped',
20-
'useTask',
21-
'useVisibleTask',
22-
'useLocation',
23-
'useNavigate',
24-
'usePreventNavigate',
25-
'useContent',
26-
'useDocumentHead',
27-
] as const
28-
29-
30-
export const VARIABLE_DECLARATION_LIST = [
31-
'useStore',
32-
'useSignal',
33-
'useComputed',
34-
'useAsyncComputed',
35-
'useContext',
36-
'useId',
37-
'useStyles',
38-
'useStylesScoped',
39-
'useConstant',
40-
'useErrorBoundary',
41-
'useSerializer',
42-
'useServerData',
43-
'useLocation',
44-
'useNavigate',
45-
'useContent',
46-
'useDocumentHead',
47-
] as const
482

49-
50-
export const EXPRESSION_STATEMENT_LIST = [
51-
'useVisibleTask',
52-
'useTask',
53-
'useResource',
54-
'useContextProvider',
55-
'usePreventNavigate',
56-
] as const
3+
const HOOK_GROUPS = {
4+
variableDeclaration: [
5+
'useStore',
6+
'useSignal',
7+
'useComputed',
8+
'useAsyncComputed',
9+
'useContext',
10+
'useId',
11+
'useStyles',
12+
'useStylesScoped',
13+
'useConstant',
14+
'useErrorBoundary',
15+
'useSerializer',
16+
'useServerData',
17+
'useLocation',
18+
'useNavigate',
19+
'useContent',
20+
'useDocumentHead',
21+
] as const,
22+
expressionStatement: [
23+
'useVisibleTask',
24+
'useTask',
25+
'useResource',
26+
'useContextProvider',
27+
'usePreventNavigate',
28+
] as const,
29+
listener: ['useOn', 'useOnDocument', 'useOnWindow'] as const,
30+
noReturn: ['useVisibleTask', 'useTask'] as const,
31+
} as const;
32+
33+
export const VARIABLE_DECLARATION_LIST = HOOK_GROUPS.variableDeclaration;
34+
export const EXPRESSION_STATEMENT_LIST = HOOK_GROUPS.expressionStatement;
35+
export const USE_HOOK_LIST = [
36+
...VARIABLE_DECLARATION_LIST,
37+
...HOOK_GROUPS.listener,
38+
...EXPRESSION_STATEMENT_LIST,
39+
] as const;
5740

5841
export const QSEQ = 'q:seq';
5942
export const QPROPS = 'q:props';
@@ -62,13 +45,13 @@ export const QTYPE = 'q:type';
6245

6346
export const VIRTUAL_QWIK_DEVTOOLS_KEY = 'virtual-qwik-devtools.ts';
6447

65-
export const INNER_USE_HOOK= 'useCollectHooks'
48+
export const INNER_USE_HOOK = 'useCollectHooks';
6649

67-
export const QWIK_DEVTOOLS_GLOBAL_STATE = 'QWIK_DEVTOOLS_GLOBAL_STATE'
50+
export const QWIK_DEVTOOLS_GLOBAL_STATE = 'QWIK_DEVTOOLS_GLOBAL_STATE';
6851

6952
export const QRL_KEY = '$qrl$';
7053
export const COMPUTED_QRL_KEY = '$computeQrl$';
7154
export const CHUNK_KEY = '$chunk$';
7255
export const CAPTURE_REF_KEY = '$captureRef$';
7356

74-
export const NORETURN_HOOK = [ 'useVisibleTask', 'useTask'] as const
57+
export const NORETURN_HOOK = HOOK_GROUPS.noReturn;

packages/kit/src/context.ts

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { target } from './shared';
21
import {
32
ViteClientContext,
43
CLIENT_CTX,
@@ -8,38 +7,23 @@ import {
87
CLIENT_RPC,
98
} from './globals';
109
import { ServerRpc, ClientRpc } from './types';
10+
import { createGlobalAccessor } from './global-store';
1111

12-
type GlobalTarget = Record<string, unknown>;
13-
const t = target as unknown as GlobalTarget;
12+
const clientContextAccessor =
13+
createGlobalAccessor<ViteClientContext>(CLIENT_CTX);
14+
const serverContextAccessor =
15+
createGlobalAccessor<ViteServerContext>(SERVER_CTX);
16+
const serverRpcAccessor = createGlobalAccessor<ServerRpc>(SERVER_RPC);
17+
const clientRpcAccessor = createGlobalAccessor<ClientRpc>(CLIENT_RPC);
1418

15-
export function getViteClientContext(): ViteClientContext {
16-
return t[CLIENT_CTX] as ViteClientContext;
17-
}
19+
export const getViteClientContext = clientContextAccessor.get;
20+
export const setViteClientContext = clientContextAccessor.set;
1821

19-
export function setViteClientContext(ctx: ViteClientContext) {
20-
t[CLIENT_CTX] = ctx;
21-
}
22+
export const getViteServerContext = serverContextAccessor.get;
23+
export const setViteServerContext = serverContextAccessor.set;
2224

23-
export function getViteServerContext() {
24-
return t[SERVER_CTX] as ViteServerContext;
25-
}
25+
export const getViteServerRpc = serverRpcAccessor.get;
26+
export const setViteServerRpc = serverRpcAccessor.set;
2627

27-
export function setViteServerContext(ctx: ViteServerContext) {
28-
t[SERVER_CTX] = ctx;
29-
}
30-
31-
export function getViteServerRpc() {
32-
return t[SERVER_RPC] as ServerRpc;
33-
}
34-
35-
export function setViteServerRpc(rpc: ServerRpc) {
36-
t[SERVER_RPC] = rpc;
37-
}
38-
39-
export function getViteClientRpc() {
40-
return t[CLIENT_RPC] as ClientRpc;
41-
}
42-
43-
export function setViteClientRpc(rpc: ClientRpc) {
44-
t[CLIENT_RPC] = rpc;
45-
}
28+
export const getViteClientRpc = clientRpcAccessor.get;
29+
export const setViteClientRpc = clientRpcAccessor.set;

packages/kit/src/global-store.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { target } from './shared';
2+
3+
type GlobalStore = Record<string, unknown>;
4+
5+
const globalStore = target as unknown as GlobalStore;
6+
7+
export function createGlobalAccessor<T>(key: string) {
8+
return {
9+
get: () => globalStore[key] as T,
10+
set: (value: T) => {
11+
globalStore[key] = value;
12+
},
13+
};
14+
}

packages/kit/src/rpc-core.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import SuperJSON from 'superjson';
2+
import { createBirpc } from 'birpc';
3+
4+
interface RpcChannel {
5+
post: (serialized: string) => void;
6+
on: (handler: (serialized: string) => void) => void;
7+
}
8+
9+
const RPC_TIMEOUT = 120_000;
10+
11+
function parseRpcPayload(payload: unknown) {
12+
return SuperJSON.parse(String(payload));
13+
}
14+
15+
export function createSerializedRpc<
16+
RemoteFunctions extends object,
17+
LocalFunctions extends object,
18+
>(functions: LocalFunctions, channel: RpcChannel) {
19+
return createBirpc<RemoteFunctions, LocalFunctions>(functions, {
20+
post: (data) => channel.post(SuperJSON.stringify(data)),
21+
on: (handler) => channel.on((data) => handler(parseRpcPayload(data))),
22+
timeout: RPC_TIMEOUT,
23+
});
24+
}

packages/kit/src/server.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1-
import SuperJSON from 'superjson';
21
import { ClientFunctions, ServerFunctions } from './types';
3-
import { createBirpc } from 'birpc';
42
import { DEVTOOLS_VITE_MESSAGING_EVENT } from './constants';
53
import { setViteServerRpc, getViteServerContext } from './context';
4+
import { createSerializedRpc } from './rpc-core';
65

76
export function createServerRpc(functions: ServerFunctions) {
87
const server = getViteServerContext();
98

10-
const rpc = createBirpc<ClientFunctions, ServerFunctions>(functions, {
11-
post: (data) =>
12-
server.ws.send(DEVTOOLS_VITE_MESSAGING_EVENT, SuperJSON.stringify(data)),
13-
on: (fn) =>
9+
const rpc = createSerializedRpc<ClientFunctions, ServerFunctions>(functions, {
10+
post: (data) => server.ws.send(DEVTOOLS_VITE_MESSAGING_EVENT, data),
11+
on: (handler) =>
1412
server.ws.on(DEVTOOLS_VITE_MESSAGING_EVENT, (data: any) => {
15-
fn(SuperJSON.parse(data));
13+
handler(data);
1614
}),
17-
timeout: 120_000,
1815
});
1916

2017
setViteServerRpc(rpc);

packages/kit/src/types.ts

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,68 @@
11
import { BirpcReturn } from 'birpc';
22
import { type Dree } from 'dree';
3-
import { VARIABLE_DECLARATION_LIST, EXPRESSION_STATEMENT_LIST } from './constants';
3+
import {
4+
VARIABLE_DECLARATION_LIST,
5+
EXPRESSION_STATEMENT_LIST,
6+
} from './constants';
7+
48
export { Type as RouteType } from 'dree';
59

610
export interface ClientFunctions {
711
healthCheck(): boolean;
812
}
913

14+
export interface DependenciesStatus {
15+
phase: 'idle' | 'phase1' | 'phase2' | 'done' | 'error';
16+
loaded: number;
17+
total: number;
18+
startedAt: number | null;
19+
finishedAt: number | null;
20+
error?: string;
21+
}
22+
23+
export interface PackageInstallResult {
24+
success: boolean;
25+
error?: string;
26+
}
27+
28+
export interface BuildAnalysisStatus {
29+
exists: boolean;
30+
reportPath: string;
31+
buildCommand: string | null;
32+
}
33+
34+
export interface BuildAnalysisRunResult {
35+
success: boolean;
36+
error?: string;
37+
}
38+
39+
export interface ModuleLookupResult {
40+
pathId: string;
41+
modules: any;
42+
error?: string;
43+
}
44+
45+
export type ParsedQwikCodeResult = Omit<ParsedStructure, '__start__'>[];
46+
1047
export interface ServerFunctions {
1148
healthCheck(): boolean;
1249
getAssetsFromPublicDir: () => Promise<AssetInfo[]>;
1350
getComponents: () => Promise<Component[]>;
1451
getRoutes: () => any;
1552
getQwikPackages: () => Promise<[string, string][]>;
1653
getAllDependencies: () => Promise<any[]>;
17-
getDependenciesStatus: () => Promise<{
18-
phase: 'idle' | 'phase1' | 'phase2' | 'done' | 'error';
19-
loaded: number;
20-
total: number;
21-
startedAt: number | null;
22-
finishedAt: number | null;
23-
error?: string;
24-
}>;
54+
getDependenciesStatus: () => Promise<DependenciesStatus>;
2555
refreshDependencies: () => Promise<void>;
2656
installPackage: (
2757
packageName: string,
2858
isDev?: boolean,
29-
) => Promise<{ success: boolean; error?: string }>;
30-
getModulesByPathIds: (pathIds: string | string[]) => Promise<{
31-
pathId: string;
32-
modules: any;
33-
error?: string;
34-
}[]>;
35-
parseQwikCode: (code: string) => Promise<Omit<ParsedStructure, '__start__'>[]>;
59+
) => Promise<PackageInstallResult>;
60+
getBuildAnalysisStatus: () => Promise<BuildAnalysisStatus>;
61+
buildBuildAnalysisReport: () => Promise<BuildAnalysisRunResult>;
62+
getModulesByPathIds: (
63+
pathIds: string | string[],
64+
) => Promise<ModuleLookupResult[]>;
65+
parseQwikCode: (code: string) => Promise<ParsedQwikCodeResult>;
3666
}
3767

3868
export type ServerRpc = BirpcReturn<ClientFunctions, ServerFunctions>;
@@ -75,17 +105,19 @@ export interface Component {
75105
file: string;
76106
}
77107

78-
export type Category = 'variableDeclaration' | 'expressionStatement' | 'listener'
108+
export type Category =
109+
| 'variableDeclaration'
110+
| 'expressionStatement'
111+
| 'listener';
79112
export type HookType =
80113
| (typeof VARIABLE_DECLARATION_LIST)[number]
81114
| (typeof EXPRESSION_STATEMENT_LIST)[number]
82-
| 'customhook'
115+
| 'customhook';
83116

84117
export interface ParsedStructure {
85-
variableName: string
86-
hookType: HookType
87-
category: Category
88-
__start__?: number
89-
data?: any
118+
variableName: string;
119+
hookType: HookType;
120+
category: Category;
121+
__start__?: number;
122+
data?: any;
90123
}
91-

0 commit comments

Comments
 (0)