SolidJS reactive framework: fine-grained reactivity

Kas tas SolidJS ir kodėl verta juo domėtis

Jei sekate frontend karkasų pasaulį, tikriausiai pastebėjote, kad kas keleri metai atsiranda naujas „žvaigždė”, žadanti išspręsti visas problemas. React’as, Vue, Svelte – visi jie turi savo fanų armiją ir konkrečius privalumus. Bet štai pastaraisiais metais vis dažniau pradėjau girdėti apie SolidJS, ir ne be reikalo.

SolidJS – tai reaktyvus JavaScript karkasas, kurį sukūrė Ryan Carniato. Pirmą kartą išvydęs šviesos 2018 metais, jis iš pradžių buvo tik eksperimentas, bet dabar tai rimtas žaidėjas su įspūdingais našumo rodikliais. Kas jį išskiria? Vienas žodis: fine-grained reactivity.

Skirtingai nei React’as, kuris perkrauna komponentus kaip bepročius, SolidJS atnaujina tik tai, kas tikrai pasikeitė. Ne visą komponentą, ne virtualų DOM medį – tik tą konkretų teksto mazgą ar atributą, kuriam reikia pasikeisti. Tai kaip chirurginė operacija, o ne renovacija su kūju.

Kaip veikia fine-grained reactivity

Gerai, tai dabar įsigilinkime į technines detales. Fine-grained reactivity reiškia, kad reaktyvumo sistema stebi priklausomybes labai smulkiu lygmeniu. Kai kuriate signalą (signal) SolidJS, jis tampa reaktyviu duomenų šaltiniu, o bet koks efektas ar skaičiavimas, kuris jį naudoja, automatiškai užsiregistruoja kaip priklausomybė.

Štai paprastas pavyzdys:

„`javascript
import { createSignal, createEffect } from ‘solid-js’;

const [count, setCount] = createSignal(0);

createEffect(() => {
console.log(‘Count yra:’, count());
});

setCount(5); // Konsolėje pamatysite: „Count yra: 5”
„`

Kas čia vyksta? Kai `createEffect` funkcija vykdoma pirmą kartą, SolidJS stebi, kokius signalus ji naudoja. Šiuo atveju – `count()`. Kai vėliau iškviečiate `setCount(5)`, sistema tiksliai žino, kad šis konkretus efektas turi būti paleistas iš naujo. Jokio virtualaus DOM palyginimo, jokio komponentų perkrovimo.

Signalai, efektai ir memo – trijulė, kurią turite suprasti

SolidJS reaktyvumo sistema remiasi trimis pagrindiniais primityvais. Supratę juos, suprasite 90% to, kaip veikia visas karkasas.

Signalai (Signals) – tai reaktyvūs duomenų konteineriai. Galvojate apie juos kaip apie kintamuosius su super galiomis. Jie grąžina getter funkciją duomenims gauti ir setter funkciją jiems pakeisti:

„`javascript
const [name, setName] = createSignal(‘Jonas’);
console.log(name()); // „Jonas”
setName(‘Petras’);
„`

Efektai (Effects) – tai funkcijos, kurios automatiškai paleidžiamos, kai pasikeičia bet kuris jų naudojamas signalas. Naudojami šalutiniams efektams – DOM manipuliacijoms, API kvietimams, logavimui:

„`javascript
createEffect(() => {
document.title = `Sveikas, ${name()}!`;
});
„`

Memo – tai kaip computed properties kitose sistemose. Jie kešuoja skaičiavimo rezultatus ir perskaičiuoja tik tada, kai pasikeičia priklausomybės:

„`javascript
const fullName = createMemo(() => `${firstName()} ${lastName()}`);
„`

Skirtumas tarp memo ir efekto: memo grąžina reikšmę ir yra pats reaktyvus šaltinis, kurį gali naudoti kiti efektai ar memo. Efektas nieko negrąžina ir yra reaktyvumo grandinės pabaiga.

Komponentai be komponentų perkrovimo

Čia prasideda tikra magija. React’e, kai pasikeičia state, komponentas ir jo vaikai perkraunami (re-render). Taip, yra optimizacijos kaip `React.memo` ar `useMemo`, bet tai papildomas darbas, kurį turite atlikti.

SolidJS komponentai yra tiesiog funkcijos, kurios vykdomos vieną kartą. Taip, teisingai girdėjote – vieną kartą komponentų inicializavimo metu. Po to veikia tik reaktyvios išraiškos viduje.

„`javascript
function Counter() {
const [count, setCount] = createSignal(0);

console.log(‘Komponentas sukurtas’); // Matote tik vieną kartą

return (

Skaičius: {count()}

);
}
„`

Kai spaudžiate mygtuką, `count` signalas pasikeičia, bet `Counter` funkcija nevykdoma iš naujo. Tik tas `{count()}` teksto mazgas DOM’e atsinaujina. Tai neįtikėtinai efektyvu.

JSX be virtualaus DOM

SolidJS naudoja JSX sintaksę, todėl jei dirbote su React’u, viskas atrodys pažįstama. Bet čia yra esminis skirtumas: SolidJS JSX yra kompiliuojamas į tikrus DOM kvietimus, ne į virtualaus DOM struktūras.

Kai rašote:

„`javascript

{title()}

„`

SolidJS kompiliatorius paverčia tai maždaug į:

„`javascript
const div = document.createElement(‘div’);
div.className = ‘container’;
const h1 = document.createElement(‘h1’);
h1.textContent = title();
div.appendChild(h1);
„`

Ir sukuria reaktyvų efektą, kuris atnaujina tik `h1.textContent`, kai `title()` pasikeičia. Jokio tarpinio sluoksnio, jokio diff algoritmo.

Tai reiškia, kad SolidJS turi React’o kūrėjo patirtį (JSX sintaksė), bet Svelte našumą (kompiliavimas į efektyvų kodą). Geriausi abiejų pasaulių.

Kontrolės srautai ir sąlyginė renderinimas

Viena iš dalykų, kurie gali suklaidinti React’o kūrėjus, yra tai, kaip SolidJS tvarko sąlyginę logiką. Negalite tiesiog naudoti `&&` ar ternary operatorių kaip React’e, nes tai sukurtų naujus efektus kiekvieną kartą.

Vietoj to SolidJS siūlo specialius komponentus:

„`javascript
import { Show, For, Switch, Match } from ‘solid-js’;

function UserProfile(props) {
return (
Kraunasi…

}
>
{(user) => (

{user.name}

{user.email}

)}

);
}
„`

`` komponentas efektyviai tvarko sąlyginį renderinimą. Kai `props.user()` yra falsy, rodomas fallback. Kai tampa truthy, rodomas turinys. Ir tai daroma be viso komponento perkrovimo.

`` komponentas sąrašams:

„`javascript

{(item, index) => (

  • {index() + 1}. {item.name}
  • )}

    „`

    Skirtingai nei `.map()`, `` efektyviai atnaujina tik pasikeitusius elementus, ne visą sąrašą.

    Store ir sudėtingas state valdymas

    Signalai puikiai veikia primityvėms reikšmėms, bet ką daryti su sudėtingais objektais? Čia ateina `createStore`:

    „`javascript
    import { createStore } from ‘solid-js/store’;

    const [state, setState] = createStore({
    user: {
    name: ‘Jonas’,
    age: 30,
    address: {
    city: ‘Vilnius’
    }
    },
    posts: []
    });

    // Galite atnaujinti giliai įdėtus laukus
    setState(‘user’, ‘address’, ‘city’, ‘Kaunas’);

    // Arba naudoti funkciją
    setState(‘user’, ‘age’, age => age + 1);
    „`

    Store objektai yra reaktyvūs visais lygiais. Kai pasiekiate `state.user.name` efekte ar komponente, SolidJS stebi būtent tą kelią. Pakeitus `state.user.address.city`, tik komponentai, naudojantys tą konkretų kelią, bus atnaujinti.

    Tai labai skiriasi nuo React’o, kur paprastai turite klonuoti visą objektą, kad suaktyvintumėte atnaujinimą. SolidJS store leidžia dirbti su duomenimis intuityviai, mutacijos stiliumi, bet išlaikant reaktyvumą.

    Našumas, kuris kalbasi už save

    Teorija teorija, bet kaip SolidJS veikia praktikoje? JS Framework Benchmark rezultatai kalba patys už save – SolidJS nuolat konkuruoja su Vanilla JS ir Svelte už pirmąsias vietas, dažnai lenkdamas React’ą 2-3 kartus.

    Kodėl taip yra? Kelios priežastys:

    Nėra virtualaus DOM overhead – kiekvienas virtualaus DOM palyginimas kainuoja procesorių laiką ir atmintį. SolidJS to tiesiog neturi.

    Tikslūs atnaujinimai – kai React’as gali perkrauti šimtus komponentų dėl vieno state pasikeitimo (net su optimizacijomis), SolidJS atnaujina tik tai, kas pasikeitė.

    Kompiliavimo laikas – daug darbo atliekama kompiliavimo metu, o ne naršyklėje. Jūsų bundle’as yra optimizuotas kodas, ne karkaso abstrakcijos.

    Mažesnis bundle dydis – SolidJS runtime yra apie 7KB gzipped. React’as su ReactDOM – apie 42KB. Tai šešis kartus skirtumas.

    Ar tai reiškia, kad turėtumėte išmesti React’ą ir viską perrašyti SolidJS? Ne būtinai. Bet jei kuriate naują projektą ir našumas yra prioritetas, arba jei jau turite Svelte ar Vue patirties, SolidJS tikrai verta rimto žvilgsnio.

    Kai fine-grained reactivity tampa jūsų supergalia

    Grįžtant prie pradžios – SolidJS nėra tiesiog dar vienas JavaScript karkasas. Tai fundamentaliai kitoks požiūris į reaktyvumą frontend’e. Fine-grained reactivity reiškia, kad jūsų aplikacijos veikia greičiau, naudoja mažiau atminties ir jaučiasi sklandžiau vartotojams.

    Ar yra trūkumų? Žinoma. Ekosistema mažesnė nei React’o, komandoje rasti SolidJS kūrėjų sunkiau, o kai kurios koncepcijos reikalauja paradigmos pasikeitimo, ypač jei esate įpratę prie React’o. Bet karkasas auga, bendruomenė stiprėja, o našumo privalumai yra neginčijami.

    Jei esate smalsus kūrėjas, kuris nori suprasti, kaip reaktyvumas veikia po gaubtu, arba tiesiog ieškote greičiausio būdo kurti interaktyvias aplikacijas – pabandykite SolidJS. Pradėkite su mažu projektu, pajuskite, kaip signalai ir efektai veikia kartu, ir greičiausiai suprasite, kodėl vis daugiau kūrėjų sako, kad tai ateitis.

    O jei vis dar abejojate – tiesiog atidarykite benchmark rezultatus ir pažiūrėkite į tuos žalius stulpelius. Kartais skaičiai kalba garsiau nei bet kokie žodžiai.

    Daugiau

    Istio service mesh Kubernetes klasteriuose