От автора: несколько месяцев назад я опубликовал статью о Guess.js. Guess.js — мощная библиотека для прогнозируемого предварительного извлечения JavaScript на основе данных аналитики веб-сайта. Библиотека использует отчеты из источника аналитики (по умолчанию Google Analytics) и создает базовую модель машинного обучения.
Когда пользователь заходит на сайт, с помощью Guess.js на основе модели происходит предварительная загрузка ресурсов, которые, вероятно, понадобятся дальше. Благодаря подходу, основанному на данных, Guess.js предлагает много преимуществ — уменьшает объем извлекаемых данных, не выполняет агрессивное предварительное извлечение в медленных сетях и т. д.
В этом посте мы рассмотрим другой подход к предварительному извлечению, который использует две эвристики:
Пользователи могут посещать ссылки, которые видны на странице
Мы не хотим агрессивно выполнять предварительное извлечение, если пользователь использует медленный интернет
Мы хотим выполнять предварительное извлечение только тогда, когда браузер простаивает
Предварительное извлечение с помощью quicklink
GatsbyJS — это генератор статических сайтов, который славится производством высокоскоростных прогрессивных веб-приложений. Чтобы стать еще быстрее, Gatsby использует агрессивное предварительное извлечение ссылок.
Когда ссылка видна на экране, Gatsby предварительно извлекает контент, связанный с ней. Это достигается с помощью IntersectionObserver путем сопоставления между ссылкой и связанным ресурсом, который доступен во время сборки.
Потенциальным недостатком этого подхода является чрезмерный объем извлекаемых данных, что может привести к дополнительному использования пропускной способности канала. Другая незначительная проблема связана с переходом на страницы, на которые нет прямых ссылок на странице. Этот сценарий возможен, например, когда пользователь обновляет URL-адрес в адресной строке вручную. Guess.js хорошо справляется с обеими проблемами, и, к счастью, для Gatsby есть плагин Guess.js. Однако для использования Guess.js необходим источник аналитики. Возможный компромисс, для которого не требуется аналитика — это предварительное извлечение ресурсов только тогда, когда пользователь использует быстрый канал связи.
quicklink — это проект, который реализует данный алгоритм! Библиотека предварительно извлекает контент, связанный со всеми ссылками, которые в данный момент видны на странице, в случае, если пользователь работает в быстрой сети. quicklink не выполняет предварительное извлечение, если пользователь работает в сети 2G или медленнее. Для определения сети пользователя Guess.js и quicklink используют navigator.connection.effectiveType.
quicklink в Angular
quicklink — это скрипт, который вы вводите на страницу, и он выполняет свою работу. К сожалению, это не относится к платформам, которые управляют собственной маршрутизацией, создавая косвенное отношение между URL-адресом и контентом. Примерами этого являются Angular, React с React Router и т. д. Давайте рассмотрим пример Angular:
import { Routes } from "@angular/router"; export const routes: Routes = [{ path: 'about', loadChildren: './about/about.module#AboutModule' }, { path: 'contact', loadChildren: './contact/contact.module#ContactModule' }, { path: '', redirectTo: '', pathMatch: 'full' }];
С помощью следующего определения маршрутизации мы можем ссылаться на страницу, которую AboutModule будет отображать с помощью routerLink:
<a routerLink="/about">About</a>
quicklink найдет все элементы a на странице во время простоя и предварительно выберет страницу, связанную с их атрибутом href. Принимая во внимание приведенный выше шаблон, это не будет работать, как ожидалось. quicklink не сможет найти пакет, связанный со страницей /about.
Представляем ngx-quicklink
Чтобы позволить всем разработчикам Angular воспользоваться мощной стратегией предварительной выборки, которую предоставляет quicklinkя, я создал ngx-quicklink.
Использование
ngx-quicklink имеет две основные части:
QuicklinkModule — включает в себя несколько внутренних служб и директиву, которая сначала находит все ссылки на маршрутизатор, а затем определяет, когда они видны на экране.
PreloadingStrategy — реализация интерфейса PreloadingStrategy, предоставляемого @angular/router. Он обеспечивает абстракцию для службы, которая решает, должен ли данный маршрут быть предварительно извлечен в данной точке.
Для использования ngx-quicklink сначала убедитесь, что вы установили пакет:
npm i ngx-quicklink --save
Вот как вы можете интегрировать его QuicklinkModule с существующим приложением:
import { QuicklinkModule } from 'ngx-quicklink'; ... @NgModule({ imports: [QuicklinkModule], declarations: [...], exports: [QuicklinkModule] }) export class SharedModule {}
Фрагмент выше добавляет QuicklinkModule к спискам imports и exports из SharedModule. Этот модуль должен быть позже импортирован в AppModule и все отложено загруженные модули. Вам не нужно создавать новый общий модуль, если он у вас уже есть.
Далее, в модуле маршрутизации установите стратегию предварительной загрузки:
import { QuicklinkStrategy } from 'ngx-quicklink'; ... @NgModule({ imports: [RouterModule.forRoot(routes, { preloadingStrategy: QuicklinkStrategy })], exports: [RouterModule] }) export class AppRoutingModule {}
По этой ссылке вы можете узнать, как интегрировать ngx-quicklinkс angular-realworld-example-app.
Как это работает
Вот ключевые особенности ngx-quicklink:
Обнаруживает routerLinks в области просмотра (используя Intersection Observer)
Ожидает, пока браузер не будет в режиме простоя (с помощью requestIdleCallback)
Проверяет, не подключен ли пользователь к медленному соединению (используя navigator.connection.effectiveType) или включен ли режим сохранения данных (используя navigator.connection.saveData)
Предварительно загружает модули с использованием стратегии предварительной выборки Angular)
Существует три основных различия между исходной реализацией quicklink и ngx-quicklink:
quicklink предварительно выбирает ресурсы link[rel=»prefetch»], если они есть, и резервирует их в XMLHttpRequest. ngx-quicklink использует только XMLHttpRequest из-за текущего механизма предварительной загрузки модуля маршрутизатора Angular. Хотя link[rel=»prefetch»] — это лучшая альтернатива, также используемая Guess.js, скорее всего, ваши пользователи не заметят разницы.
ngx-quicklink не только загружает связанные пакеты JavaScript, но также анализирует и оценивает содержимое. Это позволяет еще больше повысить производительность, когда пользователь переходит на другую страницу.
ngx-quicklink загружает все родительские модули запрошенного модуля для предварительного извлечения.
Давайте рассмотрим последний момент. Предположим, у нас есть следующее определение маршрутизации:
export const routes: Routes = [{ path: 'about', loadChildren: './about/about.module#AboutModule' }, ... ];
В AboutModule у нас есть следующий маршрут:
export const routes: Routes = [{ path: 'team', loadChildren: './team/team.module#TeamModule' }, ... ];
Если на странице есть routerLink=»/about/team», ngx-quicklink сначала загрузит AboutModule, а после этого TeamModule.
Заключение
В этой статье мы рассмотрели предварительную загрузку в веб-приложениях. Мы обсудили стратегию предварительного извлечения quicklink. После этого мы рассмотрели разницу между предиктивной предварительной выборкой и quicklink.
В следующем разделе мы введем quicklink в контекст Angular и рассмотрим ограничения оригинальной реализации. Объединив директиву Angular routerLink с PreloadingStrategyngx фреймворка, мы представим реализацию ngx-quicklink — quicklink для Angular.
Источник: https://blog.mgechev.com/
Редакция: Команда webformyself.