Proiectarea și construirea unei aplicații web progresive fără cadru (Partea 1)
Publicat: 2022-03-10Cum funcționează de fapt o aplicație web? Nu mă refer din punctul de vedere al utilizatorului final. Adică în sens tehnic. Cum rulează de fapt o aplicație web? Ce declanșează lucrurile? Fără niciun cod standard, care este modul corect de a structura o aplicație? În special, o aplicație pe partea clientului în care toată logica rulează pe dispozitivul utilizatorilor finali. Cum sunt gestionate și manipulate datele? Cum faci interfața să reacționeze la modificările datelor?
Acestea sunt genul de întrebări care sunt ușor de ocolit sau de ignorat complet cu un cadru. Dezvoltatorii caută ceva de genul React, Vue, Ember sau Angular, urmează documentația pentru a începe și a pleca. Aceste probleme sunt gestionate de cutia de trucuri a cadrului.
Poate chiar așa vrei tu lucrurile. Probabil, este lucrul inteligent de făcut dacă doriți să construiți ceva la un standard profesional. Cu toate acestea, cu magia abstrasă, nu veți putea niciodată să învățați cum sunt de fapt executate trucurile.
Nu vrei să știi cum se fac trucurile?
Am facut. Așa că, am decis să încerc să construiesc o aplicație de bază pe partea clientului, sans-framework, pentru a înțelege aceste probleme pentru mine.
Dar, sunt puțin înaintea mea; mai întâi puțin fundal.
Înainte de a începe această călătorie, m-am considerat foarte competent la HTML și CSS, dar nu la JavaScript. Deoarece simțeam că am rezolvat cele mai mari întrebări pe care le aveam despre CSS spre satisfacția mea, următoarea provocare pe care mi-am propus-o a fost înțelegerea unui limbaj de programare.
Adevărul a fost că eram la un nivel relativ începător cu JavaScript. Și, în afară de piratarea PHP-ului Wordpress, nu am avut nicio expunere sau pregătire în niciun alt limbaj de programare.
Permiteți-mi să calific această afirmație „la nivel de începător”. Sigur, aș putea obține interactivitatea lucrând pe o pagină. Comutați între clase, creați noduri DOM, adăugați-le și mutați-le, etc. Dar când a fost vorba de organizarea codului pentru orice altceva dincolo de asta, nu aveam nicio idee. Nu eram încrezător să construiesc ceva ce se apropie de o aplicație. Nu aveam idee cum să definesc un set de date în JavaScipt, darămite să-l manipulez cu funcții.
Nu înțelegeam „modele de design” JavaScript – abordări stabilite pentru rezolvarea problemelor de cod întâlnite des. Cu siguranță nu am avut o idee despre cum să abordez deciziile fundamentale de proiectare a aplicației.
Ai jucat vreodată „Top Trumps”? Ei bine, în ediția pentru dezvoltatori web, cardul meu ar arăta cam așa (note din 100):
- CSS: 95
- Copiați și lipiți: 90
- Linia părului: 4
- HTML: 90
- JavaSript: 13
Pe lângă faptul că vreau să mă provoc pe mine însumi la nivel tehnic, îmi lipsea și cotletele de design.
Având aproape exclusiv codificarea designurilor altor oameni în ultimul deceniu, abilitățile mele de design vizual nu au avut nicio provocare reală de la sfârșitul anilor nouăzeci. Reflectând la acest fapt și la abilitățile mele insignifiante JavaScript, am cultivat un sentiment din ce în ce mai mare de inadecvare profesională. Era timpul să îmi rezolv neajunsurile.
O provocare personală a luat forma în mintea mea: să proiectez și să construiesc o aplicație web JavaScript la nivelul clientului.
Despre Învățare
Nu au existat niciodată resurse mai mari pentru a învăța limbaje de calcul. Mai ales JavaScript. Cu toate acestea, mi-a luat ceva timp să găsesc resurse care să explice lucrurile într-un mod care să facă clic. Pentru mine, „You Don’t Know JS” de Kyle Simpson și „Eloquent JavaScript” de Marijn Haverbeke au fost de mare ajutor.
Dacă începeți să învățați JavaScript, cu siguranță va trebui să vă găsiți proprii guru; oameni a căror metodă de explicare funcționează pentru tine.
Primul lucru cheie pe care l-am învățat a fost că este inutil să încerci să înveți de la un profesor/resursă care nu explică lucrurile într-un mod pe care le înțelegi tu. Unii oameni se uită la exemple de funcții cu foo
și bar
și înțeleg instantaneu sensul. Nu sunt unul dintre acei oameni. Dacă nici tu nu ești, nu presupune că limbajele de programare nu sunt pentru tine. Încercați o resursă diferită și continuați să aplicați abilitățile pe care le învățați.
De asemenea, nu este un dat că te vei bucura de orice fel de moment eureka în care totul „clic” brusc; ca echivalentul codificator al iubirii la prima vedere. Este mai probabil că va fi nevoie de multă perseverență și aplicare considerabilă a învățăturilor tale pentru a te simți încrezător.
De îndată ce te simți chiar și puțin competent, încercând să aplici învățarea ta te va învăța și mai mult.
Iată câteva resurse pe care le-am găsit utile pe parcurs:
- Fun Funcție Distracție Canal YouTube
- Cursuri Kyle Simpson Plural Sight
- JavaScript30.com al lui Wes Bos
- JavaScript elocvent de Marijn Haverbeke
Corect, cam asta e tot ce trebuie să știi despre motivul pentru care am ajuns în acest moment. Elefantul acum în cameră este, de ce să nu folosești un cadru?
De ce să nu reacționezi, Ember, Angular, Vue Et Al
Deși s-a făcut aluzie la răspuns la început, cred că subiectul de ce nu a fost folosit un cadru trebuie extins.
Există o mulțime de cadre JavaScript de înaltă calitate, bine acceptate. Fiecare proiectat special pentru construirea de aplicații web la nivelul clientului. Exact genul de lucru pe care căutam să-l construiesc. Te iert că te întrebi ce este evident: cum ar fi, greșit, de ce să nu folosești unul?
Iată poziția mea cu privire la asta. Când înveți să folosești o abstracție, asta este în primul rând ceea ce înveți - abstracția. Am vrut să învăț lucrul, nu abstracția lui.
Îmi amintesc că am aflat ceva jQuery pe vremea aceea. În timp ce minunatul API mi-a permis să fac manipulările DOM mai ușoare decât oricând înainte de a deveni neputincios fără el. Nici măcar nu am putut comuta între clase pe un element fără a avea nevoie de jQuery. Înscrieți-mi ceva interactivitate de bază pe o pagină fără jQuery pe care să mă sprijin și m-am împiedicat în editorul meu ca un Samson tuns.
Mai recent, în timp ce încercam să-mi îmbunătățesc înțelegerea JavaScript, am încercat să-mi înțeleg puțin Vue și React. Dar, în cele din urmă, nu am fost niciodată sigur unde se termină JavaScript standard și unde începe React sau Vue. Părerea mea este că aceste abstracții sunt mult mai valoroase atunci când înțelegi ce fac ele pentru tine.
Prin urmare, dacă aveam de gând să învăț ceva, voiam să înțeleg părțile de bază ale limbii. În felul acesta, aveam niște abilități transferabile. Am vrut să păstrez ceva când aromă actuală a cadrului lunii a fost lăsată deoparte pentru următorul „lucru nou fierbinte”.
Bine. Acum, suntem prinși de ce a fost creată această aplicație și, de asemenea, vă place sau nu, cum ar fi creată.
Să trecem la ce avea să fie chestia asta.
O idee de aplicație
Aveam nevoie de o idee de aplicație. Nimic prea ambițios; Nu am avut nicio iluzie de a crea o afacere înființată sau de a apărea pe Dragon's Den - învățarea JavaScript-ului și noțiunile de bază ale aplicațiilor a fost scopul meu principal.
Aplicația trebuia să fie ceva ce am avut șansa de a reuși din punct de vedere tehnic și de a face o lucrare de design pe jumătate decentă.
Timp tangent.
Departe de la muncă, mă organizez și joc fotbal de sală ori de câte ori pot. În calitate de organizator, este o durere să notez mental cine mi-a trimis un mesaj pentru a spune că joacă și cine nu. De obicei, pentru un joc sunt necesare 10 persoane, 8 la o apăsare. Există o listă de aproximativ 20 de oameni care pot sau nu pot juca fiecare joc.
Ideea aplicației pe care m-am hotărât a fost ceva care a permis alegerea jucătorilor dintr-o listă, dându-mi un număr de câți jucători confirmaseră că pot juca.
Pe măsură ce m-am gândit mai mult la asta, am simțit că aș putea lărgi puțin mai mult domeniul de aplicare, astfel încât să poată fi folosit pentru a organiza orice activitate simplă bazată pe echipă.
Desigur, cu greu am visat Google Earth. Totuși, a avut toate provocările esențiale: design, managementul datelor, interactivitate, stocarea datelor, organizarea codului.
Din punct de vedere al designului, nu m-aș preocupa de altceva decât de o versiune care ar putea rula și să funcționeze bine pe o fereastră de vizualizare a telefonului. Aș limita provocările de proiectare la rezolvarea problemelor doar pe ecrane mici.
Ideea de bază s-a înclinat cu siguranță către aplicații de stil „de făcut”, dintre care au existat o grămadă de exemple existente pe care să le uite pentru inspirație, având, de asemenea, suficientă diferență pentru a oferi unele provocări unice de design și codare.
Caracteristici preconizate
O listă inițială de caracteristici pe care intenționam să le proiectez și să codific arăta astfel:
- O casetă de introducere pentru a adăuga persoane la listă;
- Capacitatea de a seta fiecare persoană la „înăuntru” sau „în afara”;
- Un instrument care împarte oamenii în echipe, implicit la 2 echipe;
- Capacitatea de a șterge o persoană din listă;
- O interfață pentru „instrumente”. Pe lângă împărțire, instrumentele disponibile ar trebui să includă capacitatea de a descărca datele introduse ca fișier, de a încărca datele salvate anterior și de a șterge toți jucătorii dintr-o singură mișcare;
- Aplicația ar trebui să arate un număr curent al câte persoane sunt „în”;
- Dacă nu există persoane selectate pentru un joc, acesta ar trebui să ascunde separatorul de echipă;
- Modul de plată. O comutare în setări care permite utilizatorilor „în” să aibă o comutare suplimentară pentru a arăta dacă au plătit sau nu.
La început, aceasta este ceea ce am considerat caracteristicile pentru un produs minim viabil.
Proiecta
Modelele au început pe bucăți de hârtie. A fost uimitor (a se citi: zdrobitor) să aflu câte idei care erau incredibile în mintea mea s-au dovedit a fi ridicole atunci când sunt supuse chiar și controlului slab oferit de un desen în creion.
Prin urmare, multe idei au fost eliminate rapid, dar reversul a fost că, schițând unele idei, a condus invariabil la alte idei pe care altfel nu le-aș fi luat în considerare.
Acum, designerii care citesc asta probabil vor fi de genul „Bineînțeles”, dar aceasta a fost o adevărată revelație pentru mine. Dezvoltatorii sunt obișnuiți să vadă design-uri ulterioare, rareori văzând toți pașii abandonați de-a lungul drumului înainte de acel moment.
Odată mulțumit de ceva ca un desen în creion, aș încerca să-l recreez în pachetul de design, Sketch. Așa cum ideile au căzut la faza de hârtie și creion, un număr egal nu a reușit să treacă prin următoarea etapă de fidelitate a Sketch. Cele care păreau să reziste ca planșe de artă în Sketch au fost apoi alese drept candidați pentru codificare.
Aș descoperi, la rândul său, că atunci când acești candidați au fost cod încorporat, un procent nu a funcționat din diferite motive. Fiecare pas de fidelitate a expus noi provocări pentru ca designul să treacă sau să eșueze. Și un eșec m-ar duce la propriu și la figurat înapoi la planșa de desen.
Ca atare, în cele din urmă, designul cu care am ajuns este destul de diferit de cel pe care l-am avut inițial în Sketch. Iată primele machete Sketch:
Chiar și atunci, nu am avut nicio iluzie; a fost un design de bază. Cu toate acestea, în acest moment aveam ceva în care eram relativ încrezător că ar putea funcționa și mă mâhneam să încerc să-l construiesc.
Cerinte tehnice
Cu unele cerințe inițiale pentru caracteristici și o direcție vizuală de bază, era timpul să luăm în considerare ce ar trebui să fie realizat cu codul.
Deși înțelepciunea primită dictează că modalitatea de a face aplicații pentru dispozitivele iOS sau Android este cu cod nativ, am stabilit deja că intenția mea a fost să construiesc aplicația cu JavaScript.
Am fost, de asemenea, dornic să mă asigur că aplicația a bifat toate căsuțele necesare pentru a se califica ca aplicație web progresivă sau PWA, așa cum sunt mai cunoscute.
Dacă nu știți ce este o aplicație web progresivă, iată „elevator pitch”. Din punct de vedere conceptual, imaginați-vă doar o aplicație web standard, dar una care îndeplinește anumite criterii. Respectarea acestui set de cerințe speciale înseamnă că un dispozitiv de suport (să gândim la telefonul mobil) acordă aplicației web privilegii speciale, făcând aplicația web mai mare decât suma părților sale.
Pe Android, în special, poate fi aproape imposibil să distingem un PWA, construit doar cu HTML, CSS și JavaScript, de o aplicație construită cu cod nativ.
Iată lista de verificare Google a cerințelor pentru ca o aplicație să fie considerată o aplicație web progresivă:
- Site-ul este servit prin HTTPS;
- Paginile sunt receptive pe tablete și dispozitive mobile;
- Toate adresele URL ale aplicațiilor se încarcă offline;
- Metadate furnizate pentru Adăugare la ecranul de pornire;
- Mai întâi se încarcă rapid chiar și pe 3G;
- Site-ul funcționează între browsere;
- Tranzițiile de pagină nu par să se blocheze în rețea;
- Fiecare pagină are o adresă URL.
Acum, în plus, dacă vrei cu adevărat să fii animalul de companie al profesorului și ca aplicația ta să fie considerată o „aplicație web exemplificativă progresivă”, atunci ar trebui să îndeplinească și următoarele cerințe:
- Conținutul site-ului este indexat de Google;
- Metadatele Schema.org sunt furnizate acolo unde este cazul;
- Metadatele sociale sunt furnizate acolo unde este cazul;
- URL-urile canonice sunt furnizate atunci când este necesar;
- Paginile folosesc API-ul History;
- Conținutul nu sare pe măsură ce pagina se încarcă;
- Apăsarea înapoi dintr-o pagină de detalii păstrează poziția de defilare pe pagina anterioară de listă;
- Când sunt apăsate, intrările nu sunt ascunse de tastatura de pe ecran;
- Conținutul este ușor de partajat din modul de sine stătător sau pe ecran complet;
- Site-ul răspunde la dimensiunile ecranului de telefon, tabletă și desktop;
- Orice solicitări de instalare a aplicației nu sunt folosite excesiv;
- Solicitarea Adăugați la ecranul de pornire este interceptată;
- Prima încărcare foarte rapidă chiar și pe 3G;
- Site-ul folosește cache-first networking;
- Site-ul informează în mod corespunzător utilizatorul când este offline;
- Oferiți context utilizatorului despre modul în care vor fi utilizate notificările;
- Interfața de utilizare care încurajează utilizatorii să activeze notificările push nu trebuie să fie prea agresivă;
- Site-ul estompează ecranul când se afișează cererea de permisiune;
- Notificările push trebuie să fie în timp util, precise și relevante;
- Oferă controale pentru activarea și dezactivarea notificărilor;
- Utilizatorul este conectat pe toate dispozitivele prin intermediul API-ului de gestionare a acreditărilor;
- Utilizatorul poate plăti cu ușurință prin interfața de utilizare nativă din Payment Request API.
Crikey! Nu știu despre tine, dar a doua grămadă de chestii pare o mulțime de muncă pentru o aplicație de bază! După cum se întâmplă, există o mulțime de elemente care oricum nu sunt relevante pentru ceea ce am planificat. Cu toate acestea, nu mi-e rușine să spun că mi-am coborât privirea pentru a trece doar de testele inițiale.
Pentru o întreagă secțiune de tipuri de aplicații, cred că un PWA este o soluție mai aplicabilă decât o aplicație nativă. Acolo unde jocurile și SaaS au mai mult sens într-un magazin de aplicații, utilitățile mai mici pot trăi destul de fericit și cu mai mult succes pe web ca aplicații web progresive.
În timp ce era vorba despre faptul că mă feresc de munca grea, o altă alegere făcută devreme a fost să încerc să stochezi toate datele pentru aplicație pe dispozitivul utilizatorului. În acest fel, nu ar fi necesar să se conecteze la servicii de date și servere și să se ocupe de autentificări și autentificări. În cazul în care s-au aflat abilitățile mele, să-mi dau seama de autentificare și stocarea datelor utilizatorului părea că aproape sigur că ar fi mai mult decât aș putea să mestec și să exagerez pentru misiunea aplicației!
Opțiuni de tehnologie
Cu o idee destul de clară asupra obiectivului, atenția s-a îndreptat către instrumentele care ar putea fi folosite pentru a-l construi.
Am decis devreme să folosesc TypeScript, care este descris pe site-ul său ca „... un superset tip de JavaScript care se compilează în JavaScript simplu.” Ce am văzut și citit despre limba mi-a plăcut, mai ales faptul că a învățat de la sine atât de bine la analiza statică.
Analiza statică înseamnă pur și simplu că un program poate analiza codul înainte de a-l rula (de exemplu, atunci când este static) și poate evidenția problemele. Nu poate indica neapărat probleme logice, dar poate indica codul neconform cu un set de reguli.
Orice ar putea indica erorile mele (cu siguranță vor fi multe) pe măsură ce mergeam, trebuia să fie un lucru bun, nu?
Dacă nu sunteți familiarizat cu TypeScript, luați în considerare următorul cod în JavaScript vanilla:
console.log(`${count} players`); let count = 0;
Rulați acest cod și veți primi o eroare de genul:
ReferenceError: Cannot access uninitialized variable.
Pentru cei care au chiar și puțină pricepere JavaScript, pentru acest exemplu de bază, nu au nevoie de un instrument care să le spună că lucrurile nu se vor termina bine.
Cu toate acestea, dacă scrieți același cod în TypeScript, acest lucru se întâmplă în editor:
Primesc feedback despre idioția mea chiar înainte de a rula codul! Aceasta este frumusețea analizei statice. Acest feedback a fost adesea ca și cum un dezvoltator mai experimentat stătea alături de mine și prindea erori pe măsură ce mergeam.
TypeScript în primul rând, după cum sugerează și numele, să specificați „tipul” așteptat pentru fiecare lucru din cod. Acest lucru vă împiedică să „constrângeți” din greșeală un tip la altul. Sau încercarea de a rula o metodă pe o bucată de date care nu este aplicabilă - o metodă matrice pe un obiect, de exemplu. Acesta nu este genul de lucru care duce neapărat la o eroare atunci când rulează codul, dar cu siguranță poate introduce erori greu de urmărit. Datorită TypeScript, primiți feedback în editor chiar înainte de a încerca să rulați codul.
TypeScript nu a fost cu siguranță esențial în această călătorie de descoperire și nu aș încuraja pe nimeni să sară pe instrumente de această natură decât dacă există un beneficiu clar. Configurarea instrumentelor și configurarea instrumentelor în primul rând poate fi o pierdere de timp, așa că luați în considerare cu siguranță aplicabilitatea lor înainte de a vă scufunda.
Există și alte beneficii oferite de TypeScript la care vom ajunge în următorul articol din această serie, dar capabilitățile de analiză statică au fost suficiente pentru ca eu să vreau să adopt TypeScript.
Au existat considerente decisive ale alegerilor pe care le făceam. Alegerea de a construi aplicația ca o aplicație web progresivă a însemnat că ar trebui să înțeleg lucrătorii de servicii într-o oarecare măsură. Folosirea TypeScript ar însemna introducerea unor instrumente de construcție. Cum aș gestiona aceste instrumente? Din punct de vedere istoric, am folosit NPM ca manager de pachete, dar cum rămâne cu Yarn? A meritat să folosiți Yarn în schimb? A fi concentrat pe performanță ar însemna să luați în considerare unele instrumente de minificare sau grupare; instrumente precum webpack deveneau din ce în ce mai populare și ar trebui evaluate.
rezumat
Am recunoscut nevoia de a mă lansa în această căutare. Puterile mele JavaScript erau slabe și nimic nu încinge coapsele la fel de mult decât încercarea de a pune teoria în practică. Hotărârea de a construi o aplicație web cu JavaScript vanilie trebuia să fie botezul meu de foc.
Petrecusem ceva timp cercetând și luând în considerare opțiunile de realizare a aplicației și am decis că a face aplicația o aplicație web progresivă avea cel mai mult sens pentru setul meu de abilități și pentru simplitatea relativă a ideii.
Aș avea nevoie de instrumente de construcție, de un manager de pachete și, ulterior, de multă răbdare.
În cele din urmă, în acest moment, întrebarea fundamentală a rămas: era asta ceva ce puteam să mă descurc? Sau aș fi umilit de propria mea ineptitudine?
Sper să vă alăturați mie în partea a doua, când puteți citi despre instrumentele de construcție, modelele de design JavaScript și despre cum să faceți ceva mai „asemănător unei aplicații”.