Skip to content

fix(optimizer): transform code incrementally #6326

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
12 changes: 6 additions & 6 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/docs/src/repl/repl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export const Repl = component$((props: ReplProps) => {
input.version = v.version;

window.addEventListener('message', (ev) => receiveMessageFromReplServer(ev, store, input));
console.log(await import('../routes/repl/repl-sw.js/entry.ts?raw'));
store.serverUrl = new URL(`/repl/~repl-server-host.html?${store.clientId}`, origin).href;

// Now get the version from the network
Expand Down
3 changes: 2 additions & 1 deletion packages/docs/src/repl/worker/repl-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,15 @@ export const initReplServer = (win: Window, doc: Document, nav: Navigator) => {
} else {
loadTmr = setTimeout(() => {
console.error('Qwik REPL server "%s" has not initialized', clientId);
}, 15000);
}, 60000);

nav.serviceWorker
.register('/repl/repl-sw.js', {
scope: '/repl/',
})
.then(
(reg) => {
console.trace('Qwik REPL server "%s" service worker registered', clientId, reg);
swRegistration = reg;
if (swRegistration.active) {
console.debug('Qwik REPL server "%s" service worker registration active', clientId);
Expand Down
4 changes: 2 additions & 2 deletions packages/docs/src/routes/api/qwik-optimizer/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@
}
],
"kind": "Interface",
"content": "```typescript\nexport interface QwikManifest \n```\n\n\n<table><thead><tr><th>\n\nProperty\n\n\n</th><th>\n\nModifiers\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\n[bundles](#)\n\n\n</td><td>\n\n\n</td><td>\n\n{ \\[fileName: string\\]: [QwikBundle](#qwikbundle)<!-- -->; }\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[injections?](#)\n\n\n</td><td>\n\n\n</td><td>\n\n[GlobalInjections](#globalinjections)<!-- -->\\[\\]\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n<tr><td>\n\n[manifestHash](#)\n\n\n</td><td>\n\n\n</td><td>\n\nstring\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[mapping](#)\n\n\n</td><td>\n\n\n</td><td>\n\n{ \\[symbolName: string\\]: string; }\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[options?](#)\n\n\n</td><td>\n\n\n</td><td>\n\n{ target?: string; buildMode?: string; entryStrategy?: { \\[key: string\\]: any; }; }\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n<tr><td>\n\n[platform?](#)\n\n\n</td><td>\n\n\n</td><td>\n\n{ \\[name: string\\]: string; }\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n<tr><td>\n\n[symbols](#)\n\n\n</td><td>\n\n\n</td><td>\n\n{ \\[symbolName: string\\]: [QwikSymbol](#qwiksymbol)<!-- -->; }\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[version](#)\n\n\n</td><td>\n\n\n</td><td>\n\nstring\n\n\n</td><td>\n\n\n</td></tr>\n</tbody></table>",
"content": "The metadata of the build. One of its uses is storing where QRL symbols are located.\n\n\n```typescript\nexport interface QwikManifest \n```\n\n\n<table><thead><tr><th>\n\nProperty\n\n\n</th><th>\n\nModifiers\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\n[bundles](#)\n\n\n</td><td>\n\n\n</td><td>\n\n{ \\[fileName: string\\]: [QwikBundle](#qwikbundle)<!-- -->; }\n\n\n</td><td>\n\nAll code bundles, used to know the import graph\n\n\n</td></tr>\n<tr><td>\n\n[injections?](#)\n\n\n</td><td>\n\n\n</td><td>\n\n[GlobalInjections](#globalinjections)<!-- -->\\[\\]\n\n\n</td><td>\n\n_(Optional)_ CSS etc to inject in the document head\n\n\n</td></tr>\n<tr><td>\n\n[manifestHash](#)\n\n\n</td><td>\n\n\n</td><td>\n\nstring\n\n\n</td><td>\n\nContent hash of the manifest, if this changes, the code changed\n\n\n</td></tr>\n<tr><td>\n\n[mapping](#)\n\n\n</td><td>\n\n\n</td><td>\n\n{ \\[symbolName: string\\]: string; }\n\n\n</td><td>\n\nWhere QRLs are located. If there's a `#`<!-- -->, the string after it is the export\n\n\n</td></tr>\n<tr><td>\n\n[options?](#)\n\n\n</td><td>\n\n\n</td><td>\n\n{ target?: string; buildMode?: string; entryStrategy?: { \\[key: string\\]: any; }; }\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n<tr><td>\n\n[platform?](#)\n\n\n</td><td>\n\n\n</td><td>\n\n{ \\[name: string\\]: string; }\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n<tr><td>\n\n[symbols](#)\n\n\n</td><td>\n\n\n</td><td>\n\n{ \\[symbolName: string\\]: [QwikSymbol](#qwiksymbol)<!-- -->; }\n\n\n</td><td>\n\nQRL symbols\n\n\n</td></tr>\n<tr><td>\n\n[version](#)\n\n\n</td><td>\n\n\n</td><td>\n\nstring\n\n\n</td><td>\n\n\n</td></tr>\n</tbody></table>",
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/types.ts",
"mdFile": "qwik.qwikmanifest.md"
},
Expand Down Expand Up @@ -644,7 +644,7 @@
}
],
"kind": "TypeAlias",
"content": "```typescript\nexport type SymbolMapperFn = (symbolName: string, mapper: SymbolMapper | undefined) => readonly [symbol: string, chunk: string] | undefined;\n```\n**References:** [SymbolMapper](#symbolmapper)",
"content": "```typescript\nexport type SymbolMapperFn = (symbolName: string, mapper: SymbolMapper | undefined, parent?: string) => readonly [symbol: string, chunk: string] | undefined;\n```\n**References:** [SymbolMapper](#symbolmapper)",
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/types.ts",
"mdFile": "qwik.symbolmapperfn.md"
},
Expand Down
13 changes: 12 additions & 1 deletion packages/docs/src/routes/api/qwik-optimizer/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1547,6 +1547,8 @@ _(Optional)_

## QwikManifest

The metadata of the build. One of its uses is storing where QRL symbols are located.

```typescript
export interface QwikManifest
```
Expand Down Expand Up @@ -1580,6 +1582,8 @@ Description

</td><td>

All code bundles, used to know the import graph

</td></tr>
<tr><td>

Expand All @@ -1593,7 +1597,7 @@ Description

</td><td>

_(Optional)_
_(Optional)_ CSS etc to inject in the document head

</td></tr>
<tr><td>
Expand All @@ -1608,6 +1612,8 @@ string

</td><td>

Content hash of the manifest, if this changes, the code changed

</td></tr>
<tr><td>

Expand All @@ -1621,6 +1627,8 @@ string

</td><td>

Where QRLs are located. If there's a `#`, the string after it is the export

</td></tr>
<tr><td>

Expand Down Expand Up @@ -1664,6 +1672,8 @@ _(Optional)_

</td><td>

QRL symbols

</td></tr>
<tr><td>

Expand Down Expand Up @@ -2758,6 +2768,7 @@ export type SymbolMapper = Record<
export type SymbolMapperFn = (
symbolName: string,
mapper: SymbolMapper | undefined,
parent?: string,
) => readonly [symbol: string, chunk: string] | undefined;
```

Expand Down
2 changes: 1 addition & 1 deletion packages/docs/src/routes/api/qwik/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@
}
],
"kind": "Interface",
"content": "Low-level API for platform abstraction.\n\nDifferent platforms (browser, node, service workers) may have different ways of handling things such as `requestAnimationFrame` and imports. To make Qwik platform-independent Qwik uses the `CorePlatform` API to access the platform API.\n\n`CorePlatform` also is responsible for importing symbols. The import map is different on the client (browser) then on the server. For this reason, the server has a manifest that is used to map symbols to javascript chunks. The manifest is encapsulated in `CorePlatform`<!-- -->, for this reason, the `CorePlatform` can't be global as there may be multiple applications running at server concurrently.\n\nThis is a low-level API and there should not be a need for you to access this.\n\n\n```typescript\nexport interface CorePlatform \n```\n\n\n<table><thead><tr><th>\n\nProperty\n\n\n</th><th>\n\nModifiers\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\n[chunkForSymbol](#)\n\n\n</td><td>\n\n\n</td><td>\n\n(symbolName: string, chunk: string \\| null) =&gt; readonly \\[symbol: string, chunk: string\\] \\| undefined\n\n\n</td><td>\n\nRetrieve chunk name for the symbol.\n\nWhen the application is running on the server the symbols may be imported from different files (as server build is typically a single javascript chunk.) For this reason, it is necessary to convert the chunks from server format to client (browser) format. This is done by looking up symbols (which are globally unique) in the manifest. (Manifest is the mapping of symbols to the client chunk names.)\n\n\n</td></tr>\n<tr><td>\n\n[importSymbol](#)\n\n\n</td><td>\n\n\n</td><td>\n\n(containerEl: Element \\| undefined, url: string \\| URL \\| undefined \\| null, symbol: string) =&gt; [ValueOrPromise](#valueorpromise)<!-- -->&lt;any&gt;\n\n\n</td><td>\n\nRetrieve a symbol value from QRL.\n\nQwik needs to lazy load data and closures. For this Qwik uses QRLs that are serializable references of resources that are needed. The QRLs contain all the information necessary to retrieve the reference using `importSymbol`<!-- -->.\n\nWhy not use `import()`<!-- -->? Because `import()` is relative to the current file, and the current file is always the Qwik framework. So QRLs have additional information that allows them to serialize imports relative to application base rather than the Qwik framework file.\n\n\n</td></tr>\n<tr><td>\n\n[isServer](#)\n\n\n</td><td>\n\n\n</td><td>\n\nboolean\n\n\n</td><td>\n\nTrue of running on the server platform.\n\n\n</td></tr>\n<tr><td>\n\n[nextTick](#)\n\n\n</td><td>\n\n\n</td><td>\n\n(fn: () =&gt; any) =&gt; Promise&lt;any&gt;\n\n\n</td><td>\n\nPerform operation on next tick.\n\n\n</td></tr>\n<tr><td>\n\n[raf](#)\n\n\n</td><td>\n\n\n</td><td>\n\n(fn: () =&gt; any) =&gt; Promise&lt;any&gt;\n\n\n</td><td>\n\nPerform operation on next request-animation-frame.\n\n\n</td></tr>\n</tbody></table>",
"content": "Low-level API for platform abstraction.\n\nDifferent platforms (browser, node, service workers) may have different ways of handling things such as `requestAnimationFrame` and imports. To make Qwik platform-independent Qwik uses the `CorePlatform` API to access the platform API.\n\n`CorePlatform` also is responsible for importing symbols. The import map is different on the client (browser) then on the server. For this reason, the server has a manifest that is used to map symbols to javascript chunks. The manifest is encapsulated in `CorePlatform`<!-- -->, for this reason, the `CorePlatform` can't be global as there may be multiple applications running at server concurrently.\n\nThis is a low-level API and there should not be a need for you to access this.\n\n\n```typescript\nexport interface CorePlatform \n```\n\n\n<table><thead><tr><th>\n\nProperty\n\n\n</th><th>\n\nModifiers\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\n[chunkForSymbol](#)\n\n\n</td><td>\n\n\n</td><td>\n\n(symbolName: string, chunk: string \\| null, parent?: string) =&gt; readonly \\[symbol: string, chunk: string\\] \\| undefined\n\n\n</td><td>\n\nRetrieve chunk name for the symbol.\n\nWhen the application is running on the server the symbols may be imported from different files (as server build is typically a single javascript chunk.) For this reason, it is necessary to convert the chunks from server format to client (browser) format. This is done by looking up symbols (which are globally unique) in the manifest. (Manifest is the mapping of symbols to the client chunk names.)\n\n\n</td></tr>\n<tr><td>\n\n[importSymbol](#)\n\n\n</td><td>\n\n\n</td><td>\n\n(containerEl: Element \\| undefined, url: string \\| URL \\| undefined \\| null, symbol: string) =&gt; [ValueOrPromise](#valueorpromise)<!-- -->&lt;any&gt;\n\n\n</td><td>\n\nRetrieve a symbol value from QRL.\n\nQwik needs to lazy load data and closures. For this Qwik uses QRLs that are serializable references of resources that are needed. The QRLs contain all the information necessary to retrieve the reference using `importSymbol`<!-- -->.\n\nWhy not use `import()`<!-- -->? Because `import()` is relative to the current file, and the current file is always the Qwik framework. So QRLs have additional information that allows them to serialize imports relative to application base rather than the Qwik framework file.\n\n\n</td></tr>\n<tr><td>\n\n[isServer](#)\n\n\n</td><td>\n\n\n</td><td>\n\nboolean\n\n\n</td><td>\n\nTrue of running on the server platform.\n\n\n</td></tr>\n<tr><td>\n\n[nextTick](#)\n\n\n</td><td>\n\n\n</td><td>\n\n(fn: () =&gt; any) =&gt; Promise&lt;any&gt;\n\n\n</td><td>\n\nPerform operation on next tick.\n\n\n</td></tr>\n<tr><td>\n\n[raf](#)\n\n\n</td><td>\n\n\n</td><td>\n\n(fn: () =&gt; any) =&gt; Promise&lt;any&gt;\n\n\n</td><td>\n\nPerform operation on next request-animation-frame.\n\n\n</td></tr>\n</tbody></table>",
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/platform/types.ts",
"mdFile": "qwik.coreplatform.md"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/src/routes/api/qwik/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1558,7 +1558,7 @@ Description

</td><td>

(symbolName: string, chunk: string \| null) =&gt; readonly [symbol: string, chunk: string] \| undefined
(symbolName: string, chunk: string \| null, parent?: string) =&gt; readonly [symbol: string, chunk: string] \| undefined

</td><td>

Expand Down
10 changes: 8 additions & 2 deletions packages/docs/src/routes/repl/repl-sw.js/entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,21 @@
self.onmessage = receiveMessageFromMain;

self.onfetch = requestHandler;

self.onsync = (ev) => {

Check failure on line 14 in packages/docs/src/routes/repl/repl-sw.js/entry.ts

View workflow job for this annotation

GitHub Actions / Build Docs

Property 'onsync' does not exist on type 'QwikWorkerGlobal'.

Check failure on line 14 in packages/docs/src/routes/repl/repl-sw.js/entry.ts

View workflow job for this annotation

GitHub Actions / Build Docs

Parameter 'ev' implicitly has an 'any' type.
debugger;

Check failure on line 15 in packages/docs/src/routes/repl/repl-sw.js/entry.ts

View workflow job for this annotation

GitHub Actions / Lint Package

Unexpected 'debugger' statement
};
self.oninstall = (ev) => {
debugger;

Check failure on line 18 in packages/docs/src/routes/repl/repl-sw.js/entry.ts

View workflow job for this annotation

GitHub Actions / Lint Package

Unexpected 'debugger' statement
self.skipWaiting();
ev.waitUntil(
Promise.all([caches.open(QWIK_REPL_DEPS_CACHE), caches.open(QWIK_REPL_RESULT_CACHE)])
);
};

self.onactivate = () => self.clients.claim();
self.onactivate = () => {
debugger;

Check failure on line 26 in packages/docs/src/routes/repl/repl-sw.js/entry.ts

View workflow job for this annotation

GitHub Actions / Lint Package

Unexpected 'debugger' statement
self.clients.claim();
};

export interface ReplGlobalApi {
qwikCore?: typeof import('@builder.io/qwik');
Expand Down
24 changes: 23 additions & 1 deletion packages/docs/vite.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,28 @@
},

plugins: [
{
name: 'spy',
enforce: 'pre',
resolveId: {
order: 'pre',
handler(id, importer) {

Check failure on line 66 in packages/docs/vite.config.mts

View workflow job for this annotation

GitHub Actions / Build Docs

Parameter 'id' implicitly has an 'any' type.

Check failure on line 66 in packages/docs/vite.config.mts

View workflow job for this annotation

GitHub Actions / Build Docs

Parameter 'importer' implicitly has an 'any' type.
console.log('===================== spy resolveId', id, importer);
},
},
load: {
order: 'pre',
handler(id, options) {

Check failure on line 72 in packages/docs/vite.config.mts

View workflow job for this annotation

GitHub Actions / Build Docs

Parameter 'id' implicitly has an 'any' type.

Check failure on line 72 in packages/docs/vite.config.mts

View workflow job for this annotation

GitHub Actions / Build Docs

Parameter 'options' implicitly has an 'any' type.
console.log('===================== spy load', id, options);
},
},
transform: {
order: 'pre',
handler(code, id, options) {

Check failure on line 78 in packages/docs/vite.config.mts

View workflow job for this annotation

GitHub Actions / Build Docs

Parameter 'code' implicitly has an 'any' type.

Check failure on line 78 in packages/docs/vite.config.mts

View workflow job for this annotation

GitHub Actions / Build Docs

Parameter 'id' implicitly has an 'any' type.

Check failure on line 78 in packages/docs/vite.config.mts

View workflow job for this annotation

GitHub Actions / Build Docs

Parameter 'options' implicitly has an 'any' type.
console.log('===================== spy transform', id, options);
},
},
},
qwikCity({
mdxPlugins: {
rehypeSyntaxHighlight: false,
Expand Down Expand Up @@ -112,7 +134,7 @@
],
},
}),
qwikVite(),
qwikVite({ debug: true }),
partytownVite({
dest: resolve('dist', '~partytown'),
}),
Expand Down
5 changes: 4 additions & 1 deletion packages/qwik/src/core/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export interface ContextId<STATE> {

// @public
export interface CorePlatform {
chunkForSymbol: (symbolName: string, chunk: string | null) => readonly [symbol: string, chunk: string] | undefined;
chunkForSymbol: (symbolName: string, chunk: string | null, parent?: string) => readonly [symbol: string, chunk: string] | undefined;
importSymbol: (containerEl: Element | undefined, url: string | URL | undefined | null, symbol: string) => ValueOrPromise<any>;
isServer: boolean;
nextTick: (fn: () => any) => Promise<any>;
Expand Down Expand Up @@ -542,6 +542,9 @@ export type NativeWheelEvent = WheelEvent;
// @internal (undocumented)
export const _noopQrl: <T>(symbolName: string, lexicalScopeCapture?: any[]) => QRL<T>;

// @internal (undocumented)
export const _noopQrlDEV: <T>(symbolName: string, opts: QRLDev, lexicalScopeCapture?: any[]) => QRL<T>;

// @public
export type NoSerialize<T> = (T & {
__no_serialize__: true;
Expand Down
2 changes: 1 addition & 1 deletion packages/qwik/src/core/internal.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { _pauseFromContexts, _serializeData } from './container/pause';
export { _noopQrl, _regSymbol } from './qrl/qrl';
export { _noopQrl, _noopQrlDEV, _regSymbol } from './qrl/qrl';
export { _renderSSR } from './render/ssr/render-ssr';
export { _hW } from './render/dom/notify-render';
export { _wrapSignal, _wrapProp } from './state/signal';
Expand Down
7 changes: 7 additions & 0 deletions packages/qwik/src/core/platform/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,19 @@ export const createPlatform = (): CorePlatform => {
if (!containerEl) {
throw qError(QError_qrlMissingContainer, url, symbolName);
}
let attr: string | undefined;
if (typeof url === 'string') {
[url, attr] = url.split('#');
}
const urlDoc = toUrl(containerEl.ownerDocument, containerEl, url).toString();
const urlCopy = new URL(urlDoc);
urlCopy.hash = '';
urlCopy.search = '';
const importURL = urlCopy.href;
return import(/* @vite-ignore */ importURL).then((mod) => {
if (attr) {
mod = mod[attr];
}
return mod[symbolName];
});
},
Expand Down
3 changes: 2 additions & 1 deletion packages/qwik/src/core/platform/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ export interface CorePlatform {
// </docs>
chunkForSymbol: (
symbolName: string,
chunk: string | null
chunk: string | null,
parent?: string
) => readonly [symbol: string, chunk: string] | undefined;
}

Expand Down
Loading
Loading