Skip to content
This repository was archived by the owner on May 7, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/huge-clubs-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@qwik.dev/devtools': patch
---

chore: update .gitignore, pnpm-lock.yaml, and add Qwik development documentation

- Updated .gitignore to include new patterns for cursor skills and Qwik devtools.
- Modified pnpm-lock.yaml to add new dependencies including rollup-plugin-visualizer and define-lazy-prop.
- Introduced AGENTS.md and SKILL.md for Qwik core development guidelines, detailing architecture, best practices, and mandatory workflows.
Comment thread
JerryWu1234 marked this conversation as resolved.
Outdated
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,7 @@ testem.log
Thumbs.db
.vite-inspect
.pnpm-store/*
related-qwik/*
.cursor/skills/*
qwik/*
.cursor/skills/*
related-folder/**
**/.qwik-devtools/
13 changes: 5 additions & 8 deletions packages/kit/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import SuperJSON from 'superjson';
import { ClientFunctions, ServerFunctions } from './types';
import { createBirpc } from 'birpc';
import { DEVTOOLS_VITE_MESSAGING_EVENT } from './constants';
import { getViteClientContext, setViteClientRpc } from './context';
import { createSerializedRpc } from './rpc-core';

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

const rpc = createBirpc<ServerFunctions, ClientFunctions>(functions, {
post: (data) =>
client.send(DEVTOOLS_VITE_MESSAGING_EVENT, SuperJSON.stringify(data)),
on: (fn) =>
const rpc = createSerializedRpc<ServerFunctions, ClientFunctions>(functions, {
post: (data) => client.send(DEVTOOLS_VITE_MESSAGING_EVENT, data),
on: (handler) =>
client.on(DEVTOOLS_VITE_MESSAGING_EVENT, (data) => {
fn(SuperJSON.parse(data));
handler(data);
}),
timeout: 120_000,
});

setViteClientRpc(rpc);
Expand Down
98 changes: 41 additions & 57 deletions packages/kit/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,59 +1,42 @@
export const DEVTOOLS_VITE_MESSAGING_EVENT = 'qwik_tools:vite_messaging_event';
export const USE_HOOK_LIST = [
'useAsyncComputed',
'useComputed',
'useConstant',
'useContext',
'useContextProvider',
'useErrorBoundary',
'useId',
'useOn',
'useOnDocument',
'useOnWindow',
'useResource',
'useSerializer',
'useServerData',
'useSignal',
'useStore',
'useStyles',
'useStylesScoped',
'useTask',
'useVisibleTask',
'useLocation',
'useNavigate',
'usePreventNavigate',
'useContent',
'useDocumentHead',
] as const


export const VARIABLE_DECLARATION_LIST = [
'useStore',
'useSignal',
'useComputed',
'useAsyncComputed',
'useContext',
'useId',
'useStyles',
'useStylesScoped',
'useConstant',
'useErrorBoundary',
'useSerializer',
'useServerData',
'useLocation',
'useNavigate',
'useContent',
'useDocumentHead',
] as const


export const EXPRESSION_STATEMENT_LIST = [
'useVisibleTask',
'useTask',
'useResource',
'useContextProvider',
'usePreventNavigate',
] as const
const HOOK_GROUPS = {
variableDeclaration: [
'useStore',
'useSignal',
'useComputed',
'useAsyncComputed',
'useContext',
'useId',
'useStyles',
'useStylesScoped',
'useConstant',
'useErrorBoundary',
'useSerializer',
'useServerData',
'useLocation',
'useNavigate',
'useContent',
'useDocumentHead',
] as const,
expressionStatement: [
'useVisibleTask',
'useTask',
'useResource',
'useContextProvider',
'usePreventNavigate',
] as const,
listener: ['useOn', 'useOnDocument', 'useOnWindow'] as const,
noReturn: ['useVisibleTask', 'useTask'] as const,
} as const;

export const VARIABLE_DECLARATION_LIST = HOOK_GROUPS.variableDeclaration;
export const EXPRESSION_STATEMENT_LIST = HOOK_GROUPS.expressionStatement;
export const USE_HOOK_LIST = [
...VARIABLE_DECLARATION_LIST,
...HOOK_GROUPS.listener,
...EXPRESSION_STATEMENT_LIST,
] as const;

export const QSEQ = 'q:seq';
export const QPROPS = 'q:props';
Expand All @@ -62,13 +45,14 @@ export const QTYPE = 'q:type';

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

export const INNER_USE_HOOK= 'useCollectHooks'
export const INNER_USE_HOOK = 'useCollectHooks';

export const QWIK_DEVTOOLS_GLOBAL_STATE = 'QWIK_DEVTOOLS_GLOBAL_STATE'
export const QWIK_DEVTOOLS_GLOBAL_STATE = 'QWIK_DEVTOOLS_GLOBAL_STATE';
export const QWIK_PRELOADS_UPDATE_EVENT = 'qwik:preloads-update';

export const QRL_KEY = '$qrl$';
export const COMPUTED_QRL_KEY = '$computeQrl$';
export const CHUNK_KEY = '$chunk$';
export const CAPTURE_REF_KEY = '$captureRef$';

export const NORETURN_HOOK = [ 'useVisibleTask', 'useTask'] as const
export const NORETURN_HOOK = HOOK_GROUPS.noReturn;
46 changes: 15 additions & 31 deletions packages/kit/src/context.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { target } from './shared';
import {
ViteClientContext,
CLIENT_CTX,
Expand All @@ -8,38 +7,23 @@ import {
CLIENT_RPC,
} from './globals';
import { ServerRpc, ClientRpc } from './types';
import { createGlobalAccessor } from './global-store';

type GlobalTarget = Record<string, unknown>;
const t = target as unknown as GlobalTarget;
const clientContextAccessor =
createGlobalAccessor<ViteClientContext>(CLIENT_CTX);
const serverContextAccessor =
createGlobalAccessor<ViteServerContext>(SERVER_CTX);
const serverRpcAccessor = createGlobalAccessor<ServerRpc>(SERVER_RPC);
const clientRpcAccessor = createGlobalAccessor<ClientRpc>(CLIENT_RPC);

export function getViteClientContext(): ViteClientContext {
return t[CLIENT_CTX] as ViteClientContext;
}
export const getViteClientContext = clientContextAccessor.get;
export const setViteClientContext = clientContextAccessor.set;

export function setViteClientContext(ctx: ViteClientContext) {
t[CLIENT_CTX] = ctx;
}
export const getViteServerContext = serverContextAccessor.get;
export const setViteServerContext = serverContextAccessor.set;

export function getViteServerContext() {
return t[SERVER_CTX] as ViteServerContext;
}
export const getViteServerRpc = serverRpcAccessor.get;
export const setViteServerRpc = serverRpcAccessor.set;

export function setViteServerContext(ctx: ViteServerContext) {
t[SERVER_CTX] = ctx;
}

export function getViteServerRpc() {
return t[SERVER_RPC] as ServerRpc;
}

export function setViteServerRpc(rpc: ServerRpc) {
t[SERVER_RPC] = rpc;
}

export function getViteClientRpc() {
return t[CLIENT_RPC] as ClientRpc;
}

export function setViteClientRpc(rpc: ClientRpc) {
t[CLIENT_RPC] = rpc;
}
export const getViteClientRpc = clientRpcAccessor.get;
export const setViteClientRpc = clientRpcAccessor.set;
14 changes: 14 additions & 0 deletions packages/kit/src/global-store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { target } from './shared';

type GlobalStore = Record<string, unknown>;

const globalStore = target as unknown as GlobalStore;

export function createGlobalAccessor<T>(key: string) {
return {
get: () => globalStore[key] as T,
set: (value: T) => {
globalStore[key] = value;
},
};
}
79 changes: 79 additions & 0 deletions packages/kit/src/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,82 @@ export interface QwikPerfStoreRemembered {

}

export type QwikPreloadStatus = 'pending' | 'loaded' | 'error' | 'unknown';
export type QwikPreloadSource =
| 'initial-dom'
| 'mutation'
| 'performance'
| 'qrl-correlation';
export type QwikPreloadOriginKind =
| 'current-project'
| 'vite-plugin-injected'
| 'node_modules'
| 'virtual-module'
| 'generated'
| 'external'
| 'unknown';
export type QwikPreloadPhase = 'csr' | 'ssr' | 'unknown';
export type QwikPreloadMatchMode =
| 'href'
| 'normalized-href'
| 'chunk-hash'
| 'resource-name'
| 'none';
export type QwikPreloadLoadMatchQuality = 'best-effort' | 'none';

export interface QwikPreloadQrlRequestRemembered {
symbol: string;
href?: string;
normalizedHref?: string;
requestedAt: number;
originKind?: QwikPreloadOriginKind;
phase?: QwikPreloadPhase;
matchedEntryId?: number;
}

export interface QwikPreloadEntryRemembered {
id: number;
href: string;
normalizedHref: string;
rel: string;
as: string;
resourceType: string;
status: QwikPreloadStatus;
source: QwikPreloadSource;
originKind: QwikPreloadOriginKind;
phase: QwikPreloadPhase;
discoveredAt: number;
requestedAt?: number;
completedAt?: number;
importDuration?: number;
loadDuration?: number;
duration?: number;
transferSize?: number;
decodedBodySize?: number;
initiatorType?: string;
qrlSymbol?: string;
qrlRequestedAt?: number;
qrlToLoadDuration?: number;
loadMatchQuality?: QwikPreloadLoadMatchQuality;
matchedBy: QwikPreloadMatchMode;
error?: string;
}

export type QwikSsrPreloadSnapshotRemembered =
Partial<QwikPreloadEntryRemembered> &
Pick<QwikPreloadEntryRemembered, 'href'>;

export interface QwikPreloadStoreRemembered {
entries: QwikPreloadEntryRemembered[];
qrlRequests: QwikPreloadQrlRequestRemembered[];
startedAt: number;
clear: () => void;
_id: number;
_initialized: boolean;
_byHref: Record<string, number>;
_byId: Record<number, QwikPreloadEntryRemembered>;
}

export interface DevtoolsRenderStats {
/**
* In-memory performance store written by devtools instrumentation.
Expand All @@ -67,6 +143,8 @@ declare global {
* Written by `@devtools/plugin` instrumentation.
*/
__QWIK_PERF__?: QwikPerfStoreRemembered;
__QWIK_PRELOADS__?: QwikPreloadStoreRemembered;
__QWIK_SSR_PRELOADS__?: QwikSsrPreloadSnapshotRemembered[];
}
}

Expand All @@ -76,6 +154,7 @@ declare global {
namespace NodeJS {
interface Process {
__QWIK_SSR_PERF__?: QwikPerfEntryRemembered[];
__QWIK_SSR_PRELOADS__?: QwikSsrPreloadSnapshotRemembered[];
__QWIK_SSR_PERF_SET__?: Set<string>;
__QWIK_SSR_PERF_ID__?: number;
__QWIK_SSR_PERF_INDEX__?: Record<string, number>;
Expand Down
24 changes: 24 additions & 0 deletions packages/kit/src/rpc-core.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import SuperJSON from 'superjson';
import { createBirpc } from 'birpc';

interface RpcChannel {
post: (serialized: string) => void;
on: (handler: (serialized: string) => void) => void;
}

const RPC_TIMEOUT = 120_000;

function parseRpcPayload(payload: unknown) {
return SuperJSON.parse(String(payload));
}

export function createSerializedRpc<
RemoteFunctions extends object,
LocalFunctions extends object,
>(functions: LocalFunctions, channel: RpcChannel) {
return createBirpc<RemoteFunctions, LocalFunctions>(functions, {
post: (data) => channel.post(SuperJSON.stringify(data)),
on: (handler) => channel.on((data) => handler(parseRpcPayload(data))),
timeout: RPC_TIMEOUT,
});
}
13 changes: 5 additions & 8 deletions packages/kit/src/server.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import SuperJSON from 'superjson';
import { ClientFunctions, ServerFunctions } from './types';
import { createBirpc } from 'birpc';
import { DEVTOOLS_VITE_MESSAGING_EVENT } from './constants';
import { setViteServerRpc, getViteServerContext } from './context';
import { createSerializedRpc } from './rpc-core';

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

const rpc = createBirpc<ClientFunctions, ServerFunctions>(functions, {
post: (data) =>
server.ws.send(DEVTOOLS_VITE_MESSAGING_EVENT, SuperJSON.stringify(data)),
on: (fn) =>
const rpc = createSerializedRpc<ClientFunctions, ServerFunctions>(functions, {
post: (data) => server.ws.send(DEVTOOLS_VITE_MESSAGING_EVENT, data),
on: (handler) =>
server.ws.on(DEVTOOLS_VITE_MESSAGING_EVENT, (data: any) => {
fn(SuperJSON.parse(data));
handler(data);
}),
timeout: 120_000,
});

setViteServerRpc(rpc);
Expand Down
Loading
Loading