Menu

Lazy Loading

Lazy Loading in Next.js hilft, die initiale Ladeperformance einer Anwendung zu verbessern, indem die Menge an JavaScript, die zum Rendering einer Route benötigt wird, verringert wird.

Es ermöglicht Ihnen, das Laden von Client-Komponenten und importierten Bibliotheken zu verzögern und sie nur dann in den Client-Bundle aufzunehmen, wenn sie benötigt werden. Beispielsweise möchten Sie das Laden eines Modals möglicherweise verzögern, bis ein Benutzer darauf klickt.

Es gibt zwei Möglichkeiten, Lazy Loading in Next.js zu implementieren:

  1. Verwendung von Dynamic Imports mit next/dynamic
  2. Verwendung von React.lazy() mit Suspense

Standardmäßig werden Server-Komponenten automatisch code split, und Sie können Streaming verwenden, um Teile der Benutzeroberfläche schrittweise vom Server an den Client zu senden. Lazy Loading gilt für Client-Komponenten.

next/dynamic

next/dynamic ist eine Kombination aus React.lazy() und Suspense. Es verhält sich in den Verzeichnissen app und pages gleich, um eine schrittweise Migration zu ermöglichen.

Beispiele

Importieren von Client-Komponenten

app/page.js
'use client'
 
import { useState } from 'react'
import dynamic from 'next/dynamic'
 
// Client-Komponenten:
const ComponentA = dynamic(() => import('../components/A'))
const ComponentB = dynamic(() => import('../components/B'))
const ComponentC = dynamic(() => import('../components/C'), { ssr: false })
 
export default function ClientComponentExample() {
  const [showMore, setShowMore] = useState(false)
 
  return (
    <div>
      {/* Sofort laden, aber in einem separaten Client-Bundle */}
      <ComponentA />
 
      {/* Bei Bedarf laden, nur wenn/falls die Bedingung erfüllt ist */}
      {showMore && <ComponentB />}
      <button onClick={() => setShowMore(!showMore)}>Toggle</button>
 
      {/* Nur auf der Clientseite laden */}
      <ComponentC />
    </div>
  )
}

Server-Side Rendering überspringen

Bei Verwendung von React.lazy() und Suspense werden Client-Komponenten standardmäßig vorgerendert (SSR).

Hinweis: Die Option ssr: false funktioniert nur für Client-Komponenten. Verschieben Sie sie in Client-Komponenten, um das clientseitige Code-Splitting korrekt zu gewährleisten.

Wenn Sie das Vorrendern für eine Client-Komponente deaktivieren möchten, können Sie die Option ssr auf false setzen:

const ComponentC = dynamic(() => import('../components/C'), { ssr: false })

Importieren von Server-Komponenten

Wenn Sie eine Server-Komponente dynamisch importieren, werden nur die Client-Komponenten, die Kinder der Server-Komponente sind, lazy geladen - nicht die Server-Komponente selbst. Es hilft auch beim Vorladen statischer Assets wie CSS, wenn Sie sie in Server-Komponenten verwenden.

app/page.js
import dynamic from 'next/dynamic'
 
// Server-Komponente:
const ServerComponent = dynamic(() => import('../components/ServerComponent'))
 
export default function ServerComponentExample() {
  return (
    <div>
      <ServerComponent />
    </div>
  )
}

Hinweis: Die Option ssr: false wird in Server-Komponenten nicht unterstützt. Sie erhalten einen Fehler, wenn Sie versuchen, sie in Server-Komponenten zu verwenden. ssr: false ist mit next/dynamic in Server-Komponenten nicht erlaubt. Bitte verschieben Sie es in eine Client-Komponente.

Externe Bibliotheken laden

Externe Bibliotheken können bei Bedarf mit der Funktion import() geladen werden. Dieses Beispiel verwendet die externe Bibliothek fuse.js für die unscharfe Suche. Das Modul wird nur auf dem Client geladen, nachdem der Benutzer in das Suchfeld eingegeben hat.

app/page.js
'use client'
 
import { useState } from 'react'
 
const names = ['Tim', 'Joe', 'Bel', 'Lee']
 
export default function Page() {
  const [results, setResults] = useState()
 
  return (
    <div>
      <input
        type="text"
        placeholder="Suche"
        onChange={async (e) => {
          const { value } = e.currentTarget
          // Dynamisches Laden von fuse.js
          const Fuse = (await import('fuse.js')).default
          const fuse = new Fuse(names)
 
          setResults(fuse.search(value))
        }}
      />
      <pre>Ergebnisse: {JSON.stringify(results, null, 2)}</pre>
    </div>
  )
}

Hinzufügen einer benutzerdefinierten Ladekomponente

app/page.js
import dynamic from 'next/dynamic'
 
const WithCustomLoading = dynamic(
  () => import('../components/WithCustomLoading'),
  {
    loading: () => <p>Lädt...</p>,
  }
)
 
export default function Page() {
  return (
    <div>
      {/* Die Ladekomponente wird gerendert, während <WithCustomLoading/> lädt */}
      <WithCustomLoading />
    </div>
  )
}

Importieren von benannten Exports

Um einen benannten Export dynamisch zu importieren, können Sie ihn von der Promise zurückgeben, die von der Funktion import() zurückgegeben wird:

components/hello.js
'use client'
 
export function Hello() {
  return <p>Hallo!</p>
}
app/page.js
import dynamic from 'next/dynamic'
 
const ClientComponent = dynamic(() =>
  import('../components/hello').then((mod) => mod.Hello)
)