Testiranje dizajn sistema na pravoj stranici: 7 komponenti i 8 nedostataka
Stranici je trebalo sedam od 74 komponente i četiri izuzetka u jednom fajlu. Na telefonu je 91% koda koji se izvršava ostalo neizmijenjeno, a četiri buga prošla su sve provjere.
Naš cross-platform dizajn sistem pokriva Next.js, Vite SPA i React Native. Ima 74 komponente, katalog i sloj provjera zbog kojeg build pada kad se prekrši neka konvencija. Ali ništa od toga ne govori može li se od njega sastaviti prava stranica. Biblioteka komponenti testira se komponentu po komponentu, pa testovi pokrivaju dijelove, a stranicu kao cjelinu nikad.
Naša postojeća marketinška stranica bila je jedan HTML fajl s inline stilovima i malom reaktivnom skriptom. Napravio sam je iznova, samo od onoga što sistem nudi. Cilj mi nije bio da stranica bude ljepša, nego da dobijem spisak: koje su komponente dovoljne za pravi ekran, koja četiri elementa moraju zaobići sistem i koliko košta svaka funkcija koja nedostaje.
Sedam komponenti bilo je dovoljno za cijelu stranicu
Na gotovoj stranici 139 elemenata dolazi iz dizajn sistema:
1Box 632Text 553Link 94Divider 75Icon 26Badge 27Surface 1Za cijelu marketinšku stranicu bilo je dovoljno sedam od 74 komponente sistema.
To je bio prvi koristan nalaz i on ide protiv pretpostavke na kojoj se biblioteka obično gradi. Katalog je bio dovoljno širok za stranicu, a njegova širina nikad nije bila granica.
Četiri izuzetka u jednom fajlu, svaki s razlogom i uslovom za brisanje
Uz tih 139 elemenata stranica na četiri mjesta izlazi iz sistema, a sva četiri mjesta su u jednom fajlu:
- tri
<div style>elementa, za flex-basis ćelija mreže i zaposition: sticky - jedan
styled.a, za skip link
Svaki od njih ima zapisan razlog i uslov pod kojim se može obrisati. Po tome se izuzetak razlikuje od curenja: izuzetak se može prebrojati, objasniti i na kraju ukloniti, a curenje se širi po kodu.
Osam stvari koje sistem nije mogao uraditi
Ova tabela je spisak zbog kojeg sam sve ovo i radio.
| Traženo | Zašto ne | Šta je stranica dobila umjesto toga |
|---|---|---|
| Naslov od 48px | display je 36px; korak 5xl postoji u skali, ali ga nijedna varijanta ne koristi | manji naslov |
| Link koji izgleda kao dugme | Button nema to; token akcentne pozadine nije pune jačine; osnovni recept fiksira radijus | bijela pilula umjesto akcentne boje |
| Kurziv | font-style ne postoji nigdje u paketima | navodi ograničenja bez kurziva |
| Responzivna mreža | Box nema basis ni min-width, a min-width: 0 je hardkodiran | jedan <div style> po ćeliji |
position: sticky | Yoga nema sticky, pa ga tip pozicije ne uključuje | jedan <div style> oko trake |
| Skip link | komponenta za vizuelno skriveni tekst prima text prop, bez djece i bez stanja fokusa | jedan styled.a |
| Isprekidan ili jednostrani okvir | border prop je boolean, jedna boja, sve četiri strane | tonirana pilula umjesto isprekidanog okvira |
| Landmark uloge | tip uloge nema main ni contentinfo, jer ih React Native nema | goli <main> i <footer> |
Dvije od tih stvari već su bile planirane kao budući posao: veličina fonta za hero i link koji izgleda kao dugme. Kad sam napravio stranicu, obje su prestale biti pretpostavka i postale izmjeren nalaz sa svojom cijenom.
Zbog toga se ovo uopšte isplati raditi. Backlog sastavljen na sastanku sadrži ono što je neko zamislio da mu treba. Kad napravite pravi ekran, dobijete spisak onoga što vas je zaustavilo, redom i s dokazom za svaku stavku.
Od koda koji se izvršava na telefonu, 91% je ostalo neizmijenjeno
Prva brojka za mobilni koju sam objavio, u tekstu koji poredi tri verzije ove stranice, bila je samo razvrstavanje koda, napravljeno prije nego što je išta pokrenuto na uređaju. U međuvremenu je stranica portovana i pokrenuta na telefonu u Expo Go, a brojke iz porta su bolje od te procjene.
| linija | fajlova | |
|---|---|---|
| Dijeljeno: jedan fajl crta i web i telefon | 975 | 4 |
| Razdvojeno: web grana i nativni blizanac | 162 | 2 |
| Samo web: okvir stranice, rutiranje frameworka | 582 | 4 |
| Samo nativno: ljuska | 47 | 1 |
Na telefonu se izvršava 1.077 linija koda, a od toga su 102 linije napisane za mobilni: 55 linija nativnog blizanca i 47 linija ljuske. Dakle, 91% onoga što telefon crta ponovo je upotrijebljeno bez ijedne izmjene.
Šta znači 91% u poređenju s ranijih 62%
Prema ranijoj procjeni, na mobilnom se moglo upotrijebiti 62% koda. To je bilo razvrstavanje cijelog sajta, zajedno s okvirom stranice. Ovih 91% je udio u onome što telefon crta. Dvije brojke imaju različite nazivnike i obje su tačne.
Važnija od obje je treća brojka: kategorija „traži doradu po stranici“ pala je na nulu. Ta dorada je urađena jednom, u 55 linija.
Neprenosivi dio bio je jedan layout fajl
U praksi se onih 38% koda za koji se činilo da radi samo na webu svelo na četiri <div> elementa u jednom layout fajlu.
Nativni blizanac ih zamjenjuje. Mreža postaje kutija, dva omotača samo propuštaju djecu dalje, a skip link vraća null. Bundler bira granu po sufiksu u imenu fajla, pa mjesto poziva ostaje identično do bajta. Nijedna sekcija stranice nije mijenjana ni prepisivana.
To je ono što brojka od 62% nije mogla pokazati. Za prenosivi dio nikad nije bilo sumnje. Unaprijed se ne može znati da li je neprenosivi dio rasut po codebaseu ili skupljen na jednom mjestu. Ovdje je to bio jedan fajl, zbog mjesta na kojem je povučena granica između platformi, i sreća s tim nije imala veze.
Šta telefon pokreće
| Modula u bundleu | 1.015 |
| Bytecode | 2,2 MB |
| Vrijeme bundlanja | 3,8 s |
| Host komponente u stablu | View, Text, RCTScrollView; nijedna web komponenta |
| Korištenih komponenti dizajn sistema | 8 |
| Hardkodiranih dizajn vrijednosti | 0 |
Dva poboljšanja koja nisam planirao: obje teme i oba jezika
Nijedno nije bilo cilj nove verzije i nijedno nije tražilo dodatni posao.
Stranica radi u obje teme. Nijedna boja nije zapisana na stranici, nego se sve razrješava preko semantičkih tokena. Original ima hardkodiranu pozadinu i akcentnu boju, pa postoji samo u tamnoj temi.
Oba jezika mogu se indeksirati. Jezik je segment rute, a ne sačuvana postavka, pa se svaki jezik prerenderuje kao statički HTML od oko 152 KB. Na originalu je crawler uvijek vidio samo engleski.
Cijela stranica renderuje se kao serverska komponenta, bez klijentskih ostrva i bez stanja.
Četiri buga koja su prošla sve provjere
Četiri stvarna problema koja sam našao važna su za svaki tim, imao on dizajn sistem ili ne. Svaki od njih prošao je kompajler, linter i build. Tri sam primijetio gledajući rezultat, a četvrti je otkrio telefon.
Pogrešno ime ikone koje ništa nije pokvarilo
Tražio sam tačku za nabrajanje. Ispostavilo se da je ime koje sam upotrijebio alias za ikonu liste, koja crta tri linije s tačkama umjesto jedne tačke.
Registar ikona je namjerno otvoren, pa su imena ikona tipizirana kao obični stringovi. Kompajler i linter nemaju ništa protiv pogrešnog imena, build prolazi, a render prikaže pogrešan glif ili praznu kutiju tačne veličine.
Pogrešno ime primijetio sam na screenshotu. Ništa drugo u lancu ga nije prijavilo.
Popravka je bila da prestanem koristiti ikonu. Badge bez djece renderuje se kao tačka od 8px, a to je bio i jedini način da dobijem akcentnu pozadinu pune jačine, koju tabela iznad navodi kao nedostatak.
To je cijena otvorenog registra. Lako se proširuje, a za to se plaća pogrešnim imenima koja ništa ne prijavi. Sloj provjera gleda primjere iz kataloga, a kod aplikacije ne gleda, pa ovo nije ni mogao uhvatiti.
Native test koji ostaje zelen za ekran koji se ne može otvoriti
Ovaj je gori. Ako omotače namijenjene samo webu renderujete u native test projektu, test prolazi i mirno ispiše ovo:
1{"type":"div","props":{"style":{"position":"sticky","top":0,"zIndex":100}}}2{"type":"a","props":{"href":"#x"}}Test renderer bilježi stablo i ne pita postoji li svaka host komponenta. Na stvarnom uređaju div pada već pri traženju view konfiguracije.
Ni import to ne otkriva. Native styled-components proxy prihvata bilo koji ključ, pa za styled.a vraća funkciju jednako spremno kao za bilo šta drugo.
Tako nijedan od četiri sloja nije reagovao: ni import ni kompajler ni linter ni test.
Provjera koja radi je mala: nabrojite host komponente u renderovanom izlazu i neka test padne ako se pojavi išta osim View ili Text. Istom provjerom sam dokazao da je jedina prenosiva kartica prenosiva i u praksi, jer emituje samo View i Text.
Dekorativna tačka u pristupačnom imenu
Tačka brenda na kraju naslova čitala se kao dio pristupačnog imena, s razmakom ispred sebe: „…systems that can't stop .“
Bug je sitan, ali spada u istu grupu kao prethodna dva. Pristupačno ime koje sam pretpostavio i ono koje sam izmjerio bili su različiti stringovi, a stvarno je bilo samo izmjereno.
Bug koji je mogao naći samo hardver
Prvi build se srušio na telefonu:
1ScrollView child layout (["alignItems","justifyContent"])2must be applied through the contentContainerStyle prop.Sa stranicom nije bilo problema. Uzrok je bio u jednom primitivu, u kojem su se sudarila dva pravila samog sistema.
Nativni primitiv za skrolanje primjenjuje zajednički stack recept, a taj recept uvijek ispisuje svojstva poravnanja. Tako je napravljen s razlogom: web i native imaju različite default vrijednosti, pa ako vrijednost nije izričito zapisana, dvije platforme se raziđu. To pravilo je ispravno.
Ispravno je i pravilo React Nativea: djeca kontejnera koji skroluje ne poravnavaju se na samom scroll viewu, nego na kontejneru sadržaja. Kad su se ta dva pravila srela, ekran se srušio.
Popravka je bila da se recept razdvoji na verziju bez svojstava poravnanja i verziju s njima. Korijen skrolanja uzima prvu, a poravnanje se seli u unutrašnji view. Tu mu je ionako bilo mjesto, jer poravnava sadržaj, a ne kutiju koja skroluje. Web strana je ostala netaknuta.
Provjere ovo nisu uhvatile iz dva razloga. Runtime provjera koja je ispisala tu poruku radi samo kad je uključena razvojna zastavica i kad je ispunjen uslov na style propu. Osim toga, testno okruženje mockuje scroll view, pa se prava klasa ni u jednom testu ne izvrši. Typecheck, native testovi i produkcijski export bili su zeleni.
Dodao sam dva testa koja provjeravaju ispisani stil umjesto da čekaju izuzetak. Provjerio sam ih na jedini način koji smatram vrijednim: ponovo sam uveo bug, vidio da oba testa padaju tačno na tom svojstvu i onda ga opet uklonio.
Zašto ih nijedna provjera nije uhvatila
Tri ovakva nalaza još bi se mogla odbaciti, ali četiri teško.
Svaki od njih prošao je svaku provjeru koju sam imao, i to uvijek iz istog razloga: svaka provjera odgovara na jedno određeno pitanje, a nijedna ne pita znači li kod ono što je autor mislio da znači. Nijedna provjera u lancu ne pita da li atribut išta radi, da li prop stiže do elementa, da li je komentar još tačan i da li će komponenta postojati na uređaju za koji se kompajlira.
Četvrti bug to pokazuje najjasnije: telefon je za tri sekunde našao ono što su četiri automatska sloja odobrila.
Prijavljena greška vas zaustavi odmah i košta vas jedan build. Bug koji prođe sve provjere ode u produkciju, a kasnije ga platite skuplje, po cijeni koju ne možete znati unaprijed.
Za port je trebala druga ljuska od 102 linije
Port nije tražio prepisivanje, nego samo drugu ljusku, ukupno 102 linije:
| Web | Mobilni |
|---|---|
| omotači mreže | kutija s razmakom |
| sticky traka | samo propušta djecu |
| skip link | vraća null |
<main> / <footer> | omotač ekrana: sigurna zona, skrol, sadržaj |
| rutiranje frameworka | navigacioni adapter koji je već postojao |
<a href> za mail i telefon | platformski poziv za otvaranje linka |
U praksi to znači da svaku sekciju izdvojite u fajl koji prima samo propse dizajn sistema, a svakoj platformi prepustite da donese svoju ljusku. Jedina kartica koja se prenijela bez ijedne izmjene već je bila tako napravljena i zato se prenijela.
Šta nisam izmjerio
Nisam pokrenuo Lighthouse niti na bilo koji drugi način mjerio performanse. Sve provjere prolaze: 678 testova u 62 suitea, izlazni kod nula. U headless browseru stranica nije imala grešaka u konzoli ni horizontalnog skrola na 390px, 29 linkova imalo je ispravna pristupačna imena, a hijerarhija naslova bila je čista. Web izlaz je nakon porta ostao isti. To sam provjerio, a brzinu nisam.
Nemam ni screenshot s uređaja. Potvrđeno je da ekran radi u Expo Go, ali slike s njega u ovom tekstu nema.
Nisam ni poredio vrijeme izrade s ljudskim radom. Druga stranica uzela je manje od pet minuta agentovog vremena, ali nema čiste polazne tačke za poređenje, jer je i produkcijski sajt napravljen uz pomoć agenta. Uz to, git mjeri kalendarsko vrijeme, a ne trud.
Šta bih rekao drugom timu
Napravite pravu stranicu svojim sistemom prije nego što mu povjerujete. Ne mislim na demo ni na izlog svih komponenti, nego na nešto što bi neko morao isporučiti. Naša stranica tražila je sedam komponenti i otkrila osam konkretnih praznina, od kojih sam dvije ranije samo naslućivao.
Prebrojte izuzetke i svakom dajte uslov pod kojim se briše. Četiri izuzetka u jednom fajlu znače da su granice sistema poznate. Da su ista četiri razasuta po stranici, sistem bi prestao raditi kao sistem, a da to niko ne primijeti.
Računajte s tim da će skupi propusti biti oni koje ništa ne prijavi. Sva četiri buga prošla su svaku provjeru koju sam imao: pogrešna ikona se iscrtala, ekran koji se ne može otvoriti bio je zelen na testu, pristupačno ime se čitalo drugačije nego što je izgledalo, a build koji se srušio na telefonu odobrili su kompajler, testovi i produkcijski export. Nijedan od njih nije izbacio grešku i zato su prošli.
Blog
Ako radite na nečemu sličnom, javite nam se s detaljima.
Prvi poziv traje 30 minuta i ni na šta vas ne obavezuje.