Kodėl DOM elementų skaičius iš tiesų svarbus
Kiekvienas frontend kūrėjas bent kartą yra girdėjęs, kad per daug DOM elementų – blogai. Bet koks tas „per daug”? Ir kodėl tai iš viso turėtų rūpėti, jei šiuolaikiniai naršyklės tokie galingi?
Realybė tokia, kad DOM medis yra vienas iš pagrindinių veiksnių, lemiančių svetainės greitį. Kiekvienas elementas turi būti ne tik sukurtas ir atvaizduotas, bet ir nuolat sekamas naršyklės variklių. Kai DOM medis tampa per didelis, pradeda kentėti viskas – nuo pirmo puslapio užsikrovimo iki interakcijų atsako laiko.
Google Lighthouse rekomenduoja laikytis ribos apie 1500 DOM mazgų vienoje svetainėje. Kai šis skaičius viršija 3000-4000, problemos tampa akivaizdžios. Lėtas scrolling’as, vėluojančios animacijos, ilgas Time to Interactive – visa tai dažnai yra per didelio DOM medžio pasekmės.
Kur slypi nematomi elementų valgytojai
Pirmiausia reikia suprasti, kur tie visi elementai atsiranda. Dažniausiai kalti ne patys kūrėjai, o jų naudojami įrankiai ir bibliotekos.
CSS frameworkai yra vienas didžiausių nusikaltėlių. Bootstrap, Foundation ir panašūs sprendimai dažnai reikalauja kelių įdėtų div’ų kiekvienam komponentui. Paprastas mygtukas gali reikalauti 3-4 wrapper’ių, o navigacijos meniu – dešimčių nereikalingų elementų.
JavaScript frameworkai taip pat prisideda. React, Vue ar Angular komponentai dažnai generuoja papildomus wrapper’ius, ypač kai naudojate trečiųjų šalių komponentų bibliotekas. Kiekvienas <Fragment> ar <div>, kuris egzistuoja tik dėl framework’o apribojimų, yra potenciali optimizavimo vieta.
Reklamų ir analitikos skriptai gali įterpti šimtus elementų, apie kuriuos net nežinote. Vienas Google Tag Manager konteineris su keliais tracking skriptais gali pridėti 200-300 DOM elementų. Pridėkite dar Facebook Pixel, Hotjar, ir turite tikrą chaosą.
Praktiniai būdai apkarpyti DOM medį
Gerai, turime problemą. Kaip ją spręsti? Štai keletas konkrečių metodų, kurie veikia realiuose projektuose.
Virtualizacija ilgiems sąrašams – tai būtina, jei rodote bet kokius duomenų sąrašus. Vietoj to, kad renderintumėte visus 1000 produktų ar įrašų, naudokite bibliotekas kaip react-window ar vue-virtual-scroller. Jos renderina tik tai, kas matoma ekrane, plius nedidelį buferį. Rezultatas? Vietoj 1000 elementų turite 20-30.
// Blogas būdas
{products.map(product => (
))}
// Geras būdas su virtualizacija
{({ index, style }) => (
)}
Lazy loading komponentams – ne tik paveikslėliams. Jei turite sudėtingą puslapį su daug sekcijų, užkraukite jas tik tada, kai vartotojas artėja prie jų. React.lazy, Vue async komponentai ar paprastas Intersection Observer API – pasirinkite tai, kas tinka jūsų stack’ui.
CSS vietoj HTML – daugelis vizualinių efektų gali būti pasiekti grynai su CSS, be papildomų elementų. Ikonos? Naudokite ::before ir ::after pseudo-elementus. Dekoratyvūs elementai? SVG kaip background-image. Sudėtingi layout’ai? CSS Grid ir Flexbox dažnai eliminuoja reikalingus wrapper’ius.
Komponentų architektūros persvarstymas
Kartais problema slypi ne tiek technologijose, kiek mūsų mąstymo būde. Daugelis kūrėjų automatiškai kuria naują komponentą kiekvienai mažai funkcionalumo daliai, o kiekvienas komponentas atneša savo wrapper’ius ir struktūrą.
Verta pergalvoti, ar tikrai reikia atskirti visko. Mažas, labai specifinis komponentas gali būti tiesiog funkcija, kuri grąžina JSX ar template string’ą, be papildomų wrapper’ų. Arba keletas susijusių komponentų gali būti sujungti į vieną, jei jie visada naudojami kartu.
Pavyzdžiui, vietoj:
Galite turėti:
Turinys
Vidinė implementacija gali būti tokia pati lanksti, bet DOM medis bus žymiai mažesnis.
Conditional rendering ir jo pavojai
Conditional rendering yra puikus dalykas, bet jį reikia naudoti protingai. Dažnai matau kodą, kur elementai slepiami su display: none ar visibility: hidden, bet lieka DOM medyje. Tai visiškai nepadeda mažinti DOM elementų skaičiaus.
Tikras conditional rendering turi visiškai pašalinti elementus iš DOM:
// Blogai - elementas lieka DOM
// Gerai - elemento nėra DOM
{isVisible && (
)}
Bet čia yra niuansas. Jei elementas dažnai keičiasi tarp visible/hidden būsenų, nuolatinis jo kūrimas ir naikinimas gali būti brangesnis nei palikimas DOM su display: none. Kaip visada, reikia balanso ir testavimo su konkrečiu use case.
Trečiųjų šalių skriptų kontrolė
Čia tampa sudėtinga, nes dažnai neturite pilnos kontrolės. Bet yra būdų sumažinti žalą.
Lazy load visus trečiųjų šalių skriptus. Google Analytics, Facebook Pixel, chat widget’ai – visi jie gali palaukti, kol pagrindinis turinys užsikrauna. Naudokite requestIdleCallback arba paprastą timeout’ą, kad atidėtumėte jų inicializaciją.
Facade pattern veikia puikiai su sunkiais widget’ais. Vietoj to, kad iš karto įkeltumėte YouTube video player’į ar Google Maps, parodykite lengvą placeholder’į su preview paveikslėliu. Tikrasis widget’as užsikrauna tik kai vartotojas paspaudžia.
Kai vartotojas paspaudžia play, JavaScript dinamiškai sukuria iframe su tikruoju YouTube player’iu. Sutaupote šimtus DOM elementų ir daug kilobaitu JavaScript kodo.
Debugging ir matavimo įrankiai
Negalite optimizuoti to, ko nematote. Laimei, yra puikių įrankių DOM elementų analizei.
Chrome DevTools turi puikią Performance tab’ą, kur galite matyti ne tik kiek elementų turite, bet ir kiek laiko užtrunka jų rendering’as. Console’ėje galite greitai patikrinti:
document.querySelectorAll('*').length
Tai parodys bendrą elementų skaičių. Bet dar naudingiau yra rasti, kurie komponentai ar sekcijos yra „sunkiausi”:
// Rasti elementus su daugiausiai vaikų
Array.from(document.querySelectorAll('*'))
.map(el => ({ el, count: el.querySelectorAll('*').length }))
.sort((a, b) => b.count - a.count)
.slice(0, 10)
Lighthouse automatiškai įspės, jei DOM medis per didelis. Bet dar svarbiau – jis parodys, kaip tai veikia kitus metrikų rodiklius. Dažnai DOM optimizacija pagerina ne tik vieną, bet kelis performance rodiklius vienu metu.
React DevTools Profiler (ar analogiški įrankiai kitiems framework’ams) leidžia matyti, kurie komponentai renderina daugiausiai elementų ir kaip dažnai jie re-renderinami. Kartais problema ne tiek elementų skaičiuje, kiek dažnuose re-render’uose.
Kai optimizacija tampa per daug
Turiu pasakyti svarbų dalyką – ne visada verta optimizuoti iki kraštutinumų. Jei jūsų svetainė turi 2000 DOM elementų ir veikia sklandžiai, galbūt nereikia nieko keisti. Optimizacija turi prasmę, kai:
– Lighthouse ar kiti įrankiai rodo konkrečias problemas
– Vartotojai skundžiasi lėtu veikimu
– Matote lėtą veikimą žemesnės klasės įrenginiuose
– Planuojate pridėti dar daugiau funkcionalumo
Kartais per agresyvi optimizacija gali pakenkti kodo skaitomumui ir palaikomumui. Virtualizuotas sąrašas yra sudėtingesnis nei paprastas map. Lazy loading prideda papildomą kompleksiškumą. Visada sverskite privalumus ir trūkumus.
Ir nepamirškite, kad DOM elementų skaičius yra tik vienas iš daugelio performance faktorių. Jei turite 5MB JavaScript bundle’ą, 1000 DOM elementų optimizacija neišspręs pagrindinės problemos.
Realūs rezultatai ir ko tikėtis
Kai teisingai optimizuojate DOM, rezultatai gali būti įspūdingi. Viename projekte, kurį optimizavau, sumažinome DOM elementus nuo 4200 iki 1800. Rezultatai:
– Time to Interactive sumažėjo 40%
– Scrolling FPS padidėjo nuo ~45 iki stabilių 60
– Mobile Lighthouse score pakilo nuo 65 iki 88
– Vartotojų skundų dėl lėtumo sumažėjo praktiškai iki nulio
Bet tai neįvyko per naktį. Procesas užtruko apie dvi savaites: savaitę analizei ir planavimui, savaitę implementacijai ir testavimui. Svarbiausia buvo sisteminis požiūris – ne tik vienkartinė optimizacija, bet ir procesų pakeitimas, kad problema nesikartotų.
Įdiegėme automatinį Lighthouse testą CI/CD pipeline’e, kuris įspėja, jei DOM elementų skaičius viršija 2000. Tai padeda išlaikyti rezultatus ilgalaikėje perspektyvoje.
Taip pat svarbu suprasti, kad skirtingi puslapiai gali turėti skirtingus limitus. Landing page su 500 elementų yra puiku. Admin dashboard su 2500 elementų gali būti priimtinas, jei funkcionalumas to reikalauja. Kontekstas visada svarbu.
Galiausiai, DOM optimizacija yra ne vienkartinis projektas, o nuolatinis procesas. Kiekvienas naujas feature, kiekviena nauja biblioteka gali pridėti elementų. Reguliarus performance auditas turėtų būti jūsų workflow dalis, kaip ir code review ar testing. Kai tai tampa įpročiu, o ne išimtimi, jūsų svetainės lieka greitos ir vartotojams malonios naudoti.

