Rimuovi il codice inutilizzato

In questo codelab, migliora le prestazioni della seguente applicazione rimuovendo le dipendenze inutilizzate e non necessarie.

Screenshot dell'app

Misura

È sempre opportuno misurare il rendimento di un sito web prima di aggiungere le ottimizzazioni.

  • Per visualizzare l'anteprima del sito, premi Visualizza app, quindi Schermo intero schermo intero.

Vai avanti e fai clic sul tuo gattino preferito! In questa applicazione viene utilizzato il Realtime Database di Firebase, per questo il punteggio viene aggiornato in tempo reale ed è sincronizzato con tutte le altre persone che utilizzano l'applicazione. 🐈

  1. Premi "Control+Maiusc+J" (o "Comando+Opzione+J" su Mac) per aprire DevTools.
  2. Fai clic sulla scheda Rete.
  3. Seleziona la casella di controllo Disabilita cache.
  4. Ricarica l'app.

Dimensione originale del bundle: 992 kB

Per caricare questa semplice applicazione è stato inviato un codice JavaScript del valore di quasi 1 MB.

Dai un'occhiata agli avvisi relativi al progetto in DevTools.

  • Fai clic sulla scheda Console.
  • Assicurati che Warnings sia abilitato nel menu a discesa dei livelli accanto all'input Filter.

Filtro avvisi

  • Dai un'occhiata all'avviso visualizzato.

Avviso della console

Firebase, che è una delle librerie utilizzate in questa applicazione, si comporta bene fornendo un avviso per comunicare agli sviluppatori di non importare l'intero pacchetto, ma solo i componenti utilizzati. In altre parole, ci sono librerie inutilizzate che possono essere rimosse in questa applicazione per velocizzarne il caricamento.

Esistono anche casi in cui viene utilizzata una particolare libreria, ma in cui potrebbe esserci un'alternativa più semplice. Il concetto di rimozione delle librerie non necessarie viene esplorato più avanti in questo tutorial.

Analisi del bundle in corso...

L'applicazione ha due dipendenze principali:

  • Firebase: una piattaforma che fornisce una serie di servizi utili per le applicazioni web, iOS o Android. Qui il suo Realtime Database viene utilizzato per archiviare e sincronizzare le informazioni per ogni gattino in tempo reale.
  • Moment.js: una libreria di utilità che semplifica la gestione delle date in JavaScript. La data di nascita di ogni gattino è archiviata nel database di Firebase e moment viene utilizzato per calcolarne l'età in settimane.

In che modo solo due dipendenze possono contribuire a una dimensione bundle di quasi 1 MB? Uno dei motivi è che ogni dipendenza può a sua volta avere dipendenze proprie, quindi ce ne sono molto di più di due, se si considera ogni profondità/ramo dell'"albero" delle dipendenze. È facile che un'applicazione diventi grande in modo relativamente rapido, se si includono molte dipendenze.

Analizza il bundler per capire meglio cosa sta succedendo. Esistono vari strumenti creati dalla community che possono aiutarti a farlo, ad esempio webpack-bundle-analyzer.

Il pacchetto di questo strumento è già incluso nell'app come devDependency.

"devDependencies": {
  //...
  "webpack-bundle-analyzer": "^2.13.1"
},

Ciò significa che può essere utilizzata direttamente nel file di configurazione del webpack. Importalo all'inizio di webpack.config.js:

const path = require("path");

//...
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;

Ora aggiungilo come plug-in alla fine del file all'interno dell'array plugins:

module.exports = {
  //...
  plugins: [
    //...
    new BundleAnalyzerPlugin()
  ]
};

Quando l'applicazione si ricarica, dovresti vedere una visualizzazione dell'intero bundle anziché dell'app stessa.

Strumento di analisi bundle Webpack

Non è così carino come vedere alcuni gattini 🐱, ma comunque incredibilmente utili. Quando passi il mouse su un pacchetto, vengono visualizzate le dimensioni rappresentate in tre modi diversi:

Dimensioni stat Dimensioni prima di qualsiasi minimizzazione o compressione.
Dimensione analizzata Dimensioni del pacchetto effettivo all'interno del bundle dopo la sua compilazione. La versione 4 del webpack (utilizzata in questa applicazione) minimizza automaticamente i file compilati, motivo per cui sono inferiori alle dimensioni della statistica.
Dimensioni compresso con gzip Dimensioni del pacchetto dopo la compressione con la codifica gzip. Questo argomento è trattato in una guida separata.

Con lo strumento webpack-bundle-analyzer, è più facile identificare i pacchetti inutilizzati o non necessari che costituiscono una percentuale elevata del bundle.

Rimozione dei pacchetti inutilizzati

La visualizzazione mostra che il pacchetto firebase è costituito da molto di più di un semplice database. Include pacchetti aggiuntivi quali:

  • firestore
  • auth
  • storage
  • messaging
  • functions

Si tratta di tutti gli straordinari servizi offerti da Firebase (per saperne di più, consulta la documentazione), ma nessuno di questi viene utilizzato nell'applicazione, perciò non c'è motivo di importarli tutti.

Ripristina le modifiche in webpack.config.js per visualizzare di nuovo l'applicazione:

  • Rimuovi BundleAnalyzerPlugin dall'elenco dei plug-in:
plugins: [
  //...
  new BundleAnalyzerPlugin()
];
  • Ora rimuovi l'importazione inutilizzata dalla parte superiore del file:
const path = require("path");

//...
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

L'applicazione dovrebbe caricarsi normalmente. Modifica src/index.js per aggiornare le importazioni di Firebase.

import firebase from 'firebase';
import firebase from 'firebase/app';
import 'firebase/database';

Ora, quando l'app viene ricaricata, l'avviso DevTools non viene visualizzato. L'apertura del riquadro Rete di DevTools mostra anche una nitida riduzione delle dimensioni dei bundle:

Dimensioni del bundle ridotte a 480 kB

Oltre la metà delle dimensioni del bundle è stata rimossa. Firebase fornisce molti servizi diversi e offre agli sviluppatori la possibilità di includere solo quelli effettivamente necessari. In questa applicazione è stato utilizzato solo firebase/database per archiviare e sincronizzare tutti i dati. L'importazione firebase/app, che configura la piattaforma API per ciascuno dei diversi servizi, è sempre obbligatoria.

Molte altre librerie note, come lodash, consentono inoltre agli sviluppatori di importare selettivamente diverse parti dei loro pacchetti. Senza fare molto lavoro, l'aggiornamento delle importazioni delle librerie in un'applicazione in modo da includere solo ciò che viene utilizzato può portare a miglioramenti significativi delle prestazioni.

Anche se le dimensioni del bundle sono diminuite di molto, devi fare ancora altro. 😈

Rimozione dei pacchi non necessari

A differenza di Firebase, l'importazione di parti della libreria moment non può essere eseguita con la stessa facilità, ma forse è possibile rimuoverla del tutto?

Il compleanno di ogni tenero gattino è memorizzato in formato Unix (millisecondi) nel database Firebase.

Date di nascita memorizzate in formato Unix

Si tratta di un timestamp di una data e un'ora specifiche, rappresentate dal numero di millisecondi trascorsi dal 1° gennaio 1970 (00:00 UTC). Se la data e l'ora correnti possono essere calcolate nello stesso formato, è probabile che si possa creare una piccola funzione per trovare l'età di ogni gattino in settimane.

Come sempre, non copiare e incollare seguendo questa procedura. Inizia rimuovendo moment dalle importazioni in src/index.js.

import firebase from 'firebase/app';
import 'firebase/database';
import * as moment from 'moment';

Esiste un listener di eventi Firebase che gestisce le modifiche ai valori nel nostro database:

favoritesRef.on("value", (snapshot) => { ... })

Sopra, aggiungi una piccola funzione per calcolare il numero di settimane a partire da una determinata data:

const ageInWeeks = birthDate => {
  const WEEK_IN_MILLISECONDS = 1000 * 60 * 60 * 24 * 7;
  const diff = Math.abs((new Date).getTime() - birthDate);
  return Math.floor(diff / WEEK_IN_MILLISECONDS);
}

In questa funzione, la differenza in millisecondi tra la data e l'ora correnti (new Date).getTime() e la data di nascita (l'argomento birthDate, già in millisecondi) viene calcolata e divisa per il numero di millisecondi in una singola settimana.

Infine, puoi rimuovere tutte le istanze di moment nel listener di eventi utilizzando questa funzione:

favoritesRef.on("value", (snapshot) => {
  const { kitties, favorites, names, birthDates } = snapshot.val();
  favoritesScores = favorites;

  kittiesList.innerHTML = kitties.map((kittiePic, index) => {
    const birthday = moment(birthDates[index]);

    return `
      <li>
        <img src=${kittiePic} onclick="favKittie(${index})">
        <div class="extra">
          <div class="details">
            <p class="name">${names[index]}</p>
            <p class="age">${moment().diff(birthday, 'weeks')} weeks old</p>
            <p class="age">${ageInWeeks(birthDates[index])} weeks old</p>
          </div>
          <p class="score">${favorites[index]} ❤</p>
        </div>
      </li>
    `})
});

Ora ricarica l'applicazione e dai un'altra occhiata al riquadro Rete.

Dimensioni del bundle ridotte a 225 kB

Le dimensioni del nostro bundle si sono nuovamente ridotte di oltre la metà.

Conclusione

Con questo codelab, dovresti avere una buona conoscenza di come analizzare un determinato bundle e perché può essere così utile rimuovere i pacchetti inutilizzati o non necessari. Prima di iniziare a ottimizzare un'applicazione con questa tecnica, è importante sapere che questa tecnica può essere molto più complessa nelle applicazioni più grandi.

Per quanto riguarda la rimozione delle librerie inutilizzate, prova a capire quali parti di un bundle vengono utilizzate e quali no. Per un pacchetto dall'aspetto misterioso che sembra non essere utilizzato da nessuna parte, fai un passo indietro e controlla quali dipendenze di primo livello potrebbero averne bisogno. Cerca di trovare un modo per separarli l'uno dall'altro.

Per quanto riguarda la rimozione delle librerie non necessarie, le cose possono essere un po' più complicate. È importante lavorare a stretto contatto con il team e vedere se esiste la possibilità di semplificare parti del codebase. Rimuovere moment in questa applicazione potrebbe sembrare la cosa giusta da fare ogni volta, ma cosa succederebbe se dovessero essere gestiti fusi orari e impostazioni internazionali diverse? E se ci fossero manipolazioni della data più complicate? Le operazioni possono essere molto complesse quando si manipolano e si analizzano date e ore e librerie come moment e date-fns semplificano notevolmente questa operazione.

Tutto è un compromesso ed è importante valutare se vale la complessità e lo sforzo richiesto per implementare una soluzione personalizzata invece di fare affidamento su una libreria di terze parti.