Import Dinamici in JavaScript: Padroneggiare Code Splitting e Lazy Loading | MLOG | MLOG

Il componente Modal viene caricato solo quando l'utente fa clic sul pulsante "Open Modal".

3. Code Splitting Basato sulle Funzionalità

Questo approccio si concentra sulla suddivisione del codice in base a funzionalità o caratteristiche distinte all'interno della tua applicazione. Ciò è particolarmente utile per applicazioni di grandi dimensioni con funzionalità complesse che non sono sempre necessarie a tutti gli utenti. Ad esempio, un sito di e-commerce potrebbe caricare pigramente il codice relativo alle recensioni dei prodotti o alle liste dei desideri solo quando l'utente interagisce con tali funzionalità.

Esempio (lazy loading di una funzionalità di reporting):

            import React, { useState, lazy, Suspense } from 'react';

const ReportingDashboard = lazy(() => import('./features/ReportingDashboard'));

function AdminPanel() {
  const [showReporting, setShowReporting] = useState(false);

  const handleShowReporting = () => {
    setShowReporting(true);
  };

  return (
    
{showReporting && ( Loading Reporting...
}> )}
); } export default AdminPanel;

Il componente ReportingDashboard, che probabilmente contiene visualizzazioni di dati complesse e logica di analisi, viene caricato solo quando l'amministratore fa clic sul pulsante "Show Reporting Dashboard".

4. Code Splitting Condizionale

Questa tecnica comporta l'importazione dinamica di moduli in base a determinate condizioni, come il dispositivo dell'utente, il browser o la posizione. Ciò ti consente di adattare il codice della tua applicazione alle esigenze specifiche di ciascun utente, ottimizzando ulteriormente le prestazioni e l'utilizzo delle risorse. Considera di servire formati di immagine diversi (ad esempio, WebP per i browser supportati) o di caricare i polyfill solo per i browser più vecchi.

Esempio (caricamento di polyfill per browser più vecchi):

            async function loadPolyfills() {
  if (!('fetch' in window)) {
    await import('whatwg-fetch');
    console.log('Fetch polyfill loaded.');
  }

  if (!('Promise' in window)) {
    await import('promise-polyfill/src/polyfill');
    console.log('Promise polyfill loaded.');
  }
}

loadPolyfills();

            

Questo codice controlla se l'API fetch e le Promise sono supportate dal browser. In caso contrario, importa dinamicamente i polyfill corrispondenti.

Strategie di Lazy Loading

Il lazy loading è una tecnica che posticipa il caricamento delle risorse fino a quando non sono effettivamente necessarie. Ciò può migliorare significativamente i tempi di caricamento iniziali della pagina e ridurre il consumo di larghezza di banda. Gli import dinamici sono uno strumento potente per implementare il lazy loading nelle applicazioni JavaScript.

1. Lazy Loading delle Immagini

Le immagini sono spesso uno dei principali fattori che contribuiscono alle dimensioni della pagina. Il lazy loading delle immagini garantisce che le immagini 'below the fold' (cioè quelle non immediatamente visibili nella viewport) vengano caricate solo quando l'utente scorre la pagina verso il basso.

Esempio (usando l'API Intersection Observer):

            const images = document.querySelectorAll('img[data-src]');

function preloadImage(img) {
  img.src = img.dataset.src;
  img.onload = () => {
    img.removeAttribute('data-src');
  };
}

const imgObserver = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      preloadImage(entry.target);
      observer.unobserve(entry.target);
    }
  });
});

images.forEach(img => {
  imgObserver.observe(img);
});

            

In questo esempio, l'attributo data-src contiene l'URL dell'immagine. L'API Intersection Observer viene utilizzata per rilevare quando l'immagine entra nella viewport, a quel punto l'immagine viene caricata.

2. Lazy Loading dei Video

Similmente alle immagini, anche i video possono influire significativamente sui tempi di caricamento della pagina. Il lazy loading dei video impedisce che vengano caricati fino a quando l'utente non interagisce con essi (ad esempio, facendo clic su un pulsante di riproduzione).

Esempio (lazy loading di un video usando un placeholder):

            
Video Placeholder

Il video è inizialmente rappresentato da un'immagine segnaposto. Quando l'utente fa clic sul pulsante di riproduzione, viene caricata la sorgente del video e il video inizia a essere riprodotto.

3. Lazy Loading degli Iframe

Gli iframe, spesso utilizzati per incorporare contenuti da fonti di terze parti, possono anche influire sulle prestazioni della pagina. Il lazy loading degli iframe garantisce che vengano caricati solo quando l'utente scorre vicino ad essi.

Esempio (lazy loading di un iframe usando l'API Intersection Observer):

            const iframes = document.querySelectorAll('iframe[data-src]');

function loadIframe(iframe) {
  iframe.src = iframe.dataset.src;
  iframe.onload = () => {
    iframe.removeAttribute('data-src');
  };
}

const iframeObserver = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      loadIframe(entry.target);
      observer.unobserve(entry.target);
    }
  });
});

iframes.forEach(iframe => {
  iframeObserver.observe(iframe);
});

            

Similmente all'esempio di lazy loading delle immagini, questo codice utilizza l'API Intersection Observer per rilevare quando l'iframe entra nella viewport e quindi carica il contenuto dell'iframe.

Webpack e gli Import Dinamici

Webpack è un popolare bundler di moduli che offre un eccellente supporto per gli import dinamici. Rileva automaticamente le istruzioni di import dinamico e suddivide il codice in chunk separati, che possono poi essere caricati su richiesta.

Configurazione:

Di solito non è richiesta alcuna configurazione speciale per abilitare gli import dinamici in Webpack. Tuttavia, potresti voler configurare ulteriormente il code splitting utilizzando funzionalità come:

Esempio (configurazione di Webpack per il code splitting):

            module.exports = {
  // ...
  output: {
    filename: '[name].[chunkhash].js',
    chunkFilename: '[name].[chunkhash].js',
    path: path.resolve(__dirname, 'dist'),
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
      },
    },
  },
  // ...
};

            

Questa configurazione crea un chunk separato per le librerie di terze parti (codice da node_modules) e utilizza un hash univoco per ogni chunk per abilitare la memorizzazione nella cache del browser.

React e gli Import Dinamici

React fornisce supporto integrato per il lazy loading dei componenti utilizzando la funzione React.lazy() e il componente Suspense. Ciò rende facile implementare il code splitting nelle applicazioni React.

Esempio (lazy loading di un componente React):

            import React, { lazy, Suspense } from 'react';

const MyComponent = lazy(() => import('./MyComponent'));

function App() {
  return (
    Loading...
}> ); } export default App;

La funzione React.lazy() accetta una funzione che restituisce un import dinamico. Il componente Suspense fornisce un'interfaccia utente di fallback mentre il componente è in caricamento.

Angular e gli Import Dinamici

Angular supporta il lazy loading dei moduli utilizzando la sua configurazione di routing. Puoi definire route che caricano moduli su richiesta, il che può migliorare significativamente il tempo di caricamento iniziale della tua applicazione Angular.

Esempio (lazy loading di un modulo in Angular):

            import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  {
    path: 'feature',
    loadChildren: () => import('./feature/feature.module').then(m => m.FeatureModule)
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

            

In questo esempio, il FeatureModule viene caricato solo quando l'utente naviga alla route /feature.

Vue.js e gli Import Dinamici

Anche Vue.js fornisce supporto per il lazy loading dei componenti utilizzando gli import dinamici. Puoi usare la sintassi import() all'interno delle definizioni dei tuoi componenti per caricare i componenti su richiesta.

Esempio (lazy loading di un componente Vue.js):

            Vue.component('async-component', () => ({
  // The component to load. Should be a Promise
  component: import('./AsyncComponent.vue'),
  // A component to use while the async component is loading
  loading: LoadingComponent,
  // A component to use if the load fails
  error: ErrorComponent,
  // Delay before showing the loading component. Default: 200ms.
  delay: 200,
  // The error component will be displayed if a timeout is
  // provided and exceeded.
  timeout: 3000
}))

            

Questo esempio definisce un componente asincrono chiamato async-component che carica il file AsyncComponent.vue su richiesta. Fornisce anche opzioni per componenti di caricamento, errore, ritardo e timeout.

Best Practice per gli Import Dinamici e il Lazy Loading

Per sfruttare efficacemente gli import dinamici e il lazy loading, considera le seguenti best practice:

Considerazioni Globali

Quando si implementano import dinamici e lazy loading per un pubblico globale, è fondamentale considerare quanto segue:

Conclusione

Gli import dinamici di JavaScript forniscono un meccanismo potente per implementare il code splitting e il lazy loading, consentendoti di ottimizzare le prestazioni della tua applicazione web e offrire un'esperienza utente superiore a un pubblico globale. Suddividendo strategicamente il tuo codice in base a route, componenti o funzionalità, e caricando le risorse su richiesta con il lazy loading, puoi ridurre significativamente i tempi di caricamento iniziali, migliorare la reattività e aumentare l'efficienza complessiva dell'applicazione. Ricorda di seguire le best practice, considerare gli aspetti globali e monitorare continuamente le prestazioni della tua applicazione per assicurarti di offrire la migliore esperienza possibile agli utenti di tutto il mondo. Adotta queste tecniche e guarda la tua applicazione prosperare nel panorama digitale globale.