Как использовать динамический импорт в Next.js
- Published on
- Authors
- Name
- Vasiliy Kramarenko
- @kramvas07
Во время ночного тестирования производительности я все время спрашивал себя: «Как уменьшить время загрузки страницы в Next.js?» Тестируя в Network Panel, я сделал то, что делают большинство инженеров во время отчаяния, и пошел искать в Google. Именно тогда я открыл для себя удивительный мир динамического импорта.
Примечание. Динамический импорт был введен в ES2020 и может потребовать дополнительной настройки. На момент написания этого динамический импорт в Next.js поддерживался только для компонентов.
Что такое динамический импорт?
В отличие от импорта обычных модулей, динамический импорт позволяет гибко определять, когда и как они загружаются. Вместо принудительной загрузки файла модуля во время чтения, динамический импорт может быть запрошен во время использования.
Как настроить динамический импорт в Next.js
Прежде чем продолжить, следует помнить о некоторых вещах, связанных с динамическим импортом. Хотя динамический импорт может снизить загрузку страницы, очень важно знать, как ведет себя процесс получение пакета, чтобы избежать негативных побочных эффектов, которые могут увеличить загрузку страницы.
- Динамический импорт запрашивает при первом рендеринге компонента.
- Уже обработанный импорт не запускает дополнительную повторный запрос.
- Каждый динамический импорт будет создавать новый увеличенный файл пакета. Это включает вложенный динамический импорт.
- Каждый динамический импорт создает новый запрос на сервер.
Next.js поддерживает динамический импорт ES2020() для JavaScript. С его помощью вы можете динамически импортировать модули JavaScript и работать с ними. Они также работают с SSR.
В следующем примере мы реализуем нечеткий поиск с помощью fuse.js и динамически загружаем модуль в браузер только после того, как пользователь вводит поисковый запрос:
Создание примера
import { useState } from 'react'
const names = ['Tim', 'Joe', 'Bel', 'Max', 'Lee']
export default function Page() {
const [results, setResults] = useState()
return (
<div>
<input
type="text"
placeholder="Search"
onChange={async (e) => {
const { value } = e.currentTarget
// Dynamically load fuse.js
const Fuse = (await import('fuse.js')).default
const fuse = new Fuse(names)
setResults(fuse.search(value))
}}
/>
<pre>Results: {JSON.stringify(results, null, 2)}</pre>
</div>
)
}
Вы можете рассматривать динамический импорт как еще один способ разбить код на управляемые части.
Компоненты React также можно импортировать с помощью динамического импорта, но в этом случае мы используем его вместе с next/dynamic, чтобы убедиться, что он работает как любой другой компонент React.
Основное использование
В следующем примере модуль ../components/hello будет динамически загружен страницей:
import dynamic from 'next/dynamic'
const DynamicComponent = dynamic(() => import('../components/hello'))
function Home() {
return (
<div>
<Header />
<DynamicComponent />
<p>HOME PAGE is here!</p>
</div>
)
}
export default Home
DynamicComponent будет компонентом по умолчанию, возвращаемым ../components/hello. Он работает как обычный компонент React, и вы можете передавать ему пропсы, как обычн
Примечание. В import ('path/to/component') путь должен быть явно записан. Это не может быть ни строка шаблона, ни переменная.-
Кроме того, import() должен находиться внутри вызова dynamic() для Next.js, чтобы иметь возможность сопоставлять идентификаторы пакетов/модулей веб-пакетов с конкретным вызовом dynamic() и предварительно загружать их перед рендерингом.
dynamic() не может использоваться внутри React-рендеринга, так как он должен быть отмечен на верхнем уровне модуля для предварительной загрузки для работы, аналогично React.lazy.
ПРОВЕРКА ВАШЕЙ РАБОТЫ
Вы можете убедиться в волшебстве динамического импорта, проверив сетевую панель в коде и просмотрев несколько JS-файлов, таких как 0.js. В Next.js 0.js является основным файлом пакета. Между тем, динамический импорт начинается с 1.js и увеличивает новый пакет за новый динамический импорт.
После рендеринга модуля динамического импорта загружается новый пакет Next.js. Имя увеличивается, например: 1.js, и будет отображаться на панели сети. Это происходит при рендеринге динамического импорта.
С именованным экспортом
Если динамический компонент не является компонентом экспортированным по умолчанию, вы также можете использовать именованный экспорт. Рассмотрим модуль ../components/hello.js с именем export Hello:
export function Hello() {
return <p>Hello!</p>
}
Чтобы динамически импортировать компонент Hello, вы можете вернуть его из Promise, возвращаемого функцией import(), например:
import dynamic from 'next/dynamic'
const DynamicComponent = dynamic(() =>
import('../components/hello').then((mod) => mod.Hello)
)
function Home() {
return (
<div>
<Header />
<DynamicComponent />
<p>HOME PAGE is here!</p>
</div>
)
}
export default Home
Настраиваемая загрузка компоненты
Опциональный компонент "загрузка" может быть добавлен для визуализации состояния загрузки во время загрузки динамического компонента. Например
import dynamic from 'next/dynamic'
const DynamicComponentWithCustomLoading = dynamic(
() => import('../components/hello'),
{ loading: () => <p>...</p> }
)
function Home() {
return (
<div>
<Header />
<DynamicComponentWithCustomLoading />
<p>HOME PAGE is here!</p>
</div>
)
}
export default Home
Без SSR
Возможно, вы не всегда хотите включать модуль на стороне сервера. Например, когда модуль включает библиотеку, которая работает только в браузере.
Взгляните на следующий пример:
import dynamic from 'next/dynamic'
const DynamicComponentWithNoSSR = dynamic(
() => import('../components/hello3'),
{ ssr: false }
)
function Home() {
return (
<div>
<Header />
<DynamicComponentWithNoSSR />
<p>HOME PAGE is here!</p>
</div>
)
}
export default Home
Когда использовать динамический импорт
Чтобы определить лучшие места для динамического импорта, может потребоваться метод проб и ошибок, но это не всегда хороший метод. Вот список мест, которые я посчитал полезными когда проводил мои эксперименты.
ЧТО НУЖНО ИСКАТЬ:
- Сценарии, в которых ресурсоемкие компоненты не отображаются при загрузке страницы, отлично подходят для динамического импорта.
- Модули, использующие внешние ресурсы, могут использовать асинхронный импорт.
- Необходимость отображать загружаемый компонент во время рендеринга компонента. Это может быть легче обнаружить при ограниченном сетевом подключении.
ЧТО СЛЕДУЕТ ИЗБЕГАТЬ:
- Если динамически импортированный компонент отображается немедленно, размер полезной нагрузки остается таким же, и добавляется дополнительный запрос сервера для дополнительного пакета кода.
- Избегайте чрезмерного использования динамического импорта. Каждый вариант использования добавляет новый запрос сервера и пакет кода. Это может быть дорогостоящим, если этой функцией злоупотреблять.
- По возможности избегайте вложенных динамических импортов. Это может легко добавить дополнительные запросы к серверу и дополнительные бандлы кода.
- Динамический импорт в Next.js не работает с функциями. Это может быть возможно в будущем, но пока не поддерживается.
СЦЕНАРИИ РЕАЛЬНОЙ ЖИЗНИ:
Вот несколько типичных компонентов, которые отлично подходят для динамического импорта:
- UI компоненты, такие как модальные окна, всплывающие панели навигации и переключатели, которые не отображают контент, пока не произойдет взаимодействие.
- Компоненты поиска, использующие ввод текста или нажатие кнопки
- Компоненты «Загрузить еще», которые отображают дополнительный контент при взаимодействии с пользователем.
- Модульные запросы из внешнего API
- Компоненты, которые загружаются медленно и могут получить выгоду от компонента загрузки, пока выполняется импорт
Выводы
Если у вас есть тяжелые компоненты ресурсов, которые не нужно обрабатывать при загрузке страницы, обязательно используйте динамический импорт. Это может оказать огромное влияние на время загрузки страницы и показать высокие оценки в PageSpeed Lighthouse. Эта функция действительно проста в использовании, и вам нечего терять, попробовав ее.