Conformità per i framework

Conformità nell'ecosistema dei framework JavaScript

Shubhie Panicker
Shubhie Panicker

Nel nostro post del blog introduttivo, abbiamo spiegato quanto abbiamo imparato durante la creazione e l'utilizzo di framework e strumenti per sviluppare e gestire applicazioni web su larga scala come la Ricerca Google, Maps, Foto e così via. Proteggere gli sviluppatori dalla scrittura di codice che può incidere negativamente sull'esperienza utente, abbiamo dimostrato che i framework possono svolgere un ruolo chiave nel migliorare i risultati in termini di prestazioni e qualità delle applicazioni.

All'interno di Google, abbiamo utilizzato il termine "Conformità" per descrivere questa metodologia e questo articolo illustra come intendiamo rendere open source questo concetto per l'ecosistema dei framework JavaScript.

Che cos'è la conformità?

In Google, la conformità è stata un'evoluzione. I team si sono affidati a un piccolo gruppo di manutentori con grande esperienza che hanno eseguito revisioni approfondite del codice, segnalando elementi che influivano sulla qualità e sulla manutenibilità dell'app ben oltre i problemi di correttezza. Per applicare questo approccio a team di sviluppatori di app in crescita, è stato sviluppato un sistema di conformità per codificare le best practice in modo automatizzato e applicabile. In questo modo è stato garantito un livello di qualità e manutenibilità della base di codice delle app costante, indipendentemente dal numero di collaboratori al codice.

La conformità è un sistema che garantisce che gli sviluppatori rimangano sul percorso corretto, incute fiducia e garantisce risultati prevedibili. Rende i team produttivi e diventa fondamentale per scalare, man mano che i team crescono e vengono sviluppate più funzionalità contemporaneamente. Consente agli sviluppatori di concentrarsi sulla creazione di funzionalità dei prodotti, liberandoli da minuzie e dal panorama in continua evoluzione in varie aree come prestazioni, accessibilità, sicurezza e così via. Chiunque può disattivare la conformità in qualsiasi momento e dovrebbe essere personalizzabile nella misura in cui i team avranno la possibilità di applicare ciò che decidono di impegnarsi.

La conformità si basa su valori predefiniti rigorosi e sulla fornitura di regole strategiche che possono essere applicate al momento della creazione. Questi si suddividono nei seguenti tre principi.

1. Valori predefiniti efficaci

Un aspetto fondamentale della conformità è garantire che gli strumenti utilizzati dagli sviluppatori abbiano valori predefiniti efficaci. Ciò significa che le soluzioni non sono solo integrate nei framework, ma anche i pattern di progettazione dei framework semplificano l'adozione delle best practice e rendono difficile seguire gli antipattern. Il framework supporta gli sviluppatori con il design dell'applicazione e la struttura del codice.

Per il rendimento del caricamento, ogni risorsa (caratteri, CSS, JavaScript, immagini e così via) deve essere ottimizzata. Si tratta di una sfida complessa che prevede il taglio dei byte, la riduzione dei round trip e la separazione di ciò che è necessario per il primo rendering, la disponibilità visiva e l'interazione con l'utente. Ad esempio, estrarre il CSS critico e impostare la priorità sulle immagini importanti.

2. Regole di immediata utilità pratica

Anche con le ottimizzazioni di base implementate, gli sviluppatori devono comunque fare delle scelte. Esiste un ampio spettro di possibilità di ottimizzazione in termini di input dello sviluppatore necessario:

  • Impostazioni predefinite che non richiedono l'intervento dello sviluppatore, ad esempio l'inserimento in linea del CSS fondamentale.
  • Richiedere l'attivazione da parte dello sviluppatore. Ad esempio, utilizzando un componente immagine fornito dal framework per ridimensionare le immagini.
  • Richiedere l'attivazione e la personalizzazione da parte dello sviluppatore. Ad esempio, il tagging delle immagini importanti da caricare in anticipo.
  • Non si tratta di una funzionalità specifica, ma di elementi che richiedono comunque la decisione dello sviluppatore. Ad esempio, evitando caratteri o script sincroni che ritardano il rendering anticipato.

Diagramma che mostra un spettro tra le ottimizzazioni automatiche e manuali degli sviluppatori

Le ottimizzazioni che richiedono una decisione da parte degli sviluppatori rappresentano un rischio per il rendimento dell'applicazione. Man mano che le funzionalità vengono aggiunte e il team cresce, anche gli sviluppatori più esperti non riescono a tenere il passo con le best practice in continua evoluzione, né è il miglior utilizzo del loro tempo. Per la conformità, le regole attuabili appropriate sono importanti quanto i valori predefiniti rigorosi per garantire che l'applicazione continui a soddisfare un determinato standard anche quando gli sviluppatori continuano ad apportare modifiche.

3. Ora di creazione

È importante rilevare e impedire i problemi di prestazioni nelle prime fasi del ciclo di vita dello sviluppo. Il momento della creazione, prima del commit del codice, è ideale per rilevare e risolvere i problemi. Quanto più tardi viene rilevato un problema nel ciclo di vita dello sviluppo, più difficile e costoso sarà risolverlo. Sebbene questo valga per i problemi di correttezza, vale anche per i problemi di prestazioni, poiché molti di questi problemi non verranno risolti in modo retroattivo dopo il commit nel codice di base.

Attualmente, la maggior parte del feedback sul rendimento è out-of-band tramite documentazione, controlli una tantum o viene visualizzata troppo tardi tramite la regressione delle metriche dopo il deployment in produzione. Vogliamo che questa funzionalità sia disponibile al momento della creazione.

Conformità nei framework

Per mantenere un livello elevato di esperienza utente per le prestazioni di caricamento, è necessario rispondere alle seguenti domande:

  1. Che cos'è un caricamento ottimale e quali sono i problemi comuni che potrebbero influire negativamente?
  2. Quali soluzioni possono essere integrate e non richiedono l'intervento degli sviluppatori?
  3. Come possiamo assicurarci che lo sviluppatore utilizzi queste soluzioni e le sfrutti in modo ottimale?
  4. Quali altre scelte potrebbe fare lo sviluppatore per influire sul rendimento del caricamento?
  5. Quali sono i pattern di codice che possono indicarci queste scelte (#3 e #4 sopra) in fase di compilazione?
  6. Quali regole possiamo formulare per valutare questi pattern di codice? Come possono essere mostrate allo sviluppatore al momento della creazione, pur essendo integrate perfettamente nel suo flusso di lavoro?

Per portare il modello di conformità che abbiamo internamente in Google ai framework open source, il nostro team ha sperimentato molto in Next.js e siamo lieti di condividere la nostra visione e i nostri piani perfezionati. Abbiamo capito che il miglior insieme di regole che può valutare i pattern di codice dovrà essere una combinazione di analisi statica del codice e controlli dinamici. Queste regole possono essere applicate a più piattaforme, tra cui:

  • ESLint
  • TypeScript
  • Controlli dinamici nel server di sviluppo dell'utente (dopo la creazione del DOM)
  • Modulo di aggregazione dei moduli (webpack)
  • Strumenti CSS (sperimentali)

Sfruttando la possibilità di fornire regole tramite diversi strumenti, possiamo assicurarci che siano coerenti, ma anche che includano eventuali problemi di esperienza utente che influiscono direttamente sulle prestazioni di caricamento. Inoltre, queste regole possono essere mostrate agli sviluppatori anche in momenti diversi:

  • Durante lo sviluppo locale nel server di sviluppo, il browser e l'IDE dell'utente mostreranno avvisi, invitando gli sviluppatori ad apportare piccole modifiche al codice.
  • Al momento della compilazione, i problemi irrisolti verranno visualizzati di nuovo nel terminale dell'utente

In breve, i team sceglieranno i risultati che contano per loro, come i Core Web Vitals o il rendimento del caricamento, e attiveranno i set di regole pertinenti da seguire per tutti i collaboratori al codice.

Sebbene questo funzioni molto bene per i nuovi progetti, non è facile eseguire l'upgrade di basi di codice di grandi dimensioni in modo che rispettino set di regole completi. Google dispone di un sistema completo per la disattivazione a diversi livelli, ad esempio singole righe di codice sorgente, intere directory, codebase legacy o parti dell'app non in fase di sviluppo attivo. Stiamo esplorando attivamente strategie efficaci per offrire questa funzionalità ai team che utilizzano framework open source.

Conformità in Next.js

ESLint è ampiamente utilizzato tra gli sviluppatori JavaScript e oltre il 50% delle applicazioni Next.js utilizza ESLint in una parte del flusso di lavoro di compilazione. La versione 11 di Next.js ha introdotto il supporto di ESLint out-of-the-box che include un plug-in personalizzato e una configurazione condivisibile per semplificare il rilevamento dei problemi comuni specifici del framework durante lo sviluppo e in fase di compilazione. Questo può aiutare gli sviluppatori a risolvere problemi significativi al momento della creazione. Alcuni esempi sono quando un determinato componente viene utilizzato o non utilizzato in modo da danneggiare il rendimento, come nel caso di Nessun link HTML per la pagina. In alternativa, se un determinato carattere, foglio di stile o script può influire negativamente sul caricamento delle risorse in una pagina. Ad esempio, Nessun script sincrono.

Oltre a ESLint, il controllo dei tipi integrato sia in fase di sviluppo che di produzione è supportato in Next.js dalla versione 9 con il supporto di TypeScript. Diversi componenti forniti dal framework (Image, Script, Link) sono stati creati come estensione degli elementi HTML (<img>, <script>, <a>) per offrire agli sviluppatori un approccio efficace per aggiungere contenuti a una pagina web. Il controllo del tipo supporta l'utilizzo appropriato di queste funzionalità garantendo che le proprietà e le opzioni assegnate rientrino nell'ambito accettabile dei valori e dei tipi supportati. Per un esempio, consulta Larghezza e altezza dell'immagine richieste.

Visualizzazione di errori con notifiche popup e overlay

Come accennato in precedenza, le regole di conformità possono essere visualizzate in più aree. Al momento, le notifiche popup e le sovrapposizioni sono in fase di esplorazione come modo per visualizzare gli errori direttamente nel browser all'interno dell'ambiente di sviluppo locale dell'utente.

Errori visualizzati tramite popup

Molti strumenti di controllo e verifica degli errori su cui fanno affidamento gli sviluppatori (Lighthouse, scheda Problemi di Chrome DevTools) sono passivi e richiedono una qualche forma di interazione dell'utente per recuperare le informazioni. Gli sviluppatori sono più propensi ad agire quando gli errori vengono visualizzati direttamente all'interno dei loro strumenti esistenti e quando forniscono azioni concrete e specifiche da intraprendere per risolvere il problema.

Conformità in altri framework

La conformità è in fase di esplorazione in Next.js, con l'obiettivo di espandersi ad altri framework (Nuxt, Angular e così via). ESLint e TypeScript sono già utilizzati in molti framework in molti modi diversi, ma il concetto di un sistema di runtime coerente a livello di browser è in fase di esplorazione attiva.

Conclusione

La conformità codifica le best practice in set di regole che sono utili per gli sviluppatori come semplici pattern di codice. Il team di Aurora si è concentrato sulle prestazioni di caricamento, ma altre best practice, come accessibilità e sicurezza, sono altrettanto applicabili.

Il rispetto delle regole di conformità dovrebbe portare a risultati prevedibili e il raggiungimento di un livello elevato per l'esperienza utente può diventare un effetto collaterale dell'evoluzione della tua tecnologia. La conformità rende i team produttivi e garantisce un livello di qualità elevato per l'applicazione, anche quando i team e le codebase crescono nel tempo.