Recentemente abbiamo realizzato un’app per IMECO, un’azienda Cremonese. L’app è stata utilizzata durante una importante fiera del settore ed è stata poi distribuita a tutti gli agenti dell’azienda in giro per il mondo.
Modelli 3D e oltre
Tra le feature salienti dell’app c’è sicuramente la possibilità di visionare i modelli 3D dei macchinari prodotti dall’azienda tramite un widget interattivo realizzato interamente da noi. Dedicheremo un post del blog più avanti solo a questo argomento in quanto è stato molto interessante realizzare un componente che dovesse essere sia molto performante che utilizzabile in maniera intuitiva.
MA
Oggi non vi voglio parlare nello specifico dell’app in quanto tale ma piuttosto degli strumenti che abbiamo utilizzato per realizzarla.
Il problema
Lo sviluppo di questa app ha presentato una serie di criticità:
- In primo luogo tempi strettissimi e non posticipabili, l’app doveva essere assolutamente pronta per la fiera!
- Funzionamento completamente offline, tutte le risorse (schemi, foto, video, modelli 3d) dovevano essere disponibili anche in assenza di connessione alla rete
- Tantissime risorse multimediali da incorporare nell’app: alcune migliaia di immagini e decine di video
- La generazione una versione esportabile in formato pdf di ogni macchinario presente nell’app
Da un punto di vista un po’ più concreto, tutte le problematiche elencate sopra si sono tradotte nelle seguenti domande:
- Come facciamo a ridimensionare, ritagliare e ottimizzare tutte le immagini dei prodotti presenti nell’app e ad organizzarle in una struttura gerarchica adeguata?
- Come facciamo a scaricare tutti i video da YouTube per renderli disponibili offline?
- Come facciamo a generare in maniera completamente automatizzata tutti i PDF dei prodotti presenti nell’app?
Se i tempi fossero stati meno stretti e le risorse da elaborare meno numerose avremmo potuto tranquillamente procedere manualmente ad effettuare le varie operazioni richieste, ma in questo caso specifico abbiamo dovuto automatizzare tutti i processi in modo da:
- Rendere le operazioni eseguibili da qualsiasi membro del team di sviluppo, per evitare la classica situazione dove c’è un solo membro del team che si ricorda a memoria come ottimizzare le immagini e che è l’unico ad avere installato sul proprio laptop tutti i software necessari
- Ridurre al minimo la possibilità di errore: inutile dire che se eseguiamo a mano la stessa operazione 100 volte non importa quanta attenzione ci mettiamo ma inevitabilmente sbaglierei almeno un paio di volte
- Aumentare al massimo la produttività del team: uno sviluppatore che perde tempo a spostare dei file da una cartella all’altra si traduce inevitabilmente in una perdita anche economica.
Lo strumento: CLI
Il pensiero di svolgere manualmente tutte quelle operazioni non ci è mai nemmeno passato per l’anticamera del cervello. Siamo sviluppatori, no? Scrivere del codice non ci spaventa e se non troviamo gli strumenti adatti per migliorare il nostro lavoro possiamo rimboccarci le maniche e crearli!
L’idea di base era molto semplice: realizzare una CLI che permettesse tramite un prompt interattivo di lanciare i task automatizzati.
Cos’è una CLI? Come dice il nome stesso, una Command Line Interface non è altro che uno strumento che ci permette di eseguire una serie di operazioni tramite il terminale. La CLI è spesso interattiva, ovvero ci guida passo passo nella configurazione del task che vogliamo eseguire. Moltissimi framework e tool moderni si basano su una CLI: Angular, Ionic, Firebase, ecc.
Da sviluppatori puramente web ci siamo chiesti: ma come si fa una CLI? Temevamo di dover ricorrere a qualche linguaggio vecchio e macchinoso, e invece no. La risposta come capita molto spesso in questi anni è stata Node.js.
Node.js
Node.js è niente meno che una runtime basata sull’engine JavaScript di Chrome. Con Node.js si può fare di tutto: da un package manager ad un web server altamente performante. Sto già vedendo la vostra faccia in questo momento: un web server, in JavaScript?!?! Ebbene sì! Il backend della nostra app Do It, che conta decine di migliaia di download è stato realizzato proprio con Node.js, ma torniamo a noi.
Librerie e tool
Tra i fattori veramente interessati di Node.js c’è sicuramente la sua semplicità di utilizzo: basta installare la runtime adatta al nostro sistema operativo e siamo pronti!
Per Node.js sono state realizzati dalla community migliaia di tool e librerie, tra cui troviamo inquirer.
Inquirer ci permette di realizzare una CLI interattiva con funzionalità molto interessanti.
All’avvio la nostra CLI mostra un menù a scelta multipla tra i vari task eseguibili. Una volta selezionato il task vengono poi proposte una serie di domande specifiche di configurazione del task stesso. Una volta inserite tutte le risposte il task viene eseguito.
Uno dei task più importanti è sicuramente quello relativo alla manipolazione delle immagini. Abbiamo risolto tutti i nostri problemi utilizzando sharp. Sharp è una libreria node che permette di eseguire tutte le classiche operazioni di manipolazione delle immagini: resize, crop, esportazione in vari formati ecc.
Per la parte di ottimizzazione finale di tutte le risorse grafiche abbiamo utilizzato imagemin con i relativi plugin per l’ottimizzazione di JPEG e PNG.
Tutte le risorse generate poi andavano organizzate in una struttura di cartelle ben definita per evitare di perdersi tra le migliaia di immagini presenti. Per la generazione di cartelle ed, in maniera più generica, per l’interazione con la Shell di sistema abbiamo utilizzato shelljs.
Shelljs non è altro che un wrapper che ci permette di utilizzare l’interfaccia di node con la Shell di sistema in maniera semplice ed immediata. Abbiamo utilizzato shelljs per creare cartelle, spostare, copiare ed eliminare file, ma anche per lanciare comandi arbitrari nella Shell di sistema (vedremo più avanti ad esempio i comandi ghostscript).
Parliamo ora dei video. La maggior parte dei video che abbiamo inserito nell’app sono stati acquisiti dal canale YouTube dell’azienda. Se non avete accesso al canale (come nel nostro caso) un modo molto rapido per scaricare i video è utilizzare ytdl-core, una libreria molto comoda che permette di scaricare un video e la relativa thumbnail alla risoluzione che preferiamo. Anche in questo caso i video venivano poi organizzati in cartelle gerarchiche create con shelljs.
Veniamo ora al pezzo forte, quello che ci ha dato più soddisfazione e ci ha fatto risparmiare più tempo. Per ogni prodotto presente nell’app avremmo dovuto generare un PDF. L’app è stata realizzata con tecnologie ibride quindi il tutto si riduceva a esportare un PDF tramite Chrome, se non che i prodotti in oggetto erano più di 40, ed ogni prodotto è stato esportato più volte in quanto il processo di impostazione grafica e di inserimento dei contenuti erano assolutamente parallelizzati per ottimizzare i tempi.
Non molto tempo fa Google ha rilasciato headless Chrome, la versione controllabile programmaticamente del browser Chrome. Parallelamente a headless Chrome è stato anche rilasciato puppeteer, un wrapper che permette di controllare headless Chrome tramite node. Generare tutti i PDF dei prodotti è stato semplice come invocare una funzione di puppeteer.
I PDF generati però erano molto pesanti e questo non era un problema da poco in quanto i PDF sarebbero dovuti finire allegati ad una email. Per comprimere i PDF non abbiamo trovato alcuna libreria node ed abbiamo quindi ripiegato su ghostscript, un tool da riga di comando che permette di ridurre in maniera considerevole le dimensioni dei PDF, senza sacrificare minimamente la qualità. Per lanciare il comando ghostscript da node abbiamo utilizzato shelljs.
Manca solo la ciliegina sulla torta: visto che la maggior parte dei task richiede anche alcuni minuti per terminare, abbiamo utilizzato progress per dare un feedback visivo sullo stato di avanzamento del task.
Eccoci arrivati in fondo a questa carrellata. Ho voluto condividere con voi questi strumenti perché ci hanno davvero dato una mano fondamentale nel terminare il progetto nei tempi stabiliti riducendo praticamente a zero la possibilità di errore. Node è oggettivamente uno strumento davvero potente e l’ecosistema di tool e librerie che si trovano online lo rendono adatto a svolgere i compiti più disparati. Se scrivere codice JavaScript vi spaventa potete sempre ricorrere a Typescript, che rende JavaScript un po’ più digeribile agli affezionati della tipizzazione.
Voglio però condividere con voi anche una riflessione un po più ad ampio spettro. Con questo articolo spero di essere riuscito a dimostrare che anche quando i tempi sono stretti, anche quando il team di sviluppo è ridotto ad un paio di individui, lavorare bene e in maniera produttiva e organizzata si può fare, basta trovare gli strumenti giusti e, soprattutto, basta volerlo.