# Qwik Optimizer Brainstorm [Optimizer Code Transformations](/lGHH9hjrSNq7yorN2EOBHA) 1. `tsc` 2. QwikOptimizer => Code can run on server (with optional entry point rename manifest) 3. Bundler: `rollup` / `webpack` / `esb` ... - Bundlers can rename entry points, but they can't change a set of entry points. - Bundlers will produced a manifest which maps the entry point from step #2 to hash based entry point. 4. QwikPostOptimzer (only client code) => (which may be port of `rollup`) inlines the manifest (by renaming the entry points per manifest) only applies to the client code OUTPUT CLIENT (QwikOptimizer => rollup => output) - hashes files in the filesystem - canonical qrl in the code QwikPostOptimzer => - [NO CHANGE] hashes files in the filesystem - hashed qrl in the code OUTPUT SERVER (QwikOptimizer => output) - canonical files in the filesystem - canonical qrl in the code QwikPostOptimzer => - canonical files in the filesystem - hashed qrl in the code Source code: 1. `my-file.js`: `export const symbol1 = qHook(() => 123)` 2. `entry-a.js`: `export const symbol1 = qHook('entry-a#symbol1')` 3. `entry-a-1234.ts`: `export const symbol1 = qHook('entry-a#symbol1')` 4. `entry-a-1234.ts`: `export const symbol1 = qHook('entry-a-2345#symbol1')` --- 1) Source in TS 3) QwikOptimizer - TS => JS - (CUSTOM TRANSFORM) Moves qHooks into exports within the same file. - (ESbuild built-in) Code move into `qHook` into separate files - Output new set of files 4) Rollup plugin - Before bundling: Run Qwik optimizer and get entry points + all files - Implement renderDynamicImports() to rename import() - Bundler generates bundles ### 1) Source ```typescript= const Greeter = qComponent({ onRender: qHook(() => (<span>Hello</span>), 's2') }) ``` ### 2) Convert to bundler friendly Input **`components.qwik.js`** ```typescript= const Greeter = qComponent({ onRender: qInternalHook('./greeter.hook-onrender.qwik.js', 'someSymbol') }) ``` entryFileName: "p-[hash].jsm" ```htmlembedded= <button on:click="/greeter.hook-onrender.qwik#someSymbol"/> ``` **`greeter.hook-onrender.qwik.js`** ```typescript= export const _NAME_ = new URL(import.meta.url).pathname; // greeter.hook-onrender.qwik.js export const someSymbol = qHook(() => (<span>Hello</span>)); ``` ### 3) Rollup ```typescript= const Greeter = qComponent({ onRender: qHook(import()"component.hook.qwik.js", 'someSymbol') }) ``` **`chunk-abc.js`** ```typescript= export const someSymbol = qHook(() => (<span>Hello</span>)); ``` **`manifest.js`** ``` { "greeter.hook-onrender.qwik": "chunk-abc.js" } ``` ### 4) Browser Ready ESM Output - Rollup Output Plugin `renderDynamicImport()` ```typescript= const Greeter = qComponent({ onRender: qHook('/chunk-abc#someSymbol') }) ``` **`chunk-abc.js`** ```typescript= export const someSymbol = qHook(() => (<span>Hello</span>)); ``` ```htmlembedded= <button on:click="/p-23424.js#someSymbol"/> ``` 1. Client build for web - Done by any bundler - Configured by the user - qHook("/chunk-1234") - entryFilename: "[hash].js" - This specific does not use canonical name - Any canonical path => hashed path 1-to-1 ---- ```sequence source -> extracted: QExtractOpt extracted -> entry: QEntryOpt entry -> bundled: Bundler bundled -> qBundled: QPostOpt bundled -> extracted: symbol-mfst (runtime) bundled -> qBundled: symbol-mfst extracted -> browser: SSR browser -> symbolStat: UserBehavior symbolStat -> entry: priority-mfst (iterative feedback) ``` ### `source` **`app.tsx`** ```typescript= import {qHook, qComponent} from '@builder.io/qwik'; import {IonButton} from 'ionic'; export const App = qComponent({ onRender: qHook(() => ( <> <IonButton on:click={qHook(() => alert('HI'))}>click-me</IonButton> </> )) }) ``` **`main`** ```typescript= import {App} from './app'; qRender(document.body, <App/>); ``` **`ionic`** ```typescript= import {qHook, qComponent} from '@builder.io/qwik'; export const IonButton = qComponent({ onRender: qHook(() => ( <button on:click={qHook(() => alert('HI'))}>click-me</button> )) }) ``` ### `extracted` **`app.js`** ```typescript= import {qHook, qComponent} from '@builder.io/qwik'; export const App = qComponent({ onRender: qHook('app_App_onHook#s0') }) ``` **`app_App_onHook.qwik.js`** ```typescript= import {IonButton} from 'ionic'; export const s0 = qHook(() => ( <> <IonButton on:click={qHook('app_App_onHook_onClick#s1')}>click-me</IonButton> </> )); ``` **`app_App_onHook_onClick.qwik.js`** ```typescript= export const s1 = qHook(() => alert('HI')); ``` **`symbols.qwik.js`** ```typescript= export {s1} from './app_App_onHook_onClick.qwik.js'; ``` **`ionic`** ```typescript= import {qHook, qComponent} from '@builder.io/qwik'; export const IonButton = qComponent({ onRender: qHook("ionic_IonButton_onRender#s2") }) ``` **`ionic_IonButton_onRender.js`** ```typescript= export const s2 = qHook(() => ( <Host on:click={qHook('ionic_IonButton_onRender_onClick#s3')}> <button on:click={qHook('ionic_IonButton_onRender_onClick#s3')}> click-me </button> </Host> )); ``` **`ionic_IonButton_onRender_onClick.js`** ```typescript= export const s3 = qHook(() => alert('HI')) ``` **`symbols.json`** ```typescript= { version: 1, symbols: [ { name: "s2", path: "./ionic_IonButton_onRender.js", }, { name: "s2", path: "./ionic_IonButton_onRender.js", } ] } ``` **package.json** ``` { "qwik": "./symbols.qwik.js" } ``` ```htmlembedded= <body> <app on:q-render="app_App_onHook#s0" on:click="someURL#s10"> <ion-button on:q-render="ionic_IonButton_onRender#s2" on:click="app_App_onHook_onClick#s1 ionic_IonButton_onRender_onClick#s3"> <button> click-me </button> </ion-button> </app> </body> ``` ### `entry` **`entry-a.js`** ```typescript= export {s0} from './app_App_onHook'; ``` **`entry-b.js`** ```typescript= export {s1} from './app_App_onHook_onClick'; ``` **`entry-c.js`** ```typescript= export {s2} from 'ionic/IonButton_onRender'; ``` **`entry-d.js`** ```typescript= export {s3} from 'ionic/IonButton_onRender_onClick'; ``` ### `bundle` ```javascript= ``` userRollup({ inputs: [ "entry-a.js", "entry-b.js", "entry-c.js", "entry-d.js", ] }) ``` **`chunk-abc.js`** ```typescript= import {qHook, qComponent} from '@builder.io/qwik'; export const App = qComponent({ onRender: qHook('app_App_onHook#s0') }) ``` **`entry-a.js`** ```typescript= import {IonButton} from 'ionic'; export s0 = qHook(() => ( <> <IonButton on:click={qHook('app_App_onHook_onClick#s1')}>click-me</IonButton> </> )); export s1 = qHook(() => alert('HI')); export s2 = qHook(() => Ionic.doSomething()); export s3 = qHook(() => Ionic.doSomething()); ``` **`manifest.json`** ```javascript= { 's0': 'entry-a-abc', 's1': 'entry-a-abc', 's2': 'entry-a-abc', 's3': 'entry-a-abc', } ``` ### `qBundle` **`chunk-abc.js`** ```typescript= import {qHook, qComponent} from '@builder.io/qwik'; export const App = qComponent({ onRender: qHook('entry-a-abc#s0') }) ``` **`entry-a-abc.js`** ```typescript= import {IonButton} from 'ionic'; export s0 = qHook(() => ( <> <IonButton on:click={qHook('entry-a-abc#s1')}>click-me</IonButton> </> )); export s1 = qHook(() => alert('HI')); export s2 = qHook(() => Ionic.doSomething()); export s3 = qHook(() => Ionic.doSomething()); ``` ---- ```typescript export const Cm1 = qComponent(...qHook1(() => ... qHook2() ) export const Cm2 = qComponent(...qHook3()) export const Cm3 = qComponent(...qHook4()) const something = () => { qHook5(() => { }); () ``` Cmp1 = 1,2,4 Cmp2 = 3,4 Cmp3 = 4,5