Sustabdykite skriptų kaupimąsi, kol svetainė netapo lėtu mechaniniu monstru
Svetainės skriptų tikrintuvas sukurtas problemai, kurią modernios interneto svetainės puoselėja su beveik religiniu atsidavimu: JavaScript prasideda kaip praktiškas ir kuklus pagalbininkas, netrukus įgyja kelis draugus, pasikviečia būrį trečiųjų šalių pusbrolių, priglaudžia analitiką, žymų tvarkykles (Google Tag Manager), valdiklius (widgets), sutikimo su slapukais rėmelius, A/B testavimo logiką, klientų aptarnavimo pokalbių langus, reklamų pikselius, personalizacijos sluoksnius ir dekoratyvinę animacinę prabangą, kol galiausiai tyliai virsta nepakeliama našta. Tuo metu puslapis vis dar „veikia“, o tai yra mėgstamiausias interneto vadybininkų pasiteisinimas. Tačiau veikti – nereiškia būti protingai suprojektuotam. Pirkinių vežimėlis su sulankstytu ratuku irgi rieda į priekį, tačiau niekas jo nevadina transporto šedevru.
Įklijuokite viešą URL adresą į šį įrankį ir jis atliks matomo skriptų sluoksnio auditą. Jis patikrina, kiek yra skriptų žymų, kiek jų yra išorinių, kiek vidinių (inline), kokį realų JavaScript svorį tempia puslapis, kiek skriptų priklauso trečiosioms šalims, ar head skriptai yra sinchroniniai (blokuojantys naršyklės DOM medžio kūrimą), ir ar puslapis rodo bent kokią krovimo discipliną naudojant async, defer ar module atributus. Paprasčiau tariant: ar jūsų puslapis neneša tokios skriptų naštos, nuo kurios paprasti telefonai ir nešiojamieji kompiuteriai pradeda dusti?
Ką jūs įvedate ir ką įrankis realiai matuoja
Jūs įvedate puslapio URL. Tikrintuvas atsisiunčia HTML kodą, ištraukia visas <script> žymas, išsprendžia išorinių skriptų URL adresus ir, kur įmanoma, patikrina išorinius resursus dėl jų dydžio ir antraščių. Tada sugeneruojamas rizikos balas, paremtas bendru skriptų kiekiu, išmatuotu išoriniu JavaScript svoriu (baitais), vidinio (inline) skripto apimtimi, trečiųjų šalių apkrova ir sinchroniniu head skriptų elgesiu. Rezultatas nėra abstraktus teorinis samprotavimas – tai griežta inžinerinė ataskaita, parodanti, ar kodo bazė primena apgalvotą architektūrą, ar tiesiog nekontroliuojamą skaitmeninių šiukšlių kaupimąsi (lot. incrementum per ruinas).
Šis skirtumas yra esminis. Nė viena svetainė netampa perpildyta skriptais todėl, kad koks nors programuotojas vieną rytą prabudo su svajone apie lėtą programinį kodą. Tai įvyksta per ilgalaikes nuosėdas: vienas fragmentas analitikai, vienas valdiklis socialiniams tinklams, vienas pikselis pakartotinei rinkodarai, vienas vaizdo įrašų leistuvo skriptas, vienas pokalbių botas, keli „lengvi“ eksperimentai ir galiausiai – didžiulė slapukų valdymo platforma (CMP), skirta paaiškinti visų šių skriptų sukeltas pasekmes. Puslapis pamažu virsta nesuderinamų priklausomybių chaosu.
Kodėl JavaScript svoris svarbus realiems įrenginiams
Stalinių kompiuterių programuotojai ir naujausi flagmanai sukuria pavojingą iliuziją: puslapis atrodo žaibiškas galingame „MacBook Pro“ ar „Intel i9“ kompiuteryje, prijungtame prie greito biuro šviesolaidžio. Tačiau realybė prasideda tada, kai svetainę atidaro vartotojas su 150 eurų kainuojančiu „Android“ telefonu, važiuodamas traukiniu su trūkinėjančiu 4G ryšiu, įjungtu baterijos taupymo režimu ir kaistančiu procesoriumi.
Skirtingai nuo paveikslėlių (kurie tėra pasyvūs baitai ekrane), JavaScript reikalauja milžiniškų CPU resursų. Parsiuntus skriptą, naršyklės variklis (pvz., „V8“) privalo jį išanalizuoti (parse), paversti abstrakčiu sintaksės medžiu (AST), sukompiliuoti į baitkodą, optimizuoti JIT (Just-In-Time) kompiliatoriumi ir įvykdyti pagrindinėje naršyklės gijoje (Main Thread). Kol vyksta šis procesas, puslapis „užšąla“ – vartotojas bando spausti meniu ar slinkti tekstą, o sąsaja nereaguoja.
Event Loop ir „Long Tasks“ (ilgųjų užduočių) problema
Naršyklės dirba vienos gijos principu (angl. Single-Threaded Event Loop). Jei bet kuri JavaScript funkcija vykdoma ilgiau nei 50 milisekundžių, „Google Chrome“ ją klasifikuoja kaip Long Task. Tokios užduotys akimirksniu blokuoja kadrų atvaizdavimą (Frame Rate krenta nuo 60 fps iki 10 fps) ir vartotojo įvesties apdorojimą. Kai puslapyje sukasi keli dešimčių kilobaitų sekimo skriptai, pagrindinė gija nuolat uždususi, o vartotojas patiria nemalonų sąsajos trūkčiojimą (angl. jank).
Google Tag Manager: nematomas Trojos arklys
Daugelis inžinierių didžiuojasi švariu savo puslapio HTML kodu, kuriame tėra viena vienintelė gtm.js žyma. Tačiau tai tėra iliuzija: Google Tag Manager veikia kaip Trojos arklys, per kurį rinkodaros skyrius be kodo peržiūros (Code Review) ir be testavimo gali įkelti dešimtis trečiųjų šalių sekiklių, reklamos pikselių ir pelių judėjimo įrašymo modulių. Šis įrankis padeda atskleisti tikrąjį puslapio svorį nepriklausomai nuo to, ar skriptai įkelti tiesiogiai, ar per konteinerius.
Micro-frontends ir karkasų dubliavimo spąstai
Dar viena moderni tendencija, sukelianti JavaScript sprogimą – vadinamoji „Micro-frontend“ architektūra. Kai skirtingos komandos tame pačiame puslapyje naudoja skirtingas karkasų versijas („React 17“, „React 18“, „Vue 3“), vartotojo naršyklė priversta parsisiųsti ir inicializuoti kelis karkasus vienu metu. Tai yra inžinerinis nihilizmas, kurio pasekmes apmoka lankytojas savo telefono baterija.
Hidracijos kaina: „React“, „Vue“ ir „Next.js“ spąstai
Moderniuose karkasuose taikoma serverio pusės generacija (SSR) sukuria gražų HTML kodą, tačiau po to seka vadinamasis hidracijos (angl. hydration) procesas. Naršyklė privalo atsisiųsti visą karkaso biblioteką, perkurti virtualų DOM medį atmintyje ir pririšti visus įvykių klausytojus (Event Listeners) prie esamų HTML elementų. Jei puslapis yra perkrautas komponentais, hidracija gali užtrukti kelias sekundes, kurių metu puslapis atrodo užkrautas, tačiau yra visiškai miręs ir nereaguoja į paspaudimus.
Wirth'o dėsnis ir programinės įrangos nutukimas
Dar 1995 metais kompiuterių mokslo pionierius Niklaus Wirth suformulavo garsųjį dėsnį: „Programinė įranga lėtėja greičiau, nei aparatinė įranga greitėja“. Šiandien šis dėsnis akivaizdžiausiai pasireiškia žiniatinklio kūrime: nors šiuolaikiniai telefonai turi aštuonių branduolių procesorius, jie vargsta atverdami paprastą naujienų portalą vien todėl, kad puslapis tempia 5 megabaitus JavaScript bibliotekų, skirtų vos keliems mygtukams animuoti.
Suspaudimo iliuzija: Gzip ir Brotli spąstai
Daugelis programuotojų pasikliauja faktu, kad jų JavaScript failas per tinklą perduodamas suspaustas su „Gzip“ arba „Brotli“ algoritmu. Pavyzdžiui, 60 KB suspaustas failas atrodo nedidelis tinklo požiūriu. Tačiau išpakuotas naršyklės atmintyje jis virsta 350 KB neapdoroto teksto, kurį mobilusis procesorius privalo baitas po baito išanalizuoti ir įvykdyti. Suspaudimas taupo tinklo pralaidumą, tačiau nesumažina CPU atliekamo skaičiavimo darbo.
Skriptų skaičius: pirmasis front-end prabangos simptomas
Didelis skriptų žymų skaičius automatiškai nepasmerkia puslapio, tačiau tai yra pats ankstyviausias matomas ligos simptomas. Dvidešimt skriptų dar galima logiškai paaiškinti. Trisdešimt – jau dvelkia vadybiniais kompromisais. O puslapis, turintis 50 ar 80 atskirų skriptų, jau nebevykdo jokio aiškaus inžinerinio plano: jis tiesiog organizuoja tarpusavyje nesusijusių tiekėjų viršūnių susitikimą vartotojo naršyklėje.
Kiekviena skripto žyma reiškia atskirą tinklo užklausą, kodo vykdymo giją, talpyklos riziką ir klaidų tikimybę. Net jei atskiri failai yra santykinai nedideli, jų bendra sankaupa sukuria trintį, kuri paralyžiuoja puslapio atvėrimo greitį.
Trečiųjų šalių saugumo rizikos ir CSP
Nekontroliuojami trečiųjų šalių skriptai kelia ne tik našumo, bet ir kritines saugumo rizikas. Vadinamųjų Magecart atakų metu užkrėstas išorinis skriptas gali slapta perimti pirkėjų banko kortelių duomenis tiesiai iš atsiskaitymo formų. Todėl profesionalūs puslapiai privalo naudoti CSP (Content Security Policy) antraštes su griežtomis script-src taisyklėmis.
Sinchroniniai „head“ skriptai ir krovimo atributai
Kai naršyklė HTML <head> bloke sutinka standartinį <script src="..."> be jokių atributų, visas puslapio atvaizdavimas sustabdomas. Naršyklė laukia, kol failas bus atsiųstas ir įvykdytas, ir tik tada tęsia teksto ir mygtukų rodymą. Šią problemą sprendžia modernūs atributai:
defer: skriptas siunčiamas fone lygiagrečiai su HTML analize, o vykdomas tik pilnai suformavus DOM medį. Tai idealus pasirinkimas daugumai puslapio skriptų.async: skriptas siunčiamas fone ir įvykdomas iškart, kai tik atsisiunčia (netvarkinga seka). Tinka visiškai nepriklausomiems analitikos skriptams.type="module": modernus ES modulių standartas, kuris pagal nutylėjimą veikia atidėtu (defer) režimu.
Vidinis (inline) JavaScript ir buitinės netvarkos problema
Vidinis JavaScript kodas turi savo vietą: trumpi konfigūracijos kintamieji ar kritiniai pradiniai stiliai gali būti naudingi. Tačiau kai HTML dokumentas užpildomas šimtais eilučių vidinio kodo, prarandamas naršyklės talpyklos (caching) efektyvumas – vartotojas kaskart iš naujo siunčiasi tą patį programinį kodą su kiekvienu atverstu puslapiu.
Core Web Vitals: INP, LCP ir TBT metrikos
Nuo 2024 m. „Google“ pakeitė FID metriką nauju standartu – INP (Interaction to Next Paint). INP matuoja, kaip greitai svetainė vizualiai sureaguoja į vartotojo paspaudimą per visą apsilankymo laikotarpį. Perteklinis JavaScript, blokuojantis pagrindinę giją (Total Blocking Time – TBT), yra pagrindinė prasto INP balo priežastis, tiesiogiai smukdanti svetainės pozicijas „Google“ paieškoje.
Perteklinis JavaScript yra vadybos, o ne programavimo klaida
Daugelis prastų našumo rezultatų neteisingai verčiami ant karkasų ar bibliotekų. Tačiau tiesa daug paprastesnė: skriptų perteklius yra vadybinės kontrolės praradimas. Kiekvienas rinkodaros skyriaus prašymas „įdėkime dar vieną pikselį“, kiekvienas greitas eksperimentas, kiekvienas nepašalintas praėjusių metų A/B testo fragmentas kaupiasi sluoksniais. Šis įrankis paverčia nematomą svorį konkrečiais skaičiais ir faktais, leidžiančiais atlikti argumentuotą svetainės valymą.
Penkių žingsnių svetainės skriptų optimizavimo planas
- Atlikite skriptų auditą: pašalinkite visus nenaudojamus analitikos ir rinkodaros pikselius.
- Perkelkite kodą iš
<head>: naudokitedeferatributą arba perkelkite skriptus į puslapio pabaigą prieš pat</body>. - Taikykite kodo skaidymą (Code Splitting): kraukite tik tą JavaScript, kuris reikalingas konkrečiam puslapiui, naudodami dinaminius
import(). - Optimizuokite vidinį (inline) kodą: didelius logikos blokus iškelkite į išorinius, naršyklės talpykloje (cache) išsaugotus failus.
- Rinkitės natyvų kodą (Vanilla JS): atsisakykite sunkių bibliotekų („jQuery“, „Moment.js“, „Lodash“) modernių naršyklės standartų naudai.