Skip to content
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
File renamed without changes.
File renamed without changes.
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