Proiectarea și construirea unei aplicații web progresive fără cadru (partea 3)
Publicat: 2022-03-10În prima parte a acestei serii, am explicat de ce a apărut acest proiect. Și anume dorința de a afla cum ar putea fi făcută o aplicație web mică în JavaScript vanilla și de a face un dezvoltator care nu proiectează să lucreze puțin la design.
În partea a doua am luat niște modele inițiale de bază și am pus lucrurile în funcțiune cu câteva opțiuni de instrumente și tehnologie. Am acoperit cum și de ce s-au schimbat părți ale designului și ramificațiile acestor modificări.
În această parte finală, vom aborda transformarea unei aplicații web de bază într-o aplicație web progresivă (PWA) și „expedierea” aplicației înainte de a analiza cele mai valoroase lecții învățate făcând aplicația web simplă In/Out:
- Valoarea enormă a metodelor matrice JavaScript;
- Depanare;
- Când ești singurul dezvoltator, ești celălalt dezvoltator;
- Designul este dezvoltare;
- Probleme de întreținere și securitate continuă;
- Lucrul la proiecte secundare fără a-ți pierde mințile, motivația sau ambele;
- Livrarea unor produse depășește livrarea niciunui produs.
Așadar, înainte de a analiza lecțiile învățate, să ne uităm la modul în care transformați o aplicație web de bază scrisă în HTML, CSS și JavaScript într-o aplicație web progresivă (PWA).
În ceea ce privește timpul total petrecut pentru realizarea acestei mici aplicații web, aș crede că a fost probabil în jur de două sau trei săptămâni. Cu toate acestea, deoarece a fost făcut în bucăți de 30-60 de minute seara, de fapt, a durat aproximativ un an de la prima comitere până când am încărcat ceea ce consider versiunea „1.0” în august 2018. Deoarece am primit aplicația „ caracteristică completă”, sau mai simplu vorbind, într-o etapă de care am fost mulțumit, am anticipat o împingere finală mare. Vedeți, nu am făcut nimic pentru a transforma aplicația într-o aplicație web progresivă. Se pare că aceasta a fost de fapt cea mai ușoară parte a întregului proces.
Realizarea unei aplicații web progresive
Vestea bună este că atunci când vine vorba de a transforma o mică aplicație bazată pe JavaScript într-o „aplicație web progresivă”, există o grămadă de instrumente pentru a face viața mai ușoară. Dacă vă întoarceți mintea la prima parte a acestei serii, vă veți aminti că a fi o aplicație web progresivă înseamnă îndeplinirea unui set de criterii.
Pentru a înțelege cum se măsoară aplicația dvs. web, prima oprire ar trebui să fie, probabil, instrumentele Lighthouse din Google Chrome. Puteți găsi auditul Progressive Web App în fila „Audituri”.
Asta mi-a spus Lighthouse când am trecut prima oară prin In/Out.

La început, In/Out a obținut doar un scor de 55 ⁄ 100 pentru o aplicație web progresivă. Totuși, am luat-o de acolo la 100⁄ 100 în mai puțin de o oră!
Promptitudinea de a îmbunătăți acest punctaj a avut puțin de-a face cu abilitatea mea. Pur și simplu pentru că Lighthouse mi-a spus exact ce trebuie făcut!
Câteva exemple de pași necesari: includeți un fișier manifest.json
(în esență un fișier JSON care furnizează metadate despre aplicație), adăugați o mulțime de meta-etichete în cap, schimbați imaginile care au fost aliniate în CSS pentru imaginile standard de referință URL, și adăugați o grămadă de imagini pe ecranul de pornire.
Crearea mai multor imagini de pe ecranul de pornire, crearea unui fișier manifest și adăugarea unei grămadă de meta-etichete ar putea părea mult de făcut în mai puțin de o oră, dar există aplicații web minunate care vă ajută să construiți aplicații web. Ce frumos este! Am folosit https://app-manifest.firebaseapp.com. Introduceți-i câteva date despre aplicația și logo-ul dvs., apăsați pe submit și vă furnizează un fișier zip care conține tot ce aveți nevoie! De acolo încolo, este doar timpul de copiere și inserare.
Lucrurile pe care le-am amânat de ceva timp din cauza lipsei de cunoștințe, cum ar fi un lucrător de service, au fost, de asemenea, adăugate destul de ușor datorită numeroaselor postări pe blog și site-uri dedicate lucrătorilor de servicii precum https://serviceworke.rs. Cu un lucrător de service, însemna că aplicația ar putea funcționa offline, o caracteristică necesară a unei aplicații web progresive.
Deși nu este strict legată de transformarea aplicației într-o PWA, fila „acoperire” a Chrome Dev Tools a fost, de asemenea, foarte utilă. După atât de multe iterații sporadice asupra designului și codului de-a lungul lunilor, a fost util să obținem o indicație clară despre unde era cod redundant. Am găsit câteva funcții vechi care împrăștiau baza de cod de care pur și simplu uitasem!
Pe scurt, după ce am lucrat la recomandările de audit Lighthouse, m-am simțit ca animalul de companie al profesorului:

Realitatea este că luarea aplicației și transformarea acesteia într-o aplicație web progresivă a fost de fapt incredibil de simplă.
Odată cu acea parte finală de dezvoltare încheiată, am încărcat mica aplicație într-un subdomeniu al site-ului meu și asta a fost tot.
Retrospectiv
Au trecut luni de când am parcat dezvoltarea micuței mele aplicații web.
Am folosit aplicația întâmplător în lunile de după. Realitatea este că o mare parte din organizarea sporturilor de echipă pe care o fac încă se întâmplă prin mesaj text. Aplicația este, totuși, cu siguranță mai ușoară decât să notezi cine este și cine iese decât să găsești o bucată de hârtie în fiecare seară de joc.
Deci, adevărul este că nu este un serviciu indispensabil. Nici nu stabilește bare pentru dezvoltare sau design. Nici eu nu aș putea să vă spun că sunt 100% mulțumit de el. Tocmai am ajuns la un punct în care eram fericit să-l abandonez.
Dar acesta nu a fost niciodată scopul exercițiului. Am luat multe din experiență. Ceea ce urmează sunt cele pe care le consider cele mai importante.
Designul este dezvoltare
La început, nu am apreciat suficient designul. Am început acest proiect crezând că timpul petrecut schițând cu un bloc și un stilou sau în aplicația Sketch, a fost timp care ar putea fi petrecut mai bine cu codificare. Cu toate acestea, se pare că atunci când am trecut direct la cod, de multe ori eram doar un prost ocupat. Explorarea conceptelor mai întâi la cea mai scăzută fidelitate posibilă a economisit mult mai mult timp pe termen lung.
Au fost numeroase ocazii la început în care s-au petrecut ore întregi pentru a lucra în cod doar pentru a realiza că era fundamental defectuos din punct de vedere al experienței utilizatorului.
Părerea mea acum este că hârtia și creionul sunt cele mai bune instrumente de planificare, proiectare și codare. Fiecare problemă semnificativă cu care se confrunta a fost rezolvată în principal cu hârtie și creion; editorul de text este doar un mijloc de executare a soluției. Fără ceva care să aibă sens pe hârtie, nu are nicio șansă să lucreze în cod.
Următorul lucru pe care am învățat să-l apreciez și nu știu de ce a durat atât de mult să-mi dau seama, este că designul este iterativ. În mod subconștient, am cumpărat mitul unui designer cu „D” mare. Cineva zbârnâind, ținând creionul mecanic în sus la margini drepte, liric despre fonturi și sorbind un alb plat (cu lapte de soia, evident) înainte de a naște pe deplin perfecțiune vizuală în lume.
Acest lucru, nu spre deosebire de noțiunea de programator „geniu”, este un mit. Dacă sunteți nou în design, dar vă încercați mâna, ți-aș sugera să nu fi obosit de prima idee care îți stârnește entuziasmul. Este atât de ieftin să încerci variante, așa că îmbrățișează această posibilitate. Niciunul dintre lucrurile care îmi plac la designul In/Out nu au fost prezente în primele modele.
Cred că romancierul Michael Crichton a fost cel care a inventat maxima „ Cărțile nu sunt scrise – sunt rescrise”. Acceptați că fiecare proces creativ este în esență același. Fiți conștienți de faptul că încrederea în proces reduce anxietatea și practica vă va rafina înțelegerea și judecata estetică.
Tu ești celălalt dezvoltator al proiectului tău
Nu sunt sigur dacă acest lucru este specific proiectelor la care se lucrează doar sporadic, dar am făcut următoarea presupunere nesăbuită:
„Nu trebuie să documentez nimic din toate acestea pentru că sunt doar eu și, evident, voi înțelege pentru că am scris-o.”
Nimic mai departe de adevăr!
Au fost seri în care, în cele 30 de minute în care am avut de lucrat la proiect, nu am făcut altceva decât să încerc să înțeleg o funcție pe care o scrisesem în urmă cu șase luni. Principalele motive pentru care reorientarea codului a durat atât de mult a fost lipsa comentariilor de calitate și a variabilelor prost numite și a argumentelor funcției.
Sunt foarte sârguincios în a comenta codul în munca mea de zi cu zi, mereu conștiincios că altcineva ar putea avea nevoie să înțeleagă ceea ce scriu. Cu toate acestea, în acest caz, eu eram acel altcineva. Chiar crezi că îți vei aminti cum funcționează blocul de cod pe care l-ai scris peste șase luni? Nu vei. Crede-mă în privința asta, fă-ți puțin timp și comentează chestia asta!
De atunci, am citit o postare pe blog intitulată, Evidențiatorul de sintaxă este greșit în ceea ce privește importanța comentariilor. Premisa de bază este că evidențiatorii de sintaxă nu ar trebui să estompeze comentariile, ci ar trebui să fie cel mai important lucru. Înclin să fiu de acord și dacă nu găsesc în curând o temă de editor de cod care să mă zgârie asta, s-ar putea să trebuiască să adaptez una în acest scop!
Depanare
Când ați lovit erori și ați scris tot codul, nu este nedrept să sugerați că eroarea provine probabil între tastatură și scaun. Cu toate acestea, înainte de a presupune asta, aș sugera să testați chiar și cele mai de bază ipoteze. De exemplu, îmi amintesc că am durat peste două ore pentru a remedia o problemă pe care am presupus că se datorează codului meu; în iOS, pur și simplu nu am putut face caseta mea de introducere să accepte introducerea textului. Nu-mi amintesc de ce nu m-a oprit înainte, dar îmi amintesc frustrarea mea cu această problemă.
Se pare că s-a datorat unei erori, încă neremediate, în Safari. Se pare că în Safari dacă aveți:
* { user-select: none; }
În foaia de stil, casetele de introducere nu vor primi nicio introducere. Puteți rezolva asta cu:
* { user-select: none; } input[type] { user-select: text; }
Care este abordarea pe care o adopt în resetarea mea CSS „Resetare aplicație”. Cu toate acestea, partea cu adevărat frustrantă a fost că am învățat deja acest lucru și, ulterior, l-am uitat. Când am ajuns în sfârșit să verific urmărirea erorilor WebKit în timp ce depanam problema, am descoperit că am scris o soluție în firul de raportare a erorilor în urmă cu mai bine de un an, completă cu reducere!
Doriți să construiți cu date? Aflați metode JavaScript Array
Poate cel mai mare avans pe care l-au avut abilitățile mele JavaScript în urma acestui exercițiu de creare a aplicației a fost familiarizarea cu metodele JavaScript Array. Acum le folosesc zilnic pentru toate nevoile mele de iterare și manipulare a datelor. Nu pot sublinia suficient cât de utile sunt metode precum map()
, filter()
, every()
, findIndex()
, find()
și reduce()
. Puteți rezolva practic orice problemă de date cu ele. Dacă nu le aveți deja în arsenalul dvs., marcați acum https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array și căutați de îndată ce puteți. Propria mea descriere a metodelor mele preferate de matrice este documentată aici.

ES6 a introdus și alte economii de timp pentru manipularea matricelor, cum ar fi Set
, Rest
și Spread
. Răsfățați-mă în timp ce vă împărtășesc un exemplu; Au fost o grămadă de faff dacă ați vrut să eliminați duplicatele chiar și dintr-o simplă matrice plată. Nu mai.
Luați în considerare acest exemplu simplu de matrice cu intrarea duplicată, „Mr Pink”:
let myArray = [ "Mr Orange", "Mr Pink", "Mr Brown", "Mr White", "Mr Blue", "Mr Pink" ];
Pentru a scăpa de duplicatele cu ES6 JavaScript, acum puteți face:
let deDuped = [...new Set(myArray)]; // deDuped logs ["Mr Orange", "Mr Pink", "Mr Brown", "Mr White", "Mr Blue"]
Ceva care obișnuia să folosească o soluție manuală sau să ajungă la o bibliotecă este acum integrat în limbaj. Desigur, pe un Array scurt, poate să nu sune așa de mare lucru, dar imaginați-vă cât de mult timp se economisește atunci când se uită la matrice cu sute de intrări și duplicate.
Întreținere și securitate
Orice construiți și care folosește NPM, chiar dacă doar pentru instrumente de construcție, are posibilitatea de a fi vulnerabil la probleme de securitate. GitHub face o treabă bună de a vă ține la curent cu potențialele probleme, dar există încă o sarcină de întreținere.
Pentru ceva care este un simplu proiect secundar, acest lucru poate fi puțin dureros în lunile și anii care urmează dezvoltării active.
Realitatea este că de fiecare dată când actualizați dependențe pentru a remedia o problemă de securitate, introduceți posibilitatea de a vă sparge construcția.
Luni de zile, package.json
meu arăta astfel:
{ "dependencies": { "gulp": "^3.9.1", "postcss": "^6.0.22", "postcss-assets": "^5.0.0" }, "name": "In Out", "version": "1.0.0", "description": "simple utility to see who's in and who's out", "main": "index.js", "author": "Ben Frain", "license": "MIT", "devDependencies": { "autoprefixer": "^8.5.1", "browser-sync": "^2.24.6", "cssnano": "^4.0.4", "del": "^3.0.0", "gulp-htmlmin": "^4.0.0", "gulp-postcss": "^7.0.1", "gulp-sourcemaps": "^2.6.4", "gulp-typescript": "^4.0.2", "gulp-uglify": "^3.0.1", "postcss-color-function": "^4.0.1", "postcss-import": "^11.1.0", "postcss-mixins": "^6.2.0", "postcss-nested": "^3.0.0", "postcss-simple-vars": "^4.1.0", "typescript": "^2.8.3" } }
Și până în iunie 2019, primeam aceste avertismente de la GitHub:

Niciunul nu avea legătură cu pluginurile pe care le foloseam direct, toate erau subdependențe ale instrumentelor de compilare pe care le folosisem. Aceasta este sabia cu două tăișuri a pachetelor JavaScript. În ceea ce privește aplicația în sine, nu a existat nicio problemă cu In/Out; care nu folosea niciuna dintre dependențele proiectului. Dar, deoarece codul era pe GitHub, m-am simțit obligat să încerc să repar lucrurile.
Este posibil să actualizați pachetele manual, cu câteva modificări ale pachetului.json. Cu toate acestea, atât Yarn, cât și NPM au propriile lor comenzi de actualizare. Am ales să rulez yarn upgrade-interactive
care vă oferă un mijloc simplu de a actualiza lucrurile din terminal.

Pare destul de ușor, există chiar și o mică cheie colorată pentru a vă spune care actualizări sunt cele mai importante.
Puteți adăuga --latest
pentru a actualiza la cea mai recentă versiune majoră a dependențelor, mai degrabă decât la cea mai recentă versiune corectată. Pentru un ban...
Problema este că lucrurile se mișcă rapid în lumea pachetelor JavaScript, așa că actualizarea câtorva pachete la cea mai recentă versiune și apoi încercarea de a construi a avut ca rezultat:

Ca atare, mi-am derulat fișierul package.json
și am încercat din nou de data aceasta fără --latest
. Asta mi-a rezolvat problemele de securitate. Nu este cel mai distractiv pe care m-am distrat într-o seară de luni, deși voi fi sincer.
Aceasta atinge o parte importantă a oricărui proiect secundar. Fii realist cu așteptările tale.
Proiecte secundare
Nu știu dacă sunteți la fel, dar am constatat că un optimism și o entuziasm amețitor mă fac să încep proiecte și dacă ceva face, jena și vinovăția mă fac să le termin.
Ar fi o minciună să spun că experiența de a face această aplicație minusculă în timpul meu liber a fost plină de distracție. Au fost ocazii în care mi-aș fi dorit să nu fi deschis nimănui gura despre asta. Dar acum s-a terminat, sunt 100% convins că a meritat timpul investit.
Acestea fiind spuse, este posibil să atenuați frustrarea cu un astfel de proiect secundar fiind realist în ceea ce privește cât timp va dura pentru a înțelege și rezolva problemele cu care vă confruntați. Ai doar 30 de minute pe noapte, câteva nopți pe săptămână? Puteți finaliza un proiect secundar; doar nu fi nemulțumit dacă ritmul tău pare glacial. Dacă lucrurile nu se pot bucura de toată atenția ta, fii pregătit pentru un ritm mai lent și mai constant decât cu care probabil ești obișnuit. Este adevărat, fie că este vorba de codificare, de finalizare a unui curs, de a învăța să jonglezi sau de a scrie o serie de articole despre motivul pentru care a durat atât de mult să scrii o mică aplicație web!
Stabilirea simplă a obiectivelor
Nu aveți nevoie de un proces elegant pentru stabilirea obiectivelor. Dar ar putea ajuta să împărțiți lucrurile în sarcini mici/scurte. Lucruri la fel de simple precum „scrieți CSS pentru meniul drop-down” sunt perfect realizabile într-un spațiu limitat de timp. În timp ce „cercetarea și implementarea unui model de proiectare pentru managementul de stat” probabil nu este. Rupe lucrurile. Apoi, la fel ca Lego, piesele minuscule merg împreună.
Gândindu-mă la acest proces ca o reducere a problemei mai mari, îmi amintesc de celebrul citat al lui Bill Gates:
„Majoritatea oamenilor supraestimează ceea ce pot face într-un an și subestimează ceea ce pot face în zece ani.”
Asta de la un bărbat care ajută la eradicarea poliomielitei. Bill își știe lucrurile. Ascultă-l pe Bill.
Expedierea ceva este mai bună decât livrarea nimic
Înainte de a „expedi” această aplicație web, am revizuit codul și am fost complet descurajat.
Deși plecasem în această călătorie dintr-un punct de naivitate și lipsă de experiență deplină, făcusem câteva alegeri decente când a fost vorba de modul în care aș putea arhitectura (dacă vei ierta un termen atât de mare) codul. Am cercetat și implementat un model de design și m-am bucurat de tot ceea ce avea de oferit acel model. Din păcate, pe măsură ce am devenit tot mai disperat să închei proiectul, nu am reușit să mențin disciplina. Codul, așa cum este, este o adevărată groază de abordări și plină de ineficiențe.
În lunile de după mi-am dat seama că acele neajunsuri nu prea contează. Nu chiar.
Sunt un fan al acestui citat din Helmuth von Moltke.
„Niciun plan de operațiuni nu se extinde cu certitudine dincolo de primul contact cu forța ostilă principală.”
Acesta a fost parafrazat astfel:
„Niciun plan nu supraviețuiește primului contact cu inamicul”.
Poate că o putem reduce și mai mult și pur și simplu mergem cu „rahat se întâmplă”?
Pot presupune că am acceptat ceea ce a fost livrat prin următoarea analogie.
Dacă un prieten a anunțat că va încerca să alerge primul lor maraton, tot ce ar conta ar fi să treacă peste linia de sosire - nu i-aș mustra pentru timpul de sosire.
Nu mi-am propus să scriu cea mai bună aplicație web. Misiunea pe care mi-am propus a fost pur și simplu să proiectez și să realizez unul.
Mai precis, din perspectiva dezvoltării, am vrut să învăț elementele fundamentale ale modului în care a fost construită o aplicație web. Din punct de vedere al designului, am vrut să încerc și să rezolv unele probleme de design (deși simple) pentru mine. Realizarea acestei mici aplicații a îndeplinit aceste provocări și apoi unele. JavaScript pentru întreaga aplicație a fost de doar 5KB (gzipped). O dimensiune mică a fișierului la care mi-ar fi greu să ajung cu orice cadru. Cu excepția poate Sveltei.
Dacă vă puneți o provocare de această natură și vă așteptați la un moment dat să „expediți” ceva, scrieți de la început de ce o faceți. Păstrează aceste motive în prim-planul minții tale și lasă-te ghidat de ele. Totul este până la urmă un fel de compromis. Nu lăsa idealurile înalte să te paralizeze să nu termini ceea ce ți-ai propus.
rezumat
În general, deoarece se apropie un an de când am lucrat la In/Out, sentimentele mele se încadrează în general în trei domenii: lucruri pe care le-am regretat, lucruri pe care mi-aș dori să le îmbunătățesc/remediez și posibilități viitoare.
Lucruri pe care le-am regretat
Așa cum am menționat deja, am fost dezamăgit că nu m-am ținut de ceea ce am considerat o metodă mai elegantă de a schimba starea aplicației și de a o reda în DOM. Modelul observatorului, așa cum s-a discutat în a doua parte a acestei serii, care a rezolvat atât de multe probleme într-o manieră previzibilă, a fost în cele din urmă dat deoparte, deoarece „transportarea” proiectului a devenit o prioritate.
Mi-a fost rușine de codul meu la început, dar în lunile următoare, am devenit mai filozofic. Dacă nu aș fi folosit mai târziu tehnici pietonale, există o posibilitate foarte reală ca proiectul să nu se fi încheiat niciodată. A scoate ceva în lume care trebuie îmbunătățit încă se simte mai bine decât să nu fie niciodată născut în lume.
Îmbunătățirea In/Out
Dincolo de a alege marcajul semantic, nu mi-am făcut nicio posibilitate pentru accesibilitate. Când am construit In/Out, eram încrezător în accesibilitatea standard a paginii web, dar nu aveam suficient de cunoștințe pentru a aborda o aplicație. Am făcut mult mai multă muncă/cercetare în acest domeniu acum, așa că mi-ar plăcea să îmi iau timp pentru a face o treabă decentă de a face această aplicație mai accesibilă.
Implementarea designului revizuit al funcționalității „Adăugați o persoană” a fost grăbită. Nu este un dezastru, doar un pic mai dur decât mi-aș dori. Ar fi frumos să facem asta mai zgomotos.
De asemenea, nu am luat în considerare ecranele mai mari. Ar fi interesant să luăm în considerare provocările de proiectare de a-l face să funcționeze la dimensiuni mai mari, dincolo de pur și simplu a face un tub de conținut.
Posibilitati
Folosirea localStorage a funcționat pentru nevoile mele simpliste, dar ar fi bine să am un depozit de date „adecvat”, așa că nu a fost necesar să vă faceți griji cu privire la backupul datelor. Adăugarea capacității de autentificare ar deschide, de asemenea, posibilitatea de a partaja organizarea jocului cu o altă persoană. Sau poate fiecare jucător ar putea doar să marcheze dacă se juca singur? Este uimitor câte căi de explorat poți avea în vedere de la începuturi atât de simple și umile.
Dezvoltarea aplicației SwiftUI pentru iOS este, de asemenea, intrigantă. Pentru cineva care a lucrat doar cu limbi web, la prima vedere, SwiftUI arată ca ceva pe care acum sunt îndrăznit să încerc. Probabil că aș încerca să reconstruiesc In/Out cu SwiftUI - doar pentru a avea ceva specific pentru a construi și a compara experiența și rezultatele de dezvoltare.
Și așa, este timpul să închei lucrurile și să-ți oferim versiunea TL;DR a tuturor acestor lucruri.
Dacă doriți să aflați cum funcționează ceva pe web, vă sugerez să omiteți abstracțiile. Renunță la cadre, fie că este vorba de CSS sau JavaScript, până când înțelegi cu adevărat ce înseamnă ele pentru tine.
Designul este iterativ, îmbrățișați acest proces.
Rezolvați problemele în cel mai scăzut mediu de fidelitate pe care îl aveți la dispoziție. Nu mergeți la cod dacă puteți testa ideea în Sketch. Nu o desenați în Sketch dacă puteți folosi pix și hârtie. Scrieți mai întâi logica. Apoi scrieți-l în cod.
Fii realist, dar niciodată descurajat. Dezvoltarea unui obicei de a ciobi ceva timp de 30 de minute pe zi poate avea rezultate. Acest fapt este adevărat, indiferent de forma pe care o ia căutarea ta.