Importuri dinamice JavaScript: Mastering Code Splitting și Lazy Loading | MLOG | MLOG

Componenta Modal este încărcată numai atunci când utilizatorul face clic pe butonul „Open Modal”.

3. Code Splitting Bazat pe Caracteristici

Această abordare se concentrează pe împărțirea codului în funcție de caracteristici sau funcționalități distincte din cadrul aplicației dvs. Acest lucru este util în special pentru aplicațiile mari, cu caracteristici complexe care nu sunt întotdeauna necesare de toți utilizatorii. De exemplu, un site de comerț electronic ar putea încărca leneș codul legat de recenziile de produs sau liste de dorințe numai atunci când utilizatorul interacționează cu acele caracteristici.

Exemplu (lazy loading a unei caracteristici de raportare):

            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;

Componenta ReportingDashboard, care probabil conține vizualizări complexe de date și logică de analiză, este încărcată numai atunci când administratorul face clic pe butonul „Show Reporting Dashboard”.

4. Code Splitting Condiționat

Această tehnică implică importul dinamic de module pe baza anumitor condiții, cum ar fi dispozitivul, browserul sau locația utilizatorului. Acest lucru vă permite să adaptați codul aplicației la nevoile specifice ale fiecărui utilizator, optimizând în continuare performanța și utilizarea resurselor. Luați în considerare servirea diferitelor formate de imagine (de exemplu, WebP pentru browserele acceptate) sau încărcarea polyfill-urilor numai pentru browserele mai vechi.

Exemplu (încărcarea polyfill-urilor pentru browserele mai vechi):

            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();

            

Acest cod verifică dacă API-ul fetch și Promise sunt acceptate de browser. Dacă nu, acesta importă dinamic polyfill-urile corespunzătoare.

Strategii de Lazy Loading

Lazy loading este o tehnică care amână încărcarea resurselor până când acestea sunt efectiv necesare. Acest lucru poate îmbunătăți semnificativ timpii inițiali de încărcare a paginii și reduce consumul de lățime de bandă. Importurile dinamice sunt un instrument puternic pentru implementarea lazy loading în aplicațiile JavaScript.

1. Lazy Loading Imagini

Imaginile sunt adesea un contribuitor major la dimensiunea paginii. Lazy loading-ul imaginilor asigură că imaginile de sub fold (adică cele care nu sunt vizibile imediat în viewport) sunt încărcate numai atunci când utilizatorul derulează în jos pagina.

Exemplu (folosind API-ul 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);
});

            

În acest exemplu, atributul data-src conține URL-ul imaginii. API-ul Intersection Observer este utilizat pentru a detecta momentul în care imaginea intră în viewport, moment în care imaginea este încărcată.

2. Lazy Loading Videoclipuri

Similar imaginilor, videoclipurile pot, de asemenea, să aibă un impact semnificativ asupra timpilor de încărcare a paginii. Lazy loading-ul videoclipurilor împiedică încărcarea acestora până când utilizatorul interacționează cu ele (de exemplu, face clic pe un buton de redare).

Exemplu (lazy loading a unui videoclip folosind un substituent):

            <div class="video-container">
  <img src="placeholder.jpg" alt="Video Placeholder" class="video-placeholder">
  <button class="play-button">Play</button>
  <video data-src="my-video.mp4" controls>
    Your browser does not support the video tag.
  </video>
</div>

<script>
  const videoContainer = document.querySelector('.video-container');
  const playButton = document.querySelector('.play-button');
  const video = document.querySelector('video');

  playButton.addEventListener('click', () => {
    video.src = video.dataset.src;
    video.load();
    video.play();
    playButton.style.display = 'none';
    videoContainer.querySelector('.video-placeholder').style.display = 'none';
  });
</script>

            

Videoclipul este reprezentat inițial de o imagine substituentă. Când utilizatorul face clic pe butonul de redare, sursa video este încărcată și videoclipul începe să fie redat.

3. Lazy Loading Iframes

Iframes, adesea folosite pentru a încorpora conținut din surse terțe, pot avea, de asemenea, impact asupra performanței paginii. Lazy loading-ul iframes asigură că acestea sunt încărcate numai atunci când utilizatorul derulează aproape de ele.

Exemplu (lazy loading a unui iframe folosind API-ul 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);
});

            

Similar exemplului de lazy loading a imaginii, acest cod utilizează API-ul Intersection Observer pentru a detecta momentul în care iframe intră în viewport, apoi încarcă conținutul iframe-ului.

Webpack și Importuri Dinamice

Webpack este un pachet de module popular care oferă un suport excelent pentru importurile dinamice. Acesta detectează automat instrucțiunile de import dinamic și împarte codul în bucăți separate, care pot fi apoi încărcate la cerere.

Configurare:

De obicei, nu este necesară o configurare specială pentru a activa importurile dinamice în Webpack. Cu toate acestea, este posibil să doriți să configurați code splitting în continuare utilizând funcții precum:

Exemplu (configurație Webpack pentru 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',
        },
      },
    },
  },
  // ...
};

            

Această configurație creează o bucată separată pentru bibliotecile de furnizori (cod din node_modules) și utilizează o hash unic pentru fiecare bucată pentru a activa cache-ul browserului.

React și Importuri Dinamice

React oferă suport încorporat pentru componentele de lazy loading utilizând funcția React.lazy() și componenta Suspense. Acest lucru facilitează implementarea code splitting în aplicațiile React.

Exemplu (lazy loading a unei componente React):

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

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

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

Funcția React.lazy() ia o funcție care returnează un import dinamic. Componenta Suspense oferă o interfață de utilizare de rezervă în timp ce componenta se încarcă.

Angular și Importuri Dinamice

Angular acceptă modulele de lazy loading utilizând configurația sa de rutare. Puteți defini rute care încarcă modulele la cerere, ceea ce poate îmbunătăți semnificativ timpul inițial de încărcare al aplicației Angular.

Exemplu (lazy loading a unui modul în 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 { }

            

În acest exemplu, FeatureModule este încărcat numai atunci când utilizatorul navighează la ruta /feature.

Vue.js și Importuri Dinamice

Vue.js oferă, de asemenea, suport pentru componentele de lazy loading folosind importuri dinamice. Puteți utiliza sintaxa import() în cadrul definițiilor componentelor pentru a încărca componentele la cerere.

Exemplu (lazy loading a unei 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
}))

            

Acest exemplu definește o componentă asincronă numită async-component care încarcă fișierul AsyncComponent.vue la cerere. De asemenea, oferă opțiuni pentru componente de încărcare, eroare, întârziere și expirare.

Bune Practici pentru Importuri Dinamice și Lazy Loading

Pentru a utiliza în mod eficient importurile dinamice și lazy loading, luați în considerare următoarele bune practici:

Considerații Globale

Când implementați importuri dinamice și lazy loading pentru un public global, este esențial să luați în considerare următoarele:

Concluzie

Importurile dinamice JavaScript oferă un mecanism puternic pentru implementarea code splitting și lazy loading, permițându-vă să optimizați performanța aplicației dvs. web și să oferiți o experiență superioară utilizatorului pentru un public global. Împărțind strategic codul pe baza rutelor, componentelor sau caracteristicilor și prin încărcarea leneșă a resurselor la cerere, puteți reduce semnificativ timpii inițiali de încărcare, îmbunătăți receptivitatea și îmbunătăți eficiența generală a aplicației. Amintiți-vă să urmați cele mai bune practici, să luați în considerare considerentele globale și să monitorizați continuu performanța aplicației dvs. pentru a vă asigura că oferiți cea mai bună experiență posibilă utilizatorilor din întreaga lume. Adoptați aceste tehnici și urmăriți cum aplicația dvs. înflorește în peisajul digital global.