Zamjene CSS-a u JS-u

Fotograf Artem Bali

Nedavno sam napisao pregled više razine CSS-a u JS-u, uglavnom govoreći o problemima koje ovaj pristup pokušava riješiti. Autori knjižnice rijetko ulažu vrijeme za opisivanje kompromisa svog rješenja. Ponekad je to zato što su previše pristrani, a ponekad jednostavno ne znaju kako korisnici primjenjuju alat. Ovo je pokušaj da se opišu dosadašnji kompromisi. Mislim da je važno spomenuti da sam autor JSS-a, pa bi me trebalo smatrati pristranim.

Društveni utjecaj

Postoji sloj ljudi koji rade na web platformi i ne znaju nikakav JavaScript. Ti ljudi dobivaju plaću za pisanje HTML-a i CSS-a. CSS-in-JS napravio je ogroman utjecaj na tijek rada programera. Doista transformativna promjena se nikad ne može postići bez nekih ljudi iza sebe. Ne znam mora li CSS-u-JS biti jedini način, ali masovno usvajanje je jasan znak problema s korištenjem CSS-a u modernim aplikacijama.

Veliki dio problema je naša nesposobnost da točno komuniciramo o slučajevima gdje CSS-in-JS svijetli i kako ga pravilno koristiti za zadatak. Mnogi ljubitelji CSS-a u JS-u bili su uspješni u promociji tehnologije, ali nisu mnogi kritičari govorili o kompromisima na konstruktivan način, ne uzimajući jeftine promjene u alatima. Kao rezultat toga, mnoge iskaze smo ostavili skrivene i nismo se potrudili pružiti objašnjenje i otklone.

CSS-in-JS je pokušaj složenijih slučajeva upotrebe lakši za obradu, tako da ga nemojte gurati tamo gdje nije potrebno!

Trošak rada

Kad se CSS generira iz JavaScripta tijekom runtimea, u pregledniku postoji svojstveni režijski iznos. Rukovanje radnim vremenom varira od knjižnice do knjižnice. Ovo je dobro općenito mjerilo, ali obavezno napravite vlastite testove. Glavne razlike tijekom vremena izvođenja pojavljuju se ovisno o potrebi potpunog raščlanjivanja nizova predložaka, količine optimizacija, detalja implementacije dinamičkih stilova, troškova algoritma raspršivanja i integracije okvira. *

Osim mogućeg vremena trajanja, potrebno je razmotriti 4 različite strategije grupiranja, jer neke CSS-u-JS knjižnice podržavaju više strategija i na korisniku je da ih primijeni. *

Strategija 1: Samo generacija vremena rada

Runtime CSS generacija je tehnika koja generira CSS niz u JavaScript-u, a zatim ubrizgava taj niz pomoću oznake stila u dokument. Ova tehnika proizvodi tablicu stila, a ne inline stilove.

Kombinacija vremena izvođenja je nemogućnost pružanja stiliziranog sadržaja u ranoj fazi, jer se dokument počinje učitavati. Ovaj pristup obično odgovara aplikacijama bez sadržaja koji bi mogli biti korisni odmah. Obično takve aplikacije zahtijevaju interakcije korisnika prije nego što zaista mogu postati korisne. Često takve aplikacije rade sa sadržajem koji je toliko dinamičan da postaje zastario čim ga učitate, pa morate na početku uspostaviti cjevovod za ažuriranje, na primjer, Twitter. Uz to, kada se korisnik prijavi, nema potrebe za pružanjem HTML-a za SEO.

Ako interakcija zahtijeva JavaScript, paket se mora učitati prije nego što je aplikacija spremna. Na primjer, možete prikazati sadržaj zadanog kanala prilikom učitavanja Slack u dokumentu, ali vjerovatno je da će korisnik odmah nakon toga željeti promijeniti kanal. Dakle, ako ste učitali početne sadržaje samo da biste ih odmah bacili.

Uočena učinkovitost takvih aplikacija može se poboljšati pomoću rezerviranih mjesta i drugih trikova kako bi se aplikacija osjećala trenutačnije nego što zapravo jest. Takve su aplikacije ionako obično teške, pa neće biti korisne brzo kao članak.

Strategija 2: Izrada vremena izvršavanja s kritičnim CSS-om

Kritični CSS je minimalna količina CSS-a koja je potrebna za stiliziranje stranice u početnom stanju. Prikazuje se upotrebom oznake stila u glavi dokumenta. Ova se tehnika široko koristi sa i bez CSS-a u JS-u. U oba slučaja vjerojatno ćete dvostruko učitati CSS pravila, jednom kao dio kritičnog CSS-a i jednom kao dio paketa JavaScript ili CSS. Veličina kritičkog CSS-a može biti poprilično velika, ovisno o količini sadržaja. Dokument se obično ne može keširati.

Bez kritičnog CSS-a, statička aplikacija s jednom stranicom koja sadrži veliku količinu sadržaja s vremenom izvođenja CSS-u-JS morat će prikazati mjesta umjesto sadržaja. To je loše jer bi korisniku moglo biti korisno puno ranije, poboljšavajući dostupnost na niskobudžetnim uređajima i za niskopojasne veze.

S kritičnim CSS-om, generiranje vremena CSS-a moguće je obaviti u kasnijoj fazi, bez blokiranja korisničkog sučelja u početnoj fazi. No upozorite, na mobilnim uređajima niže klase, stari oko 5 godina, CSS generacija iz JavaScripta može negativno utjecati na performanse. To snažno ovisi o količini generiranog CSS-a i knjižnici koja se koristi, tako da ih nije moguće generalizirati.

Zamjena ove strategije trošak je vađenja kritičnog CSS-a i trošak generacije CSS-a za vrijeme izvođenja.

Strategija 3: Samo izdvajanje vremena izgradnje

Ova je strategija zadana na webu bez CSS-a u JS-u. Neke CSS-u-JS biblioteke omogućuju vam izdvajanje statičkog CSS-a u vrijeme izrade. * U ovom slučaju, nije potrebno prekoračenje vremena izvršavanja, CSS se prikazuje na stranici pomoću oznake veze. Trošak CSS generacije plaća se jednom prije vremena.

Ovdje su dva glavna pregovora:

  1. Ne možete koristiti neke dinamičke API-je CSS-in-JS ponude za vrijeme izvođenja jer nemate pristup državi. Često još uvijek ne možete koristiti CSS prilagođena svojstva jer nisu podržana u svakom pregledniku i ne mogu ih priroda polifitirati u vrijeme izrade. U ovom slučaju morat ćete zaobići dinamična tematska obrada i styling temeljen na državi. *
  2. Bez kritičnog CSS-a i s praznom predmemorijom blokirat ćete prvu boju dok se vaš CSS paket ne učita. Element veze u glavi dokumenta blokira prikazivanje HTML-a.
  3. Neodređena specifičnost s dijeljenjem skupa na temelju stranice u aplikacijama za jednu stranicu. *

Strategija 4: Izvlačenje u vremenu izgradnje s kritičnim CSS-om

Ova strategija također nije jedinstvena za CSS-u-JS. Potpuna statička ekstrakcija s kritičnim CSS-om pruža najbolje performanse u radu sa statičnijom aplikacijom. Ovaj pristup još uvijek ima gore spomenute kompromise statičkog CSS-a, osim što se oznaka blokade veze može premjestiti na dno dokumenta.

Postoje 4 glavne strategije prikazivanja CSS-a. Samo 2 od njih specifična su za CSS-in-JS i nijedan se ne odnosi na sve knjižnice.

Pristupačnost

CSS-in-JS može smanjiti pristupačnost ako se koristi na pogrešan način. To će se dogoditi kada se web lokacija s velikim statičkim sadržajem implementira bez Critical CSS ekstrakcije, tako da HTML ne može biti obojan prije učitavanja i procjene paketa JavaScript. To se može dogoditi i kad se ogromna CSS datoteka generira pomoću oznake za blokiranje veze u glavi dokumenta, što je najpopularniji trenutni problem s tradicionalnim ugradnjom, a nije specifičan za CSS u JS.

Programeri trebaju preuzeti odgovornost za pristupačnost. Još uvijek postoji snažna pogrešna ideja da je nestabilna internetska veza problem ekonomski slabih zemalja. Skloni smo zaboraviti da imamo problema sa povezivanjem svaki dan kada uđemo u podzemni željeznički sustav ili veliku zgradu. Stabilna mobilna veza bez kabela je mit. Nije lako imati stabilnu WiFi vezu, na primjer, 2,4 GHz WI-FI mreža može dobiti smetnje u mikrovalnoj pećnici!

Trošak kritičnog CSS-a s prikazom na strani poslužitelja

Da bismo dobili kritičnu CSS ekstrakciju za CSS-u-JS, potreban nam je SSR. SSR je proces generiranja završnog HTML-a za dano stanje aplikacije na poslužitelju. U stvari, to može biti prilično složen i skup proces. Zahtijeva određenu količinu CPU ciklusa na poslužitelju za svaki HTTP zahtjev.

CSS-in-JS obično koristi činjenicu da je zakačen u cjevovod za prikaz HTML-a. * Zna se što je HTML učinio i CSS-u je potreban da bi mogao proizvesti apsolutni minimalni iznos od njega. Kritični CSS dodaje dodatni režijski trošak HTML prikazu na poslužitelju jer CSS također mora biti sastavljen u konačni CSS niz. U nekim je situacijama teško ili čak nemoguće keširati na poslužitelju.

Crni okvir s prikazom

Morate biti svjesni kako CSS-in-JS biblioteka koju koristite prikazuje vaš CSS. Na primjer, ljudi često nisu svjesni kako Styled Components i Emotion implementiraju dinamičke stilove. Dinamički stilovi sintaksa je koja omogućuje upotrebu JavaScript funkcija unutar vaše deklaracije stilova. Te funkcije prihvaćaju rekvizite i vraćaju CSS blok.

Kako bi se održala dosljedna specifičnost redoslijeda izvora, obje navedene knjižnice generiraju novo CSS pravilo ako sadrži dinamičku deklaraciju i nadogradnju komponente novim rekvizitima. Kako bih demonstrirao što mislim, stvorio sam ovu kutiju s pijeskom. U JSS-u smo odlučili poduzeti drugačiji tradeoff, koji nam omogućava ažuriranje dinamičkih svojstava bez generiranja novih CSS pravila. *

Strma krivulja učenja

Za ljude koji su upoznati s CSS-om, ali novi su u JavaScript-u, početna količina posla za ubrzanje CSS-a u JS-u može biti prilično velika.

Ne morate biti profesionalni programer JavaScripta za upisivanje CSS-a u JS-u sve do trenutka kada se uključuje složena logika. Složenost stiliranja ne možemo generalizirati, jer ona zapravo ovisi o slučaju uporabe. U slučajevima kada CSS-u-JS postane složen, vjerovatno je da bi primjena s CSS-om vanilije bila još složenija.

Za osnovni CSS-in-JS styling treba znati kako deklarirati varijable, kako koristiti nizove predloška i interpolirati JavaScript vrijednosti. Ako se koristi notacija objekata, treba znati kako raditi s JavaScript objektima i sintaksom specifičnom za biblioteku. Ako je uključen dinamički stil, treba znati kako koristiti JavaScript funkcije i uvjete.

Sve u svemu, postoji krivulja učenja, ne možemo je poreći. Ta krivulja učenja obično nije mnogo veća od učenja Sass-a. Zapravo sam stvorio ovaj tečaj jajolika da to demonstriram.

Nema interoperabilnosti

Većina CSS-u-JS-a nije interoperabilna. To znači da se stilovi napisani pomoću jedne biblioteke ne mogu prikazati pomoću druge knjižnice. To praktično znači da ne možete lako prebaciti čitavu aplikaciju s jedne na drugu implementaciju. To također znači da ne možete lako dijeliti svoj UI na NPM bez unošenja svoje CSS-u-JS biblioteke po izboru u potrošački paket ako nemate statičku ekstrakciju za CSS u ugrađenom vremenu.

Počeli smo raditi na ISTF formatu koji bi trebao riješiti ovaj problem, ali nažalost još nismo imali vremena da ga vratimo u stanje spremno za proizvodnju. *

Mislim da je dijeljenje okvira agnostičkih komponenata korisničkog sučelja za višekratnu upotrebu u javnom domenu i dalje općenito teško rješiv problem.

Sigurnosni rizici

Moguće je uvesti propuste sigurnosti s CSS-om u JS-u. Kao i kod svih aplikacija na strani klijenta, uvijek morate izbjeći unos korisnika prije nego što ga pokrenete.

Ovaj će vam članak pružiti više uvida i nekoliko neuglednih primjera.

Nečitljiva imena klasa

Neki i dalje misle da je važno da na webu zadržimo smislena čitljiva imena klasa. Trenutno mnoge CSS-u-JS knjižnice pružaju smislena imena klase na temelju naziva deklaracije ili naziva komponente u razvojnom načinu. Neki od njih čak omogućuju prilagođavanje funkcije generatora naziva klase.

Međutim, u načinu proizvodnje većina ih generira kraća imena za manji korisni teret. Ovo je kompromis koji korisnik knjižnice mora napraviti i prilagoditi knjižnicu ako je potrebno.

Zaključak

Kompromiti postoje i vjerojatno ih nisam ni spomenuo. Ali većina ih se ne primjenjuje na sve CSS-ove u JS-u. Ovise o tome koju biblioteku koristite i kako je koristite.

* Za objašnjavanje ove rečenice potreban je posvećeni članak. Javite mi na Twitteru (@ oleg008) o kojem biste željeli pročitati više.