Qwik framework: resumability koncepcija

Kai pirmą kartą susiduri su Qwik framework, pirmiausia į akis krenta keistas žodis – „resumability”. Jei esi bent šiek tiek susipažinęs su moderniais JavaScript framework’ais, tikriausiai girdėjai apie hydration procesą, kurį naudoja React, Vue ar kiti populiarūs įrankiai. Na, Qwik kūrėjai pasakė „ačiū, ne” ir sugalvojo visiškai kitokį būdą, kaip tvarkyti interaktyvumą naršyklėje.

Kas čia per resumability ir kodėl turėtų rūpėti

Įsivaizduok situaciją: tu atsidari puslapį telefone, stovėdamas metro stotelėje su prasčiausiu 3G ryšiu. Puslapis užsikrauna, matai turinį, bet negali nieko paspausti, nes JavaScript vis dar kraunasi ir „hidratauja” visą aplikaciją. Skamba pažįstama? Tai klasikinė hydration problema.

Resumability veikia fundamentaliai kitaip. Vietoj to, kad serveris sugeneruotų HTML, o paskui naršyklė turėtų iš naujo perskaityti visą komponentų medį ir „prisegti” event listener’ius, Qwik serializa aplikacijos būseną tiesiai į HTML. Kai vartotojas ką nors paspaudžia, framework žino tiksliai, kokį kodą reikia pakrauti – nei daugiau, nei mažiau.

Praktiškai tai reiškia, kad tavo aplikacija tampa interaktyvi akimirksniu, net jei JavaScript dar nėra pilnai užsikrovęs. Tai ne maža optimizacija – tai paradigmos pokytis.

Kaip tai veikia po gaubtu

Qwik naudoja keletą gudrybių, kad resumability veiktų. Pirmiausia, viskas prasideda nuo to, kaip rašai komponentus. Vietoj įprastų funkcijų, naudoji component$() sintaksę. Tas dolerinis ženklas nėra atsitiktinis – jis nurodo Qwik optimizatoriui, kad šis kodas turėtų būti išskaidytas į atskirus chunk’us.

Štai paprastas pavyzdys:

export const Counter = component$(() => {
  const count = useSignal(0);
  
  return (
    <button onClick$={() => count.value++}>
      Paspaudė: {count.value}
    </button>
  );
});

Matai tą onClick$? Ir vėl dolerio ženklas. Tai reiškia, kad event handler’io kodas bus iškeltas į atskirą failą. Kai vartotojas paspaus mygtuką, Qwik pakraus tik tą konkretų kodą, o ne visą aplikaciją.

Serveris sugeneravo HTML atrodys maždaug taip:

<button q:id="abc123" on:click="./chunk-xyz.js#handler">
  Paspaudė: 0
</button>

Viskas, ko reikia interaktyvumui, yra čia – nuoroda į kodą ir būsenos identifikatorius. Naršyklė nežiūri į visą komponentų medį, ji tiesiog žino: „jei kas nors paspaus šitą mygtuką, man reikia pakrauti chunk-xyz.js”.

Lazy loading steroidais

Turbūt galvoji: „bet lazy loading juk egzistuoja jau seniai”. Teisybė, bet Qwik veža jį į visiškai kitą lygį. React ar Vue gali lazy loadinti komponentus, bet event handler’iai vis tiek turi būti prisegti per hydration procesą. O tai reiškia, kad bent minimalus JavaScript bundle turi būti pakrautas ir įvykdytas.

Qwik lazy loadina viską – komponentus, event handler’ius, net būsenos valdymą. Ir svarbiausia – tai vyksta automatiškai. Tau nereikia sėdėti ir galvoti, ką ir kaip lazy loadinti. Optimizer’is padaro tai už tave, analizuodamas tavo kodą build metu.

Praktinis pavyzdys: turite e-commerce puslapį su produktų sąrašu. Kiekvienas produktas turi „Pridėti į krepšelį” mygtuką. Tradiciniame framework’e, net jei vartotojas tik skaito aprašymus ir nieko nepaspaudžia, visas krepšelio logikos kodas jau yra pakrautas. Qwik? Jis pakraus krepšelio kodą tik tada, kai kas nors bandys į jį ką nors įdėti.

Signals – būsenos valdymas be galvos skausmo

Qwik naudoja signals būsenos valdymui, ir tai puikiai dera su resumability koncepcija. Jei dirbai su SolidJS ar Vue 3 Composition API, tai bus pažįstama. Signals yra reaktyvūs primityvai, kurie automatiškai atnaujina UI, kai pasikeičia jų vertė.

Štai kaip galėtum susikurti paprastą todo aplikaciją:

export const TodoList = component$(() => {
  const todos = useSignal(['Išmokti Qwik', 'Sukurti app']);
  const newTodo = useSignal('');
  
  const addTodo = $(() => {
    if (newTodo.value.trim()) {
      todos.value = [...todos.value, newTodo.value];
      newTodo.value = '';
    }
  });
  
  return (
    <div>
      <input 
        value={newTodo.value}
        onInput$={(e) => newTodo.value = e.target.value}
      />
      <button onClick$={addTodo}>Pridėti</button>
      <ul>
        {todos.value.map((todo) => (
          <li key={todo}>{todo}</li>
        ))}
      </ul>
    </div>
  );
});

Gražu tai, kad signals yra serializable. Kai serveris generuoja HTML, jis įtraukia signal’ų vertes tiesiai į markup’ą. Kai naršyklė paima valdymą, ji gali tęsti nuo tos pačios vietos, kur serveris baigė. Jokio state mismatch, jokio flicker’io.

Optimizer – slaptas ginklas

Qwik optimizer’is yra tai, kas daro visą magiją įmanomą. Tai Vite pluginas, kuris analizuoja tavo kodą build metu ir automatiškai jį skaido į mažus chunk’us. Kiekvienas $() simbolis yra signalas optimizer’iui: „čia prasideda naujas lazy loadable boundary”.

Optimizer’is taip pat generuoja visą metadata, kurios reikia resumability procesui. Jis sukuria mapping’us tarp HTML atributų ir JavaScript chunk’ų, suskaičiuoja priklausomybes, optimizuoja bundle dydžius.

Ir viskas vyksta automatiškai. Tu tiesiog rašai kodą su dolerino ženklais, o optimizer’is paverčia jį į super optimizuotą, lazily loadable aplikaciją. Nereikia jokių manual code splitting konfigūracijų ar dynamic import() iškvietimų.

Realaus pasaulio performance

Gerai, teorija skamba įspūdingai, bet kaip tai veikia praktikoje? Qwik komanda dažnai demonstruoja pavyzdžius, kur jų framework’as pasiekia beveik idealų Time to Interactive (TTI) rodiklį – dažnai tik kelias milisekundes.

Pagalvok apie tai: tradicinis React aplikacija gali turėti 200-300KB JavaScript bundle’ą, kurį reikia parsinti ir įvykdyti prieš tai, kai aplikacija tampa interaktyvi. Net su code splitting ir lazy loading, vis tiek reikia pakrauti ir įvykdyti „core” bundle’ą.

Qwik aplikacija? Pradinis JavaScript gali būti vos kelių kilobaitų – tik mažytis runtime, kuris žino, kaip pakrauti reikalingus chunk’us pagal poreikį. Viskas kita kraunasi tik tada, kai to reikia.

Tai ypač svarbu mobiliuose įrenginiuose su lėtesniais procesoriais. JavaScript parsing ir execution yra vienas iš didžiausių bottleneck’ų mobile performance. Jei to galima išvengti, laimite milžinišką performance boost’ą.

Kada Qwik turi prasmę (ir kada ne)

Nenoriu skambėti kaip Qwik fanboy’us – kaip ir bet kuris įrankis, jis turi savo niche. Qwik yra puikus pasirinkimas, kai tau rūpi:

  • Greitas initial page load, ypač lėtuose tinkluose
  • SEO ir server-side rendering
  • Mobile performance
  • Content-heavy puslapiai, kur didelė dalis turinio yra statiška

Bet jei kurti highly interactive aplikaciją, kur vartotojas nuolat sąveikauja su UI (pvz., Google Docs tipo editor’ius), resumability privalumai gali būti mažesni. Tokiose aplikacijose vis tiek greitai pakrausi didžiąją dalį kodo, nes vartotojas naudos daugumą funkcijų.

Taip pat reikia pripažinti, kad Qwik ekosistema dar nėra tokia brandi kaip React ar Vue. Trūksta bibliotekų, community mažesnė, Stack Overflow atsakymų rasi mažiau. Bet jei esi avangardinių technologijų mėgėjas ir nebijai kartais pasikasti dokumentacijoje, tai neturėtų būti didelė problema.

Ką turėtum žinoti prieš pradedant

Jei nusprendei išbandyti Qwik, štai keletas praktinių patarimų:

Įpratink prie dolerino ženklų. Iš pradžių gali atrodyti keista rašyti onClick$ vietoj onClick, bet tai greitai tampa antra prigimtimi. Tiesiog prisimink: dolerio ženklas = lazy loading boundary.

Nekovok su optimizer’iu. Jei optimizer’is skundžiasi dėl tavo kodo, greičiausiai tu darai kažką, kas nėra compatible su resumability. Vietoj to, kad bandytum apgauti sistemą, geriau perskaityk dokumentaciją ir suprask, kodėl tai problema.

Naudok Qwik City. Tai meta-framework, pastatytas ant Qwik, kuris prideda routing, layouts, data loading ir kitas būtinas funkcijas. Tai kaip Next.js React’ui ar Nuxt Vue’ui. Nebent turi labai specifinių poreikių, pradėk su Qwik City.

Išmok signals. Jie yra Qwik būsenos valdymo pagrindas. Gera žinia – jie daug paprastesni nei Redux ar MobX. Bloga žinia – jei esi įpratęs prie React hooks, reikės šiek tiek perkonfigūruoti smegenis.

Testuok realiomis sąlygomis. Qwik privalumai labiausiai matomi lėtuose tinkluose ir mobiliuose įrenginiuose. Chrome DevTools turi network throttling – naudok jį. Testuok su CPU throttling. Tik taip pamatysi tikrąjį performance skirtumą.

Į ką žiūri ateitis

Resumability koncepcija nėra vien Qwik išradimas – tai idėja, kuri gali pakeisti, kaip mes kuriame web aplikacijas. Jau dabar matome, kad kiti framework’ai pradeda eksperimentuoti su panašiomis idėjomis. React komanda dirba su Server Components, kurie šiek tiek juda ta kryptimi. Solid turi savo partial hydration sprendimus.

Bet Qwik yra pirmasis framework’as, kuris pastatė resumability kaip core principą, o ne kaip papildomą optimizaciją. Ir tai daro jį unikalų. Ar jis taps nauju standartu? Sunku pasakyti. Web development istorija pilna framework’ų, kurie atrodė revoliuciniai, bet taip ir nesugebėjo įsitvirtinti.

Tačiau viena aišku – Qwik verčia mus permąstyti, kaip turėtų veikti web aplikacijos. Gal hydration nėra vienintelis būdas. Gal galime geriau. Ir net jei Qwik pats netaptų mainstream, jo idėjos tikrai įtakos ateinančią framework’ų kartą.

Taigi verta sekti, eksperimentuoti, o jei tavo projektas tinka – ir rimtai apsvarstyti naudojimą. Nes kartais naujos idėjos, kurios iš pradžių atrodo keistos, tampa tuo, kaip visi dirba po penkerių metų. O kas žino – gal resumability yra būtent tokia idėja.

Daugiau

OVHcloud Europos debesų sprendimai