Главная » Статьи » link rel=”prefetch/preload” в Webpack

link rel=”prefetch/preload” в Webpack

link rel=”prefetch/preload” в Webpack

От автора: для чего нужно использовать в Webpack link rel prefetch или preload. Что это такое, и как применяется на практике. Ответы на самые популярные вопросы.

Немного о применении link rel: используйте import(/* webpackPrefetch: true */ «…») для предварительного получения данных.

Что такое <link rel=”prefetch”>?

Ресурсная подсказка говорит браузеру, что этот ресурс, возможно, понадобится для навигации в будущем.

Обычно браузеры получают эти ресурсы, когда находятся в незанятом состоянии. После получения ресурс попадает в HTTP кэш для выполнения будущих запросов. Несколько prefetch подсказок становятся в очередь и вытягиваются во время простоя браузера. Выход из состояния ожидания во время получения данных в браузере может отменить любое текущее получение данных и остановить очередь.

Вывод: вытягивайте данные во время простоя.

Что такое <link rel=”preload”>?

Эта ресурсная подсказка говорит браузеру, что ресурс точно понадобится для навигации, но будет просмотрен позже. Chrome даже выводит предупреждение, если ресурс не используется в течение 3 секунд после загрузки.

Обычно браузеры получают эти ресурсы со средним приоритетом (не блокируя макет).

Вывод: обнаруживается раньше, вытягивается по-обычному.

Почему это полезно?

Предварительная загрузка используется для раннего обнаружения ресурсов, избегая водопада загрузки. Это может снизить загрузку страницы до 2 обращений (1. HTML, 2. Все остальные ресурсы). Это не требует дополнительных ресурсов сети.

Предварительное получение использует время простоя браузера для ускорения будущей навигации. Ее использование может потребовать дополнительных ресурсов сети, когда пользователь переходит не туда, куда ожидается.

Разбиение кода

Предположим, что вы строите свое огромное приложение с помощью Webpack и On-Demand-Loading через import(), чтобы загружать только части приложения, которые сейчас необходимы пользователю.

Для примера возьмем HomePage, на которой есть LoginButton, которая открывает LoginModal. После авторизации приложение перекидывает пользователя на DashboardPage. Страницы могут содержать другие кнопки, но они не такие распространенные.

Для лучшей производительности вы использовали import(«LoginModal») на LoginButton, чтобы сохранить HomePage на минимуме. Точно так же LoginModal содержит import(«DashboardPage»).

Сейчас этот пример-приложение разбит на 3 части: home-chunk, login-chunk, dashboard-chunk. При первой загрузке необходим только home-chunk, который создает замечательный UX. Но когда пользователь нажимает на LoginButton есть задержка, пока не откроется LoginModal, потому что эта часть приложения должна загрузиться первой. Точно так же с DashboardPage.

Использование предварительного получения данных в Webpack

Новая функция предварительного получения данных позволяет улучшить рабочий процесс. Она супер легкая.

На LoginButton измените import(«LoginModal») на import(/* webpackPrefetch: true */ «LoginModal»).

Точно так же измените import(«DashboardPage») на import(/* webpackPrefetch: true */ «DashboardPage») в LoginModal.

Это скажет Webpack предварительно вытащить данные (во время простоя браузера) этот On-Demand-Loaded chunk, когда родительский chunk закончит загружаться. В этом примере: когда home-chunk заканчивает загружаться, добавьте login-chunk в очередь на предварительное получение данных. Когда загрузится login-chunk (реальная загрузка, не предварительное получение), добавьте в очередь dashboard-chunk.

Если home-chunk является точкой входа, это сгенерирует в HTML странице <link rel=»prefetch» href=»login-chunk.js»>. login-chunk является on-demand-chunk, поэтому webpack runtime сам вставит <link rel=»prefetch» href=»dashboard-chunk.js»> после полной загрузки login-chunk.

Это улучшит UX следующим образом:

Пользователь заходит на HomePage. UX и производительность замечательные, как и раньше. После загрузки HomePage браузер входит в состояние простоя и начинает предварительно вытягивать login-chunk в фоновом режиме. Пользователь не замечает этого. Предполагая, что пользователю понадобится некоторое время на поиск LoginButton, этот запрос завершится до клика по кнопке.

Теперь когда пользователь нажмет на кнопку, login-chunk уже сидит в HTTP кэше, и запрос идет в кэш, на что нужно минимум времени. Пользователь мгновенно увидит LoginModal. В то же время webpack runtime добавить dashboard-chunk в очередь, и после авторизации эта часть также отобразится мгновенно без ожидания.

У пользователя не всегда может мгновенно загружаться LoginModal. Есть куча факторов, которые могут вернуть задержку для LoginButton: слабая сеть, быстрые клики, отключенное предварительное получение на устройствах с ограничениями по сети, отсутствие поддержки предварительного получения в браузере, очень медленное выполнение части,…

Использование предварительной загрузки в Webpack

Для import(/* webpackPrefetch: true */ «…») также можно использовать import(/* webpackPreload: true */ «…»). По сравнение с предварительным получением здесь есть ряд расхождений:

Предварительно загруженные части начинают загружаться параллельно с родительской частью. Предварительно полученные части начинают загружаться после завершения загрузки родителя.

Предварительно загруженные части имеют средний приоритет и мгновенно загружаются. Предварительно полученные части загружаются во время простоя браузера.

Предварительно загруженные части должны мгновенно запрашиваться родительской частью. Предварительно полученные части можно использовать в любое время в будущем.

Разная поддержка в браузерах.

Из-за этих свойств используется это крайне редко. Это можно использовать, если модуль всегда мгновенно import() что-то. Был бы смысл, если бы компонент зависел от большой библиотеки, которая должна находиться в отдельной части. Пример: ChartComponent использует большую ChartingLibrary. Он показывает LoadingIndicator и мгновенно import(/* webpackPreload: true */ «ChartingLibrary»). Когда запрашивается страница, использующая ChartComponent, также запрашивается charting-library-chunk через <link rel=»preload»>. Предположим, что page-chunk меньше и грузится быстрее, тогда страница отобразится с LoadingIndicator, пока не загрузится уже запрошенный charting-library-chunk. Это даст небольшое ускорение в загрузке, так как нужен всего 1 запрос, а не 2. Особенно на устройствах с высокой задержкой.

Неправильное использование webpackPreload может ухудшить производительность. Используйте это осторожно.

Если выбирать между preload и prefetch, то, наверное, выберите prefetch. Заметка: это касается Webpack import(). В HTML страницах вы, скорее всего, захотите использовать preload.

Несколько предварительно полученных частей

Вы можете добавить флаг webpackPrefetch в любое количество import (), но обратите внимание, что все предварительно загруженные куски сражаются за пропускную способность. Они фактически поставлены в очередь, и действительно используемый фрагмент может не быть предварительной выборкой, когда пользователь запрашивает его.

Это не проблема, когда все куски в равной степени могут быть запрошены. Но когда некоторые куски более вероятны, чем другие, вы, скорее всего, захотите контролировать порядок предварительной выборки.

К счастью, мы прикрыли вас. (обратите внимание, что это расширенный сценарий использования)

Вместо использования webpackPrefetch: true вы можете передать число как значение. webpack будет предварительно отбирать куски в указанном вами порядке. Пример: webpackPrefetch: 42 будет предварительно получен перед webpackPrefetch: 1, который будет предварительно выбран до webpackPrefetch: true, которое будет предварительно выбран перед webpackPrefetch: -99999 (например, z-order). Фактически true считает 0.

Точно так же для webpackPreload, но я не думаю, что вам это понадобится!

FAQ

Что если несколько import() запрашивают одну часть и некоторые уже предварительно выбраны/загружены?

Preload выше prefetch. В таком случае побеждает наивысший приоритет.

Что если prefetch/preload не поддерживается в браузере?

Браузер это игнорирует. Webpack не пробует применять фолбеки. Это лишь подсказка, поэтому даже браузер с поддержкой может ее проигнорировать.

Prefetch/preload не работает на входной точке. Что не так?

webpack runtime заботится только о prefetch/preload для частей on-demand-loaded. Когда prefetch/preload используется в import() во входной части, за добавление тегов в HTML отвечает HTML генерация. Json со статистикой предоставляет информацию в entrypoints[].childAssets.

Почему нельзя использовать prefetch/preload на всех import()?

Вы потеряете впустую много трафика. Также более выгодно использовать их выборочно для import (), которые, скорее всего, будут посещены. Не тратьте трафик в пустую. У некоторых ограничен объем или пропускная способность. Для получения максимальной выгода используйте выборочно!

Я не хочу/мне не нужна эта функция. Что будет, если ее не использовать?

Код времени выполнения добавляется только тогда, когда эта функция используется в одном из ваших блоков on-demand-loaded. Поэтому, когда вы его не используете, вам не нужно платить никаких накладных расходов.

У меня на import() уже есть магический комментарий. Можно добавить несколько магических комментариев?

Да, через разделитель, или отдельные комментарии:

import( /* webpackChunkName: "test", webpackPrefetch: true */ "LoginModal"
)
// or
import( /* webpackChunkName: "test" */ /* webpackPrefetch: true */ "LoginModal"
)
// spacing optional

Я создаю свою библиотеку с помощью rollup и также использую import (). Могут ли пользователи моей библиотеки, которые используют webpack, выигрывать от предварительной выборки?

Да, вы можете добавить волшебные комментарии webpack к import (), и rollup сохранит комментарий. Когда результат, который он построил с помощью webpack, будет использовать комментарий. Когда он не построен с помощью webpack, комментарий удаляется с помощью минимизаторов.

Я не уверен, что добавление предварительной выборки для конкретного import () повышает производительность. Должен ли я добавить его?

Лучше всего это измерить. A / B тестирование. Здесь нет общих советов. Это зависит от вероятности посещения пользователями этого пути приложения.

У меня уже есть сервис воркер, который кэширует все приложение при загрузке. Нужен ли мне prefetch?

Это зависит от вашего приложения. В общем, такой сервис воркер загружает все файлы приложения в произвольном порядке, а предварительная выборка позволяет указать порядок и зависит от фактического положения пользователя в приложении. Предварительная выборка также более эффективна с точки зрения пропускной способности и загружается только в режиме простоя браузера. Предварительная выборка позволяет указать порядок и зависит от фактического положения пользователя в приложении. Prefetch также более эффективен с точки зрения пропускной способности и загружает только время простоя браузера.

Измерьте, сколько времени требуется для загрузки всего приложения в среде с низкой пропускной способностью, по сравнению с тем, когда происходит первая пользовательская навигация. В огромных приложениях было бы целесообразно использовать предварительную выборку.

Я хочу разбить загрузку начальной страницы на критические ресурсы и некритический ресурс и загрузить их в этом порядке. Поможет ли предварительная загрузка?

Да, вы можете поставить критические ресурсы в точку входа и некритические ресурсы за import () с помощью webpackPreload: true. Обратите внимание: не забудьте добавить <link rel = «preload»> для дополнительных элементов для ввода (перед тегами для детей).

Автор: Tobias Koppers

Источник: https://medium.com/

Редакция: Команда webformyself.