Progettazione e creazione di un'applicazione Web progressiva senza un framework (parte 3)
Pubblicato: 2022-03-10Nella prima parte di questa serie, abbiamo spiegato perché è nato questo progetto. Vale a dire il desiderio di imparare come una piccola applicazione web potrebbe essere realizzata in JavaScript vanilla e di convincere uno sviluppatore non progettista a lavorare un po' con le sue capacità di progettazione.
Nella seconda parte abbiamo preso alcuni progetti iniziali di base e abbiamo messo le cose in funzione con alcune scelte di strumenti e tecnologie. Abbiamo spiegato come e perché parti del design sono cambiate e le ramificazioni di tali modifiche.
In questa parte finale, tratteremo la trasformazione di un'applicazione Web di base in un'applicazione Web progressiva (PWA) e la "spedizione" dell'applicazione prima di esaminare le lezioni più preziose apprese rendendo la semplice applicazione Web In/Out:
- L'enorme valore dei metodi array JavaScript;
- debug;
- Quando sei l'unico sviluppatore, sei l'altro sviluppatore;
- Il design è sviluppo;
- Manutenzione continua e problemi di sicurezza;
- Lavorare su progetti collaterali senza perdere la testa, la motivazione o entrambe;
- La spedizione di alcuni prodotti batte la spedizione di nessun prodotto.
Quindi, prima di esaminare le lezioni apprese, diamo un'occhiata a come trasformare un'applicazione Web di base scritta in HTML, CSS e JavaScript in un'applicazione Web progressiva (PWA).
In termini di tempo totale speso per realizzare questa piccola applicazione web, direi che probabilmente sono state circa due o tre settimane. Tuttavia, poiché è stato fatto in blocchi di 30-60 minuti strappati la sera, in realtà ci è voluto circa un anno dal primo commit a quando ho caricato quella che considero la versione "1.0" nell'agosto 2018. Dato che avevo l'app " feature complete', o più semplicemente, in una fase di cui ero soddisfatto, ho anticipato una grande spinta finale. Vedete, non avevo fatto nulla per trasformare l'applicazione in un'applicazione Web progressiva. Si scopre che questa era in realtà la parte più semplice dell'intero processo.
Realizzazione di un'applicazione Web progressiva
La buona notizia è che quando si tratta di trasformare una piccola app basata su JavaScript in una "app Web progressiva", ci sono un sacco di strumenti per semplificare la vita. Se ripensi alla prima parte di questa serie, ricorderai che essere un'app Web progressiva significa soddisfare una serie di criteri.
Per avere un'idea di come misura la tua applicazione web, la tua prima tappa dovrebbe essere probabilmente gli strumenti Lighthouse di Google Chrome. Puoi trovare l'audit dell'app Web progressiva nella scheda "Audit".
Questo è ciò che mi ha detto Lighthouse quando l'ho attraversato per la prima volta.
All'inizio In/Out otteneva solo un punteggio di 55 ⁄ 100 per un'app Web progressiva. Tuttavia, l'ho portato da lì a 100 ⁄ 100 in ben meno di un'ora!
L'opportunità di migliorare quel punteggio aveva poco a che fare con le mie capacità. È stato semplicemente perché Lighthouse mi ha detto esattamente cosa era necessario fare!
Alcuni esempi di passaggi necessari: includi un file manifest.json
(essenzialmente un file JSON che fornisce metadati sull'app), aggiungi un'intera serie di meta tag nella testa, cambia le immagini che erano inline nel CSS per le immagini di riferimento URL standard, e aggiungi un sacco di immagini della schermata iniziale.
Creare una serie di immagini della schermata iniziale, creare un file manifest e aggiungere un sacco di meta tag potrebbe sembrare molto da fare in meno di un'ora, ma ci sono meravigliose applicazioni web che ti aiutano a creare applicazioni web. Com'è bello! Ho usato https://app-manifest.firebaseapp.com. Inserisci alcuni dati sulla tua applicazione e sul tuo logo, premi invia e ti fornirà un file zip contenente tutto ciò di cui hai bisogno! Da lì in poi, è solo il momento del copia e incolla.
Cose che rimandavo da tempo per mancanza di conoscenza, come un Service Worker, sono state aggiunte abbastanza facilmente anche grazie a numerosi post di blog e siti dedicati agli operatori di servizio come https://serviceworke.rs. Con un addetto ai servizi in atto significava che l'app poteva funzionare offline, una caratteristica necessaria di un'applicazione Web progressiva.
Sebbene non strettamente correlata al rendere l'applicazione una PWA, anche la scheda "copertura" di Chrome Dev Tools è stata molto utile. Dopo così tante sporadiche iterazioni sul design e sul codice nel corso di mesi, è stato utile ottenere una chiara indicazione di dove c'era codice ridondante. Ho trovato alcune vecchie funzioni che riempiono la base di codice di cui mi ero semplicemente dimenticato!
In breve, dopo aver elaborato le raccomandazioni di audit del faro, mi sono sentito l'animale domestico dell'insegnante:
La realtà è che prendere l'applicazione e renderla un'applicazione Web progressiva è stato in realtà incredibilmente semplice.
Con l'ultimo pezzo di sviluppo concluso, ho caricato la piccola applicazione in un sottodominio del mio sito Web e basta.
Retrospettiva
Sono passati mesi da quando ho interrotto lo sviluppo della mia piccola applicazione web.
Ho usato l'applicazione casualmente nei mesi successivi. La realtà è che gran parte dell'organizzazione sportiva di squadra che faccio avviene ancora tramite SMS. L'applicazione, tuttavia, è decisamente più semplice che scrivere chi è dentro e fuori che trovare un pezzo di carta ogni notte di gioco.
Quindi, la verità è che non è certo un servizio indispensabile. Né stabilisce alcun limite per lo sviluppo o la progettazione. Non posso dirti nemmeno che sono soddisfatto al 100%. Sono appena arrivato a un punto in cui ero felice di abbandonarlo.
Ma non è mai stato questo il punto dell'esercizio. Ho preso molto dall'esperienza. Quelli che seguono sono quelli che considero i più importanti da asporto.
Il design è sviluppo
All'inizio, non apprezzavo abbastanza il design. Ho iniziato questo progetto credendo che il tempo trascorso a disegnare con un pad e una penna o nell'applicazione Sketch fosse tempo che avrebbe potuto essere speso meglio con la programmazione. Tuttavia, quando passavo direttamente al codice, spesso ero solo un pazzo indaffarato. Esplorare i concetti prima con la fedeltà più bassa possibile, ha fatto risparmiare molto più tempo a lungo termine.
All'inizio c'erano numerose occasioni in cui si passavano ore a far funzionare qualcosa nel codice solo per rendersi conto che era fondamentalmente imperfetto dal punto di vista dell'esperienza dell'utente.
La mia opinione ora è che carta e matita siano i migliori strumenti di pianificazione, design e codifica. Ogni problema significativo affrontato è stato risolto principalmente con carta e matita; l'editor di testo è semplicemente un mezzo per eseguire la soluzione. Senza qualcosa che abbia un senso sulla carta, non ha alcuna possibilità di lavorare nel codice.
La prossima cosa che ho imparato ad apprezzare, e non so perché ci sia voluto così tanto tempo per capire, è che il design è iterativo. Inconsciamente avevo creduto al mito di un Designer con la “D” maiuscola. Qualcuno che saltella in giro, tenendo la matita meccanica in alto sui bordi dritti, cerando i testi sui caratteri tipografici e sorseggiando un bianco piatto (con latte di soia, ovviamente) prima di far nascere casualmente nel mondo la perfezione visiva completamente formata.
Questo, non diversamente dalla nozione di programmatore "geniale", è un mito. Se sei nuovo nel design ma ci stai provando, ti suggerirei di non rimanere bloccato dalla prima idea che suscita la tua eccitazione. È così economico provare le varianti, quindi abbraccia questa possibilità. Nessuna delle cose che mi piace del design di In/Out era presente nei primi progetti.
Credo sia stato il romanziere, Michael Crichton, a coniare la massima: "I libri non si scrivono, si riscrivono". Accetta che ogni processo creativo è essenzialmente lo stesso. Sii consapevole del fatto che la fiducia nel processo riduce l'ansia e la pratica raffinerà la tua comprensione e il tuo giudizio estetico.
Tu sei l'altro sviluppatore del tuo progetto
Non sono sicuro che questo sia specifico per i progetti su cui si lavora solo sporadicamente, ma ho fatto la seguente ipotesi avventata:
"Non ho bisogno di documentare nulla di tutto ciò perché sono solo io, e ovviamente lo capirò perché l'ho scritto io".
Nulla potrebbe essere più lontano dalla verità!
C'erano serate in cui, per i 30 minuti che dovevo lavorare al progetto, non facevo altro che cercare di capire una funzione che avevo scritto sei mesi fa. I motivi principali per cui il riorientamento del codice ha richiesto così tanto tempo è stata la mancanza di commenti di qualità e variabili e argomenti di funzione con nomi scadenti.
Sono molto diligente nel commentare il codice nel mio lavoro quotidiano, sempre consapevole che qualcun altro potrebbe aver bisogno di dare un senso a ciò che sto scrivendo. Tuttavia, in questo caso, io ero quel qualcun altro. Pensi davvero che ti ricorderai come funziona il blocco di codice che hai scritto tra sei mesi? Non lo farai. Credimi su questo, prenditi una pausa e commenta quella cosa!
Da allora ho letto un post sul blog intitolato Il tuo evidenziatore di sintassi è sbagliato sull'argomento dell'importanza dei commenti. La premessa di base è che gli evidenziatori di sintassi non dovrebbero sbiadire i commenti, dovrebbero essere la cosa più importante. Sono propenso ad essere d'accordo e se non trovo presto un tema per l'editor di codice che graffia quel prurito, potrei doverne adattarne uno io stesso!
Debug
Quando si riscontrano dei bug e si è scritto tutto il codice, non è ingiusto suggerire che l'errore sia probabilmente originato tra la tastiera e la sedia. Tuttavia, prima di presumerlo, ti suggerirei di testare anche le tue ipotesi più elementari. Ad esempio, ricordo di aver impiegato più di due ore per risolvere un problema che pensavo fosse dovuto al mio codice; in iOS non riuscivo proprio a far sì che la mia casella di input accettasse l'immissione di testo. Non ricordo perché non mi avesse fermato prima, ma ricordo la mia frustrazione per il problema.
Si scopre che era dovuto a un bug, ancora da correggere, in Safari. Si scopre che in Safari se hai:
* { user-select: none; }
Nel tuo foglio di stile, le caselle di input non accettano alcun input. Puoi aggirare questo problema con:
* { user-select: none; } input[type] { user-select: text; }
Qual è l'approccio che adotto nel mio ripristino CSS "App Reset". Tuttavia, la parte davvero frustrante di questo era che l'avevo già imparato e successivamente l'avevo dimenticato. Quando finalmente sono riuscito a controllare il monitoraggio dei bug di WebKit durante la risoluzione del problema, ho scoperto di aver scritto una soluzione alternativa nel thread di segnalazione dei bug più di un anno fa, completa di riduzione!
Vuoi costruire con i dati? Impara i metodi di array JavaScript
Forse il più grande progresso che le mie abilità JavaScript hanno preso sottoponendomi a questo esercizio di creazione di app è stato familiarizzare con i metodi JavaScript Array. Ora li uso quotidianamente per tutte le mie esigenze di iterazione e manipolazione dei dati. Non posso sottolineare abbastanza quanto siano utili metodi come map()
, filter()
, every()
, findIndex()
, find()
e reduce()
. Puoi risolvere praticamente qualsiasi problema di dati con loro. Se non li hai già nel tuo arsenale, aggiungi https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array ora e accedi non appena puoi. Il mio riassunto dei miei metodi di array preferiti è documentato qui.
ES6 ha introdotto altri risparmiatori di tempo per la manipolazione di array, come Set
, Rest
e Spread
. Assecondami mentre condivido un esempio; c'erano un sacco di cazzate se si desidera rimuovere i duplicati anche da un semplice array piatto. Non più.
Considera questo semplice esempio di un array con la voce duplicata, "Mr Pink":
let myArray = [ "Mr Orange", "Mr Pink", "Mr Brown", "Mr White", "Mr Blue", "Mr Pink" ];
Per eliminare i duplicati con ES6 JavaScript ora puoi semplicemente fare:
let deDuped = [...new Set(myArray)]; // deDuped logs ["Mr Orange", "Mr Pink", "Mr Brown", "Mr White", "Mr Blue"]
Qualcosa che prima richiedeva l'arrotolamento manuale di una soluzione o il raggiungimento di una libreria ora è integrato nel linguaggio. Certo, su array così brevi che potrebbero non sembrare un grosso problema, ma immagina quanto tempo si risparmia quando si guardano array con centinaia di voci e duplicati.
Manutenzione e sicurezza
Tutto ciò che crei che fa uso di NPM, anche se solo per strumenti di compilazione, comporta la possibilità di essere vulnerabile a problemi di sicurezza. GitHub fa un buon lavoro nel tenerti informato sui potenziali problemi, ma c'è ancora qualche onere di manutenzione.
Per qualcosa che è un semplice progetto collaterale, questo può essere un po' una seccatura nei mesi e negli anni che seguono lo sviluppo attivo.
La realtà è che ogni volta che aggiorni le dipendenze per risolvere un problema di sicurezza, introduci la possibilità di rompere la tua build.
Per mesi, il mio package.json
simile a questo:
{ "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" } }
E a giugno 2019, ricevevo questi avvisi da GitHub:
Nessuno era correlato ai plug-in che stavo usando direttamente, erano tutte dipendenze secondarie degli strumenti di compilazione che avevo usato. Tale è l'arma a doppio taglio dei pacchetti JavaScript. Per quanto riguarda l'app stessa, non ci sono stati problemi con In/Out; che non stava usando nessuna delle dipendenze del progetto. Ma poiché il codice era su GitHub, mi sono sentito in dovere di provare a sistemare le cose.
È possibile aggiornare i pacchetti manualmente, con alcune modifiche alla scelta di package.json. Tuttavia, sia Yarn che NPM hanno i propri comandi di aggiornamento. Ho scelto di eseguire l' yarn upgrade-interactive
che ti offre un mezzo semplice per aggiornare le cose dal terminale.
Sembra abbastanza facile, c'è anche un piccolo tasto colorato per dirti quali aggiornamenti sono più importanti.
È possibile aggiungere il flag --latest
per eseguire l'aggiornamento all'ultima versione principale delle dipendenze, anziché solo all'ultima versione patchata. In per un centesimo...
Il problema è che le cose si muovono velocemente nel mondo dei pacchetti JavaScript, quindi l'aggiornamento di alcuni pacchetti all'ultima versione e quindi il tentativo di build hanno portato a questo:
Pertanto, ho ripristinato il mio file package.json
e ho riprovato questa volta senza il flag --latest
. Questo ha risolto i miei problemi di sicurezza. Non è stato il massimo divertimento che ho avuto un lunedì sera, anche se sarò onesto.
Ciò tocca una parte importante di qualsiasi progetto collaterale. Essere realistici con le tue aspettative.
Progetti collaterali
Non so se siete uguali ma ho scoperto che un ottimismo vertiginoso e un'eccitazione mi fanno iniziare dei progetti e se qualcosa lo fa, l'imbarazzo e il senso di colpa me li fanno finire.
Sarebbe una bugia dire che l'esperienza di creare questa piccola applicazione nel mio tempo libero è stata divertente. Ci sono state occasioni in cui vorrei non aver mai aperto bocca a nessuno. Ma ora è fatto, sono convinto al 100% che ne sia valsa la pena il tempo investito.
Detto questo, è possibile mitigare la frustrazione per un simile progetto collaterale essendo realistici su quanto tempo ci vorrà per capire e risolvere i problemi che devi affrontare. Hai solo 30 minuti a notte, poche notti a settimana? Puoi ancora completare un progetto secondario; non essere scontento se il tuo ritmo sembra glaciale. Se le cose non possono godere della tua piena attenzione, preparati a un ritmo più lento e costante di quello a cui forse sei abituato. È vero, che si tratti di programmare, completare un corso, imparare a destreggiarsi o scrivere una serie di articoli sul perché ci è voluto così tanto tempo per scrivere una piccola applicazione web!
Semplice definizione degli obiettivi
Non hai bisogno di un processo di fantasia per la definizione degli obiettivi. Ma potrebbe aiutare a scomporre le cose in compiti piccoli/brevi. Cose semplici come "scrivi CSS per il menu a discesa" sono perfettamente realizzabili in uno spazio di tempo limitato. Mentre "ricercare e implementare un modello di progettazione per la gestione statale" probabilmente non lo è. Rompi le cose. Quindi, proprio come i Lego, i piccoli pezzi si uniscono.
Pensando a questo processo come a un'eliminazione del problema più grande, mi viene in mente la famosa citazione di Bill Gates:
"La maggior parte delle persone sopravvaluta ciò che può fare in un anno e sottovaluta ciò che può fare in dieci anni".
Questo da un uomo che sta aiutando a sradicare la poliomielite. Bill sa il fatto suo. Ascolta Bill tutti voi.
Spedire qualcosa è meglio che spedire niente
Prima di "spedire" questa applicazione web, ho rivisto il codice e sono rimasto completamente scoraggiato.
Sebbene avessi intrapreso questo viaggio da un punto di completa ingenuità e inesperienza, avevo fatto alcune scelte decenti quando si trattava di come progettare (se perdoni un termine così grandioso) il codice. Avevo studiato e implementato un modello di progettazione e mi era piaciuto tutto ciò che il modello aveva da offrire. Purtroppo, mentre diventavo più disperato per concludere il progetto, non sono riuscito a mantenere la disciplina. Il codice così com'è è un vero miscuglio di approcci e pieno di inefficienze.
Nei mesi trascorsi mi sono reso conto che quelle carenze non contano davvero. Non proprio.
Sono un fan di questa citazione di Helmuth von Moltke.
"Nessun piano operativo si estende con certezza oltre il primo contatto con la principale forza ostile".
Questo è stato parafrasato come:
“Nessun piano sopravvive al primo contatto con il nemico”.
Forse possiamo ridurlo ulteriormente e semplicemente andare con "merda succede"?
Posso supporre il mio venire a patti con ciò che è stato spedito tramite la seguente analogia.
Se un amico avesse annunciato che avrebbe provato a correre la sua prima maratona, sarebbe stato tutto ciò che contava superare il traguardo: non li avrei rimproverati per il loro tempo di arrivo.
Non ho deciso di scrivere la migliore applicazione web. Il compito che mi ero prefissato era semplicemente quello di progettarne uno e realizzarne uno.
Più specificamente, dal punto di vista dello sviluppo, volevo imparare i fondamenti di come è stata costruita un'applicazione web. Da un punto di vista progettuale, volevo provare a risolvere alcuni problemi di progettazione (anche se semplici) per conto mio. Realizzare questa piccola applicazione ha soddisfatto quelle sfide e poi alcune. Il JavaScript per l'intera applicazione era di soli 5 KB (gzippato). Una piccola dimensione del file che faticherei a raggiungere con qualsiasi framework. Tranne forse Svelte.
Se ti stai proponendo una sfida di questa natura e ti aspetti di "spedire" qualcosa a un certo punto, scrivi all'inizio il motivo per cui lo stai facendo. Tieni queste ragioni in primo piano nella tua mente e lasciati guidare da esse. Tutto è in definitiva una sorta di compromesso. Non lasciare che gli ideali elevati ti paralizzino nel finire ciò che ti sei prefissato di fare.
Sommario
Nel complesso, poiché è passato un anno da quando ho lavorato a In/Out, i miei sentimenti rientrano sostanzialmente in tre aree: cose di cui mi sono pentito, cose che vorrei migliorare/aggiustare e possibilità future.
Cose di cui mi sono pentito
Come già accennato, sono rimasto deluso di non essere rimasto fedele a quello che consideravo un metodo più elegante per cambiare lo stato dell'applicazione e renderla al DOM. Il modello dell'osservatore, come discusso nella seconda parte di questa serie, che ha risolto così tanti problemi in modo prevedibile è stato infine messo da parte poiché la "spedizione" del progetto è diventata una priorità.
All'inizio ero imbarazzato dal mio codice, ma nei mesi successivi sono diventato più filosofico. Se non avessi usato più tecniche pedonali in seguito, c'è una possibilità molto reale che il progetto non si sarebbe mai concluso. Portare fuori qualcosa nel mondo che deve essere migliorato è ancora meglio di quanto non sia mai nato nel mondo.
Miglioramento in entrata/uscita
Oltre a scegliere il markup semantico, non avevo fatto concessioni per l'accessibilità. Quando ho creato In/Out ero sicuro dell'accessibilità standard delle pagine Web ma non sufficientemente informato per affrontare un'applicazione. Ora ho svolto molto più lavoro/ricerca in quell'area, quindi mi piacerebbe dedicare del tempo a fare un lavoro decente per rendere questa applicazione più accessibile.
L'implementazione del design rivisto della funzionalità "Aggiungi persona" è stata affrettata. Non è un disastro, solo un po' più ruvido di quanto vorrei. Sarebbe bello renderlo più liscio.
Inoltre non ho preso in considerazione gli schermi più grandi. Sarebbe interessante considerare le sfide progettuali di farlo funzionare a dimensioni maggiori, oltre a renderlo semplicemente un tubo di contenuto.
Possibilità
L'uso di localStorage ha funzionato per le mie esigenze semplicistiche, ma sarebbe bello avere un archivio dati "corretto", quindi non era necessario preoccuparsi di eseguire il backup dei dati. L'aggiunta della funzionalità di accesso aprirebbe anche la possibilità di condividere l'organizzazione del gioco con un altro individuo. O forse ogni giocatore potrebbe semplicemente segnare se stava giocando da solo? È incredibile quante strade da esplorare puoi immaginare da un inizio così semplice e umile.
Anche lo sviluppo di app SwiftUI per iOS è interessante. Per qualcuno che ha sempre lavorato solo con le lingue web, a prima vista, SwiftUI sembra qualcosa che ora sono incoraggiato a provare. Probabilmente proverei a ricostruire In/Out con SwiftUI, solo per avere qualcosa di specifico da costruire e confrontare l'esperienza di sviluppo e i risultati.
E quindi, è il momento di concludere e darti la versione TL; DR di tutto questo.
Se vuoi imparare come funziona qualcosa sul web, ti suggerisco di saltare le astrazioni. Abbandona i framework, che si tratti di CSS o JavaScript fino a quando non capisci davvero cosa fanno per te.
Il design è iterativo, abbraccia quel processo.
Risolvi i problemi nel mezzo di fedeltà più basso a tua disposizione. Non andare al codice se puoi testare l'idea in Sketch. Non disegnarlo in Sketch se puoi usare carta e penna. Scrivi prima la logica. Quindi scrivilo in codice.
Sii realistico ma mai scoraggiato. Sviluppare l'abitudine di scheggiare qualcosa per un minimo di 30 minuti al giorno può ottenere risultati. Questo fatto è vero qualunque sia la forma che assume la tua ricerca.