Skip to content

Commit c9eaa78

Browse files
committed
chore(optimizer): move dev qrl mapping to plugin
we don't have a qrl mapping in dev because there's no manifest, so instead we make parseable qrl segment filenames
1 parent b1330cb commit c9eaa78

File tree

9 files changed

+68
-98
lines changed

9 files changed

+68
-98
lines changed

.changeset/all-cloths-hammer.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik.dev/core': minor
3+
---
4+
5+
FEAT: the QRL segment mapping during Vite dev mode now happens in core and does not require providing a separate `symbolMapper` function any more.

packages/docs/src/routes/api/qwik-optimizer/api.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -754,8 +754,8 @@
754754
}
755755
],
756756
"kind": "Variable",
757-
"content": "> This API is provided as a beta preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.\n> \n\nFor a given symbol (QRL such as `onKeydown$`<!-- -->) the server needs to know which bundle the symbol is in.\n\nNormally this is provided by Qwik's `q-manifest` . But `q-manifest` only exists after a full client build.\n\nThis would be a problem in dev mode. So in dev mode the symbol is mapped to the expected URL using the symbolMapper function below. For Vite the given path is fixed for a given symbol.\n\n\n```typescript\nsymbolMapper: ReturnType<typeof createSymbolMapper>\n```",
758-
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/plugins/vite-dev-server.ts",
757+
"content": "> This API is provided as an alpha preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.\n> \n\n> Warning: This API is now obsolete.\n> \n> No longer needed, it is automatic now\n> \n\n\n```typescript\nsymbolMapper: undefined\n```",
758+
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/index.ts",
759759
"mdFile": "core.symbolmapper.md"
760760
},
761761
{
@@ -768,7 +768,7 @@
768768
}
769769
],
770770
"kind": "TypeAlias",
771-
"content": "> This API is provided as a beta preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.\n> \n\nFor a given symbol (QRL such as `onKeydown$`<!-- -->) the server needs to know which bundle the symbol is in.\n\nNormally this is provided by Qwik's `q-manifest` . But `q-manifest` only exists after a full client build.\n\nThis would be a problem in dev mode. So in dev mode the symbol is mapped to the expected URL using the symbolMapper function below. For Vite the given path is fixed for a given symbol.\n\n\n```typescript\nsymbolMapper: ReturnType<typeof createSymbolMapper>\n```",
771+
"content": "> This API is provided as an alpha preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.\n> \n\n> Warning: This API is now obsolete.\n> \n> No longer needed, it is automatic now\n> \n\n\n```typescript\nsymbolMapper: undefined\n```",
772772
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/types.ts",
773773
"mdFile": "core.symbolmapper.md"
774774
},

packages/docs/src/routes/api/qwik-optimizer/index.mdx

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3090,32 +3090,28 @@ export type SourceMapsOption = "external" | "inline" | undefined | null;
30903090

30913091
## symbolMapper
30923092

3093-
> This API is provided as a beta preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
3093+
> This API is provided as an alpha preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
30943094

3095-
For a given symbol (QRL such as `onKeydown$`) the server needs to know which bundle the symbol is in.
3096-
3097-
Normally this is provided by Qwik's `q-manifest` . But `q-manifest` only exists after a full client build.
3098-
3099-
This would be a problem in dev mode. So in dev mode the symbol is mapped to the expected URL using the symbolMapper function below. For Vite the given path is fixed for a given symbol.
3095+
> Warning: This API is now obsolete.
3096+
>
3097+
> No longer needed, it is automatic now
31003098

31013099
```typescript
3102-
symbolMapper: ReturnType<typeof createSymbolMapper>;
3100+
symbolMapper: undefined;
31033101
```
31043102

3105-
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/plugins/vite-dev-server.ts)
3103+
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/index.ts)
31063104

31073105
## SymbolMapper
31083106

3109-
> This API is provided as a beta preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
3110-
3111-
For a given symbol (QRL such as `onKeydown$`) the server needs to know which bundle the symbol is in.
3112-
3113-
Normally this is provided by Qwik's `q-manifest` . But `q-manifest` only exists after a full client build.
3107+
> This API is provided as an alpha preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
31143108

3115-
This would be a problem in dev mode. So in dev mode the symbol is mapped to the expected URL using the symbolMapper function below. For Vite the given path is fixed for a given symbol.
3109+
> Warning: This API is now obsolete.
3110+
>
3111+
> No longer needed, it is automatic now
31163112

31173113
```typescript
3118-
symbolMapper: ReturnType<typeof createSymbolMapper>;
3114+
symbolMapper: undefined;
31193115
```
31203116

31213117
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/types.ts)

packages/qwik-router/src/buildtime/vite/plugin.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ function qwikRouterPlugin(userOpts?: QwikRouterVitePluginOptions): any {
151151
},
152152

153153
configureServer(server) {
154+
// this callback is run after the vite middlewares are registered
154155
return () => {
155156
if (!ctx) {
156157
throw new Error('configureServer: Missing ctx from configResolved');

packages/qwik/src/optimizer/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,5 @@ export type { BundleGraphAdder } from './plugins/bundle-graph';
5252

5353
export { qwikRollup } from './plugins/rollup';
5454
export { qwikVite } from './plugins/vite';
55-
export { symbolMapper } from './plugins/vite-dev-server';
55+
/** @alpha @deprecated No longer needed, it is automatic now */
56+
export const symbolMapper = undefined;

packages/qwik/src/optimizer/src/plugins/vite-dev-server.ts

Lines changed: 3 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,15 @@ import type { IncomingMessage, ServerResponse } from 'http';
44
import { magenta } from 'kleur/colors';
55

66
import type { Connect, ViteDevServer } from 'vite';
7-
import type {
8-
OptimizerSystem,
9-
Path,
10-
ServerQwikManifest,
11-
SymbolMapper,
12-
SymbolMapperFn,
13-
} from '../types';
7+
import type { OptimizerSystem, Path, ServerQwikManifest } from '../types';
148
import clickToComponent from './click-to-component.html?raw';
159
import errorHost from './error-host.html?raw';
1610
import imageDevTools from './image-size-runtime.html?raw';
1711
import perfWarning from './perf-warning.html?raw';
18-
import { type NormalizedQwikPluginOptions, QWIK_HANDLERS_ID } from './plugin';
12+
import { type NormalizedQwikPluginOptions } from './plugin';
1913
import type { QwikViteDevResponse } from './vite';
2014
import { VITE_ERROR_OVERLAY_STYLES } from './vite-error';
2115
import { formatError, parseId } from './vite-utils';
22-
import { SYNC_QRL } from 'packages/qwik/src/core/shared/qrl/qrl-utils';
2316

2417
function getOrigin(req: IncomingMessage) {
2518
const { PROTOCOL_HEADER, HOST_HEADER } = process.env;
@@ -33,65 +26,15 @@ function getOrigin(req: IncomingMessage) {
3326
return `${protocol}://${host}`;
3427
}
3528

36-
function createSymbolMapper(base: string): SymbolMapperFn {
37-
return (
38-
symbolName: string,
39-
_mapper: SymbolMapper | undefined,
40-
parent: string | undefined
41-
): [string, string] => {
42-
if (symbolName === SYNC_QRL) {
43-
return [symbolName, ''];
44-
}
45-
if (!parent) {
46-
// Core symbols
47-
if (symbolName.startsWith('_')) {
48-
return [symbolName, `${base}${QWIK_HANDLERS_ID}`];
49-
}
50-
console.error(
51-
'qwik vite-dev-server symbolMapper: unknown qrl requested without parent:',
52-
symbolName
53-
);
54-
return [symbolName, `${base}${symbolName}.js`];
55-
}
56-
// In dev mode, the `parent` is the Vite URL for the parent, not the real absolute path.
57-
// It is always absolute but when on Windows that's without a /
58-
const qrlFile = `${base}${parent.startsWith('/') ? parent.slice(1) : parent}_${symbolName}.js`;
59-
return [symbolName, qrlFile];
60-
};
61-
}
62-
63-
let lazySymbolMapper: ReturnType<typeof createSymbolMapper> | null = null;
64-
/**
65-
* @beta
66-
* For a given symbol (QRL such as `onKeydown$`) the server needs to know which bundle the symbol is in.
67-
*
68-
* Normally this is provided by Qwik's `q-manifest` . But `q-manifest` only exists after a full client build.
69-
*
70-
* This would be a problem in dev mode. So in dev mode the symbol is mapped to the expected URL using the symbolMapper function below. For Vite the given path is fixed for a given symbol.
71-
*/
72-
export let symbolMapper: ReturnType<typeof createSymbolMapper> = (symbolName, mapper, parent) => {
73-
// This is a fallback in case the symbolMapper is copied early
74-
if (lazySymbolMapper) {
75-
return lazySymbolMapper(symbolName, mapper, parent);
76-
}
77-
throw new Error('symbolMapper not initialized');
78-
};
79-
8029
export async function configureDevServer(
8130
base: string,
8231
server: ViteDevServer,
8332
opts: NormalizedQwikPluginOptions,
8433
sys: OptimizerSystem,
8534
path: Path,
8635
isClientDevOnly: boolean,
87-
clientDevInput: string | undefined,
88-
devSsrServer: boolean
36+
clientDevInput: string | undefined
8937
) {
90-
symbolMapper = lazySymbolMapper = createSymbolMapper(base);
91-
if (!devSsrServer) {
92-
// we just needed the symbolMapper
93-
return;
94-
}
9538
const hasQwikRouter = server.config.plugins?.some(
9639
(plugin) => plugin.name === 'vite-plugin-qwik-router'
9740
);
@@ -214,7 +157,6 @@ export async function configureDevServer(
214157
stream: res,
215158
snapshot: !isClientDevOnly,
216159
manifest: isClientDevOnly ? undefined : manifest,
217-
symbolMapper: isClientDevOnly ? undefined : symbolMapper,
218160
serverData,
219161
containerAttributes: { ...serverData.containerAttributes },
220162
};

packages/qwik/src/optimizer/src/plugins/vite.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,8 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
639639

640640
configureServer(server: ViteDevServer) {
641641
qwikPlugin.configureServer(server);
642-
const devSsrServer = 'devSsrServer' in qwikViteOpts ? !!qwikViteOpts.devSsrServer : true;
642+
const devSsrServer =
643+
!qwikViteOpts.csr && ('devSsrServer' in qwikViteOpts ? !!qwikViteOpts.devSsrServer : true);
643644
const imageDevTools =
644645
qwikViteOpts.devTools && 'imageDevTools' in qwikViteOpts.devTools
645646
? qwikViteOpts.devTools.imageDevTools
@@ -649,7 +650,7 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
649650
server.middlewares.use(getImageSizeServer(qwikPlugin.getSys(), rootDir!, srcDir!));
650651
}
651652

652-
if (!qwikViteOpts.csr) {
653+
if (devSsrServer) {
653654
const plugin = async () => {
654655
const opts = qwikPlugin.getOptions();
655656
const sys = qwikPlugin.getSys();
@@ -661,11 +662,10 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
661662
sys,
662663
path,
663664
isClientDevOnly,
664-
clientDevInput,
665-
devSsrServer
665+
clientDevInput
666666
);
667667
};
668-
// TODO: Removed the "__qwikCityNew" condition in V3
668+
// TODO: Remove the "__qwikCityNew" condition in V3
669669
const isNEW =
670670
(globalThis as any).__qwikRouterNew === true ||
671671
(globalThis as any).__qwikCityNew === true ||

packages/qwik/src/optimizer/src/qwik.optimizer.api.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -406,10 +406,8 @@ export type SourceMapsOption = 'external' | 'inline' | undefined | null;
406406
// @public (undocumented)
407407
export type SymbolMapper = Record<string, readonly [symbol: string, chunk: string]>;
408408

409-
// Warning: (ae-forgotten-export) The symbol "createSymbolMapper" needs to be exported by the entry point index.d.ts
410-
//
411-
// @beta
412-
export let symbolMapper: ReturnType<typeof createSymbolMapper>;
409+
// @alpha @deprecated (undocumented)
410+
export const symbolMapper: undefined;
413411

414412
// @public (undocumented)
415413
export type SymbolMapperFn = (symbolName: string, mapper: SymbolMapper | undefined, parent?: string) => readonly [symbol: string, chunk: string] | undefined;

packages/qwik/src/server/platform.ts

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,42 @@
1-
import type { SerializeDocumentOptions } from './types';
21
import { setPlatform } from '@qwik.dev/core';
3-
import type { ResolvedManifest } from '@qwik.dev/core/optimizer';
4-
import type { CorePlatformServer } from './qwik-types';
2+
import { isDev } from '@qwik.dev/core/build';
3+
import type { ResolvedManifest, SymbolMapperFn } from '@qwik.dev/core/optimizer';
54
import { SYNC_QRL } from './qwik-copy';
5+
import type { CorePlatformServer, SymbolMapper } from './qwik-types';
6+
import type { SerializeDocumentOptions } from './types';
67

78
declare const require: (module: string) => Record<string, any>;
89

10+
/**
11+
* In dev mode, we create predicatable QRL segment filenames so we can recover the parent path in
12+
* the vite plugin, because we don't have a manifest
13+
*/
14+
const getDevSegmentPath = (
15+
mapper: SymbolMapper | undefined,
16+
symbolName: string,
17+
parent?: string
18+
): ReturnType<SymbolMapperFn> => {
19+
const existing = mapper?.[symbolName];
20+
if (existing) {
21+
return mapper[symbolName];
22+
}
23+
if (symbolName === SYNC_QRL) {
24+
return [symbolName, ''];
25+
}
26+
if (!parent) {
27+
// Core symbols
28+
if (symbolName.startsWith('_')) {
29+
return [symbolName, `${import.meta.env.BASE_URL}@qwik-handlers`];
30+
}
31+
console.error('qwik symbolMapper: unknown qrl requested without parent:', symbolName);
32+
return [symbolName, `${import.meta.env.BASE_URL}${symbolName}.js`];
33+
}
34+
// In dev mode, the `parent` is the Vite URL for the parent, not the real absolute path.
35+
// It is always absolute but when on Windows that's without a /
36+
const qrlFile = `${import.meta.env.BASE_URL}${parent.startsWith('/') ? parent.slice(1) : parent}_${symbolName}.js`;
37+
return [symbolName, qrlFile];
38+
};
39+
940
export function createPlatform(
1041
opts: SerializeDocumentOptions,
1142
resolvedManifest: ResolvedManifest | undefined
@@ -14,9 +45,9 @@ export function createPlatform(
1445
const mapperFn = opts.symbolMapper
1546
? opts.symbolMapper
1647
: (symbolName: string, _chunk: any, parent?: string): readonly [string, string] | undefined => {
17-
if (mapper) {
48+
if (mapper || isDev) {
1849
const hash = getSymbolHash(symbolName);
19-
const result = mapper[hash];
50+
const result = !isDev ? mapper![hash] : getDevSegmentPath(mapper, symbolName, parent);
2051
if (!result) {
2152
if (hash === SYNC_QRL) {
2253
return [hash, ''] as const;
@@ -25,10 +56,6 @@ export function createPlatform(
2556
if (isRegistered) {
2657
return [symbolName, '_'] as const;
2758
}
28-
if (parent) {
29-
// In dev mode, SSR may need to refer to a symbol that wasn't built yet on the client
30-
return [symbolName, `${parent}?qrl=${symbolName}`] as const;
31-
}
3259
console.error('Cannot resolve symbol', symbolName, 'in', mapper, parent);
3360
}
3461
return result;

0 commit comments

Comments
 (0)