Lazy Loading
Lazy Loading in Next.js hilft, die anfängliche Ladeleistung einer Anwendung zu verbessern, indem die Menge an JavaScript reduziert wird, die zum Rendern einer Route benötigt wird.
Es ermöglicht Ihnen, das Laden von Client-Komponenten (Client Components) und importierten Bibliotheken zu verzögern und sie nur dann in das Client-Bundle einzubinden, wenn sie benötigt werden. Beispielsweise können Sie das Laden eines Modals verzögern, bis ein Benutzer auf eine Schaltfläche klickt, um es zu öffnen.
Es gibt zwei Möglichkeiten, Lazy Loading in Next.js zu implementieren:
- Verwendung von Dynamischen Imports mit
next/dynamic
- Verwendung von
React.lazy()
mit Suspense
Standardmäßig werden Server-Komponenten (Server Components) automatisch code-split, und Sie können Streaming verwenden, um Teile der UI 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
'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 die Bedingung erfüllt ist */}
{showMore && <ComponentB />}
<button onClick={() => setShowMore(!showMore)}>Umschalten</button>
{/* Nur auf der Client-Seite laden */}
<ComponentC />
</div>
)
}
SSR überspringen
Bei Verwendung von React.lazy()
und Suspense werden Client-Komponenten standardmäßig vorgerendert (SSR).
Wenn Sie die Vorrendering 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, verzögert geladen - nicht die Server-Komponente selbst.
import dynamic from 'next/dynamic'
// Server-Komponente:
const ServerComponent = dynamic(() => import('../components/ServerComponent'))
export default function ServerComponentExample() {
return (
<div>
<ServerComponent />
</div>
)
}
Laden externer Bibliotheken
Externe Bibliotheken können bei Bedarf mit der import()
-Funktion geladen werden. Dieses Beispiel verwendet die externe Bibliothek fuse.js
für die Fuzzy-Suche. Das Modul wird nur auf dem Client geladen, nachdem der Benutzer eine Suchanfrage eingegeben hat.
'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
// Dynamisch fuse.js laden
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
import dynamic from 'next/dynamic'
const WithCustomLoading = dynamic(
() => import('../components/WithCustomLoading'),
{
loading: () => <p>Laden...</p>,
}
)
export default function Page() {
return (
<div>
{/* Die Ladekomponente wird gerendert, während <WithCustomLoading/> geladen wird */}
<WithCustomLoading />
</div>
)
}
Importieren benannter Exports
Um einen benannten Export dynamisch zu importieren, können Sie ihn aus dem von der import()
-Funktion zurückgegebenen Promise zurückgeben:
'use client'
export function Hello() {
return <p>Hallo!</p>
}
import dynamic from 'next/dynamic'
const ClientComponent = dynamic(() =>
import('../components/hello').then((mod) => mod.Hello)
)