Как ускорить работу вашего приложения Next.js с помощью разделения кода и интеллектуальных стратегий загрузки.
Опубликовано: 8 ноября 2019 г.
Узнайте о различных типах разделения кода и о том, как использовать динамический импорт для ускорения работы ваших приложений Next.js.
Разделение кода на основе маршрутов и компонентов
По умолчанию Next.js разбивает ваш JavaScript-код на отдельные фрагменты для каждого маршрута. Когда пользователи загружают ваше приложение, Next.js отправляет только код, необходимый для начального маршрута. При перемещении по приложению пользователи получают фрагменты кода, связанные с другими маршрутами. Разделение кода на основе маршрутов минимизирует объем скрипта, который необходимо одновременно анализировать и компилировать, что приводит к более быстрой загрузке страниц.
Хотя разделение кода на основе маршрутов — это хороший вариант по умолчанию, вы можете дополнительно оптимизировать процесс загрузки, разделив код на уровне компонентов. Если в вашем приложении есть большие компоненты, отличной идеей будет разделить их на отдельные части. Таким образом, любые большие компоненты, которые не являются критически важными или отображаются только при определенных действиях пользователя (например, при нажатии кнопки), могут загружаться с отложенной загрузкой.
Next.js поддерживает динамический import() , который позволяет динамически импортировать модули JavaScript (включая компоненты React) и загружать каждый импорт как отдельный фрагмент. Это обеспечивает разделение кода на уровне компонентов и позволяет контролировать загрузку ресурсов, чтобы пользователи загружали только тот код, который им нужен для той части сайта, которую они просматривают. В Next.js эти компоненты по умолчанию отображаются на стороне сервера (SSR) .
Динамический импорт в действии
В этом посте представлены несколько версий примера приложения, состоящего из простой страницы с одной кнопкой. При нажатии на кнопку вы увидите милого щенка. По мере прохождения каждой версии приложения вы увидите, чем динамический импорт отличается от статического и как с ним работать.
В первой версии приложения щенок находится в components/Puppy.js . Для отображения щенка на странице приложение импортирует компонент Puppy в index.js с помощью статического импорта:
import Puppy from "../components/Puppy";
Чтобы увидеть, как Next.js собирает приложение, изучите трассировку сети в инструментах разработчика:
Для предварительного просмотра сайта нажмите «Просмотреть приложение» . Затем нажмите «Полноэкранный режим».
.
Нажмите `Control+Shift+J` (или `Command+Option+J` на Mac), чтобы открыть инструменты разработчика.
Перейдите на вкладку «Сеть» .
Установите флажок «Отключить кэш» .
Перезагрузите страницу.
При загрузке страницы весь необходимый код, включая компонент Puppy.js , объединяется в index.js :

При нажатии кнопки «Нажмите на меня» на вкладку «Сеть» добавляется только запрос на получение изображения щенка в формате JPEG:

Недостаток такого подхода заключается в том, что даже если пользователи не нажимают кнопку, чтобы увидеть щенка, им приходится загружать компонент Puppy поскольку он включен в index.js . В этом небольшом примере это не имеет большого значения, но в реальных приложениях загрузка больших компонентов только при необходимости часто является огромным улучшением.
Теперь взгляните на вторую версию приложения, в которой статический импорт заменен динамическим. Next.js включает в себя next/dynamic , что позволяет использовать динамический импорт для любых компонентов в Next.js:
import Puppy from "../components/Puppy";
import dynamic from "next/dynamic";
// ...
const Puppy = dynamic(import("../components/Puppy"));
Выполните действия из первого примера, чтобы просмотреть трассировку сети.
При первом запуске приложения загружается только файл index.js . На этот раз он на 0,5 КБ меньше (уменьшился с 37,9 КБ до 37,4 КБ), поскольку не содержит код компонента Puppy :

Компонент Puppy теперь находится в отдельном фрагменте кода, 1.js , который загружается только при нажатии кнопки:

В реальных приложениях компоненты часто намного больше по размеру , и отложенная загрузка может уменьшить первоначальный объем полезной нагрузки JavaScript на сотни килобайт.
Динамический импорт с настраиваемым индикатором загрузки
При отложенной загрузке ресурсов рекомендуется указывать индикатор загрузки на случай задержек. В Next.js это можно сделать, указав дополнительный аргумент в функции dynamic() :
const Puppy = dynamic(() => import("../components/Puppy"), {
loading: () => <p>Loading...</p>
});
Чтобы увидеть индикатор загрузки в действии, смоделируйте медленное сетевое соединение в инструментах разработчика:
Для предварительного просмотра сайта нажмите «Просмотреть приложение» . Затем нажмите «Полноэкранный режим».
.
Нажмите `Control+Shift+J` (или `Command+Option+J` на Mac), чтобы открыть инструменты разработчика.
Перейдите на вкладку «Сеть» .
Установите флажок «Отключить кэш» .
В раскрывающемся списке «Ограничение скорости» выберите «Быстрый 3G» .
Нажмите кнопку «Нажмите на меня» .
Теперь при нажатии кнопки требуется некоторое время для загрузки компонента, и в это время приложение отображает сообщение "Загрузка…".

Динамический импорт без SSR
Если вам необходимо отображать компонент только на стороне клиента (например, виджет чата), вы можете сделать это, установив параметр ssr в false :
const Puppy = dynamic(() => import("../components/Puppy"), {
ssr: false,
});
Заключение
Благодаря поддержке динамического импорта, Next.js позволяет разделять код на уровне компонентов, что минимизирует объем JavaScript-кода и улучшает время загрузки приложения. Все компоненты по умолчанию отображаются на стороне сервера, и эту опцию можно отключить при необходимости.