Мой собственный опыт создания моего первого React SPA и пошаговый путь к достижению оценки производительности 100/100 и получению всех значков PWA в Google Lighthouse

В этой статье я делюсь своим скромным опытом создания веб-продукта, с самого начала фокусируясь на оптимизации веб-производительности и реализации PWA для https://www.vinivox.com, моей личной попытки взломать цифровые заметки для дегустаторов вин.

Постановка задачи

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

Обычно сегодня у этих «продвинутых» дегустаторов есть два способа сделать свои вкусовые заметки:

  • Использовать бумажные заметки (пример): совсем не удобно и не практично по многим причинам, например, по хранению или транспортировке.
  • Используйте собственное приложение (WSET, Другое)

Вариант 2 связан с некоторыми проблемами:

  • Нативные приложения действительно обеспечивают очень инстинктивное и плавное взаимодействие, но большинству из них не хватает поддержки нескольких экранов / устройств, что затрудняет переключение между экранами.
  • Еще одна проблема с текущими доступными приложениями - это отсутствие выбора шаблонов: каждое приложение подталкивает пользователей к использованию собственного шаблона, который обычно не подходит для всех пользовательских ситуаций. Например, пользователь может захотеть использовать простой базовый шаблон, когда он находится в ресторане с друзьями, но более сложный, когда доступно больше времени.
  • Также очень популярные винные приложения, такие как Vivino, часто не обеспечивают достаточной сложности для дегустаторов (только 5-звездочный рейтинг).

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

Основные потребности пользователя

Чтобы оказать влияние на пользователей, необходимо удовлетворить 3 ключевые потребности:

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

Ценностное предложение

Нативные приложения, даже если они обычно обеспечивают мощный UX и внешний вид, ориентированный на мобильные устройства, не могут удовлетворить потребность в многоэкранной поддержке в любом масштабе. Они также страдают от проблем с обнаружением, поскольку их нужно найти и загрузить из магазинов приложений, а затем установить на устройства пользователей. Как следствие, они не соответствуют основным требованиям проекта для легкого обнаружения. Платформа Vinivox будет веб-интерфейсом, что обеспечит многоэкранную поддержку и простой / открытый доступ.

Наша цель - создать лучшее в своем классе веб-приложение, основанное на одной из последних сред разработки на основе Javascript (JS) (одностраничные приложения или SPA) и опирающееся на современные технологии mWeb.

Начиная с агрессивных целей с первого дня:

  • Приложение должно быть защищено ›Цель: запускать по HTTPS.
  • Приложение должно быть быстрым ›Цель: 90 + / 100 в Google Lighthouse Performance
  • Приложение должно быть обнаружено в Поиске Google для некоторых страниц с релевантным содержанием ›Цель: отображение некоторых страниц содержания в Поиске Google
  • Приложение должно быть «устанавливаемым» и работать в автономном режиме как PWA ›Цель: 100/100 в Google Lighthouse PWA, чтобы получить все значки PWA.
  • Характеристики пользовательского интерфейса

Настройка проекта

Переход на фреймворк SPA

Учитывая потребности пользователей в быстром и плавном взаимодействии с приложением, когда они заполняют свои заметки о дегустации, использование веб-сайта, построенного на платформе одностраничных приложений (SPA), имеет большой смысл в контексте этого проекта.
Напоминаем, что одностраничное приложение - это приложение, которое работает внутри браузера и не требует перезагрузки страницы во время использования. SPA предназначены для обслуживания выдающегося UX, пытаясь имитировать «естественную» среду в браузере - без перезагрузки страницы, без дополнительного времени ожидания. Это всего лишь одна веб-страница, которую посещают пользователи, которая затем загружает весь остальной контент с помощью JavaScript, от которого они сильно зависят.

SPA запрашивает разметку и данные независимо и отображает страницы прямо в браузере. Одностраничные сайты помогают удерживать пользователя в одном удобном веб-пространстве, где контент предоставляется пользователю простым, легким и работоспособным способом. Это соответствует нашим первоначальным ожиданиям.

Самыми известными фреймворками, используемыми сегодня в экосистеме, являются: Vue.js, React JS, Angular,… Основываясь на начальных спецификациях моего проекта, быстрый тест показал, что все эти 3 фреймворка смогут предоставить ожидаемые функции.

Уже работая с Angular в других проектах, я решил работать с React JS.
React - это фреймворк, который сегодня очень быстро распространяется, и я хотел понять влияние этого фреймворка на производительность (а также протестировать его в реальный случай), а также понять, как решать проблемы, связанные с поиском, в контексте React JS.

В качестве инструмента для связывания модулей мы будем использовать WebPack JS, который изначально интегрирован в готовые сборки React JS, используя очень хороший инструмент React CLI (см. Здесь).

Выбор платформы, на которой запущен бэкэнд

React JS - это фреймворк, который для работы необходимо развернуть на движке Node JS.
Проект будет размещен на Firebase, платформе Google, которая предоставляет бесплатное решение для начинающих разработчиков, которые могут размещать SPA на сервере на основе node.js. Выбор Firebase явился естественным, поскольку я также хотел протестировать эту платформу как продукт, и это ценностное предложение выглядело многообещающим с точки зрения возможностей безотказной работы и скорости сервера: независимо от того, где находится пользователь, контент на самом деле доставляется быстро, поскольку сайты развертываются на Хостинг Firebase кэшируется на твердотельных накопителях на пограничных серверах CDN по всему миру.

Это хостинговое решение по умолчанию использует шифрование HTTPS с бесплатными сертификатами SSL, что прекрасно решает задачу создания безопасного веб-сайта с первого дня. Firebase изначально интегрирует небольшую платформу управления DNS, которая позволяет вам использовать свой собственный веб-домен.

Firebase также поддерживает надежный интерфейс командной строки, который очень помогает при развертывании. Наконец, платформа предлагает возможность отката в один клик.

Вдобавок ко всему, Firebase выглядела очень удобной для этого проекта, потому что платформа также предоставляет несколько дополнительных API, реализованных на стороне клиента, которые я смогу легко интегрировать в веб-приложение для различных целей:

  • API-интерфейсы баз данных с двумя типами баз данных Nosql: облачное хранилище на основе документов (скорее всего, для заметок о дегустации) и быстрая и эффективная база данных в реальном времени (для ссылок на вина)
  • API аутентификации, включая несколько популярных методов аутентификации, таких как электронная почта / пароль, вход в Google, подключение к Facebook
  • Облачные функции Google: возможность запускать собственный бэкэнд-код без необходимости управлять собственной логикой сервера и масштабировать ее.
  • Возможности хранения: например, для хранения изображений или медиаресурсов.

Создание лучшего в своем классе веб-приложения

Формирование структуры приложения

На очень высоком уровне приложение должно выглядеть так:

Сосредоточьтесь на опыте пользователя

  1. Быть адаптивным

Чтобы сайт мог работать на нескольких устройствах с одной и той же кодовой базой, он должен быть построен с адаптивным дизайном - способом собрать веб-сайт таким образом, чтобы он автоматически масштабировал его содержимое и элементы в соответствии с размером экрана, на котором он просматривается. . Конечная цель адаптивного дизайна - избежать ненужного изменения размера, прокрутки, масштабирования или панорамирования, которые происходят с сайтами, которые не были оптимизированы для разных устройств. Навигация по этим сайтам часто бывает очень сложной.
Адаптивный дизайн веб-сайта также заменяет предыдущую потребность в разработке специального мобильного веб-сайта для пользователей смартфонов. Теперь вместо того, чтобы разрабатывать несколько веб-сайтов для разных размеров экрана, можно создать только один веб-сайт, который автоматически масштабируется вверх или вниз в соответствии с устройством, на котором он просматривается. Это соответствует первоначальным требованиям.

2. Следуйте модели App Shell

Чтобы обеспечить ориентированность на мобильные устройства и приложения, мы должны были максимально приблизиться к внешнему виду и дизайну нативного приложения. Это цель оболочки приложения: архитектура оболочки приложения (или оболочки приложения) - это один из способов создания прогрессивного веб-приложения, которое надежно и мгновенно загружает оболочку содержимого на пользовательские экраны, аналогичные тем, что вы видите в собственных приложениях.

К счастью, одностраничные приложения, подобные тому, которое использовалось в проекте, React JS, действительно хорошо вписываются в эту концепцию, поскольку их цель - вводить контент через Javascript в файл index.html, который будет действовать как «оболочка».

При этом эта настройка по-прежнему требует дополнительного внимания с точки зрения UX, которое может повлиять на структуру кода сайта: вы можете использовать необработанный файл index.html без содержимого, который будет действовать только как место, где доставляется контент. с помощью веб-приложения или встроить некоторые повторяющиеся элементы из пользовательского интерфейса напрямую в оболочку. Оба параметра влияют на то, как пользовательский интерфейс будет кэшироваться браузером.

Я решил встроить верхний и нижний колонтитулы своего приложения непосредственно в оболочку index.html, где взаимодействие с этими элементами будет обрабатываться вне среды React JS с использованием Vanilla Javascript.

3. Варианты CSS

Выбор библиотеки CSS должен соответствовать следующим критериям:

  • Открытый исходный код
  • Легкий (очень важно для производительности)
  • Бесплатно
  • Отзывчивый
  • JS бесплатно
  • Легко настроить и обрезать (если возможно, с помощью Sass)

Как следствие, выбор был сделан в пользу Bulma, CSS-фреймворка с открытым исходным кодом, основанного на Flexbox и используемого более чем 100 000 разработчиков. Bulma предлагает высокую гибкость и легкий комплект.

Пора сосредоточиться на веб-производительности!

Контекст

Эта тема, безусловно, самая сложная в этом проекте и по умолчанию требует некоторого дополнительного внимания для обеспечения того, чтобы большинство лучших практик по производительности было доставлено с первого дня. Этот элемент имеет решающее значение для создания надежной веб-платформы, поскольку, как заявляет Google, «Более 50% потребителей покинут мобильный сайт, если он загружается более 3 секунд». Цель состоит в том, чтобы по умолчанию полагаться на очень быстрое веб-приложение.

Есть еще одна большая проблема: хорошо известно, что одностраничные приложения, такие как те, которые созданы с помощью React JS, имеют более медленную загрузку первой страницы, чем серверные приложения. Это связано с тем, что первая загрузка должна вывести из строя фреймворк и код приложения перед рендерингом требуемого представления в виде HTML в браузере. Серверное приложение просто должно протолкнуть необходимый HTML-код в браузер, уменьшая задержку и время загрузки.
Следовательно, внедрение передовых методов для ускорения загрузки SPA требует особого внимания.

Внедрение лучших практик оптимизации

Вот оптимизации, над которыми я работал:

Ускорьте первое впечатление.

Избегайте переадресации целевой страницы:

  • ✅ Сайт выполнен в адаптивном дизайне

Сжимайте и выбирайте эффективные изображения:

  • Сжатие: ✅ Все изображения сжимаются на лету с помощью gulp-imagemin, а также изменяются до нескольких размеров, адаптированных к разным размерам области просмотра.
  • Использование современных форматов: ✅ Все изображения конвертируются в Progressive JPEG и WebP

Выберите эффективные изображения:

  • ✅ Клиентский HTML использует семантический элемент HTML5 ‹picture›, который позволяет вам предоставлять набор изображений, сюда доставляются изображения WebP (только формат Chrome) и JPG вместе с медиа-запросами CSS.

Приоритет загрузки видимого контента, отложить / асинхронно некритичный JS:

  • Vanilla JS и обращение к сторонним службам: ✅ Все сторонние JS вызываются асинхронно, интегрированный Диспетчер тегов Google для обработки сценариев согласия на использование файлов cookie. Весь ванильный JS доступен после события DOM Ready
  • Оптимизация пакетов React JS: это будет рассмотрено в следующем разделе

Извлечь критический CSS:

  • ❓ Вероятно, один из элементов, который еще можно оптимизировать, мы извлекаем важные классы CSS и встраиваем все классы CSS непосредственно в оболочку.
    ›Некоторые классы CSS не используются на нескольких страницах, но в целом размер всего CSS остается очень маленьким, поэтому возможности незначительны.
    › Другой важный вывод: я считаю, что с первого дня мне следовало использовать CSS в логике компонентов, чтобы не увязнуть в переполненном пакете CSS, и позволить WebPack фактически работать за меня.

Постепенно загружайте ожидаемые данные, используйте советы по ресурсам:

  • Ленивая загрузка: ✅ Реализовать при загрузке данных для страниц профиля, а также для изображений.
  • Подсказки по ресурсам: ✅ Используйте предварительную загрузку, предварительное подключение, предварительную выборку

Ограничение обращений к серверу:

Включить HTTPS:

  • ✅ Предоставляется Firebase Hosting по умолчанию

Включить HTTP / 2:

  • ✅ Предоставляется Firebase Hosting по умолчанию

Максимальное использование кеширования браузера:

  • ✅ Пакеты JS, предоставляемые при сборке WebPack, настроены таким образом, что в них встроен ключ блокировки кеша.
    Как следствие, можно максимально расширить стратегию кеширования, чтобы пакеты JS и каждый повторяющийся элемент имели кеш, установленный на максимально долгое время. Мы переопределили настройки хостинга Firebase, чтобы максимизировать это.

Оптимизация доставки контента:

Уменьшите время ответа сервера:

  • ✅ Высокая производительность, обеспечиваемая Firebase Hosting по умолчанию

Сжать с помощью Gzip:

  • ✅ Предоставляется Firebase Hosting по умолчанию

Сократите ресурсы:

  • ✅ Пакеты JS и HTML, предоставляемые при сборке WebPack, имеют конфигурацию, которая должна быть уменьшена и утеряна, а также удалены кавычки.

Сосредоточьтесь на производительности React

Чтобы объяснить эту тему более подробно, давайте сначала подумаем о том, как браузер загружает SPA:

В жизненном цикле SPA первый ответ сервера отправит браузеру оболочку index.html вместе с CSS и JS, необходимыми для запуска приложения (также известный как JS Bundle). Этот пакет JS обычно является синхронным, что означает, что браузер ожидает, пока все функции будут обработаны: чем тяжелее или даже хуже, чем он менее оптимизирован, тем больше времени потребуется браузеру, чтобы быть готовым.

По умолчанию фреймворки SPA обычно поставляют тяжелые пакеты JS, что требует очень больших затрат с точки зрения производительности.
Как подчеркивается в этой отличной статье Адди Османи, есть много оптимизаций, которые можно добавить в веб-приложение React по умолчанию. Очевидно, это требует дополнительных усилий для добавления в код.

Ниже приведены улучшения, реализованные в Vinivox:

✅В целом с помощью этого решения основной пакет уменьшился с 2,5 МБ до ‹500 КБ, время загрузки страницы увеличилось на 5 секунд, а оценка Lighthouse - с 45 до 80.

Соображения по SEO

Контекст

Из-за отсутствия выполнения JavaScript на сканерах некоторых популярных поисковых систем, SEO (поисковая оптимизация) исторически представляла проблему для общедоступных веб-сайтов, желающих принять модель SPA и желающих быть обнаруживаемыми в поисковых системах.
Хотя это активно обсуждается в Интернете (см. Видео здесь), хорошая новость заключается в том, что на самом деле существует множество технических ответов для решения этой проблемы.
Давайте помнить о главной цели Vinivox: быть личным приложение для создания заметок. Как следствие, не все страницы задуманы как общедоступные по дизайну или открытые, поэтому SEO само по себе не нужно создавать в больших масштабах.
Следовательно, важно найти правильный баланс с точки зрения требований SEO, поскольку только несколько содержательных страниц должны быть открыты для обнаружения сканером

Добавление слоя рендеринга на стороне сервера

Решение для улучшения возможности обнаружения Vinivox SPA при поисковой оптимизации называется «рендеринг на стороне сервера», и его концепция поясняется на изображении ниже:

Рендеринг на стороне сервера (далее SSR) - это способность интерфейсной инфраструктуры отображать разметку во время работы в серверной системе. С SSR пользователю (а также поисковому роботу!) Не нужно ждать, пока JS установится и загрузится, и он получает полностью отрисованный HTML, как только первоначальный запрос возвращает ответ.

С технической точки зрения, учитывая, что эта функция изначально не поддерживается в Firebase JS, ее необходимо реализовать как дополнительную функцию.

Решение должно быть развернуто на функции Google Cloud, настроив стратегию маршрутизации сервера Firebase и используя сервер Express JS. Решение объясняется на высоком уровне здесь.

Ожидаемые характеристики:

  • Каждый маршрут отслеживается, и вызовы на сервер Firebase перенаправляются в облачную функцию, на которой запущен Express JS в качестве промежуточного сервера.
  • Инициируйте маршрутизацию в облачной функции, чтобы напрямую ввести в HTML-ответ требуемое содержимое страницы, мета-данные поисковой системы (заголовок, роботы, описание и т. Д.) И данные Open Graph. Оболочка index.html очень полезна в этом контексте, так как это страница шаблона, которая будет загружена
  • Браузер загружает пакет React JS Bundle параллельно, после чего React берет на себя управление приложением, как только все будет выполнено.

✅С этой настройкой Vinivox теперь может корректно сканироваться и отображаться в результатах поиска в Google Search.

Улучшения производительности

Еще одна хорошая новость при использовании SSR заключается в том, что он, очевидно, ускоряет доставку HTML, поскольку HTML теперь отображается сервером, а не дожидается, пока приложение React вставит контент в оболочку.

Затронутая метрика - это первая значимая окраска затронутых страниц, включая домашнюю страницу (то есть время, необходимое для отображения основного содержимого страницы), улучшенная на 0,7 с с 2,2 до 1,5 с в сети 3G. Быстро.

Представляем функции прогрессивного веб-приложения

Что PWA может добавить в Vinivox?

Прогрессивное веб-приложение (или PWA) - это в основном набор функций W3C, созданных для улучшения возможностей взаимодействия с веб-сайтами, таких как возможность добавлять значок на рабочий стол, отправлять push-уведомления и даже добавлять возможность взаимодействия с веб-приложением в автономном режиме.

Как это работает?

Функции PWA в основном полагаются на прокси-сервер на основе JS, который будет установлен в браузере параллельно с веб-приложением и сможет перехватывать запросы к сети для возможного взаимодействия с некоторыми API-интерфейсами кеша браузера, отправки push-уведомлений, так далее…

Учитывая первоначальные требования, не все эти функции действительно будут актуальны для Vinivox.

На ум приходят четыре основных варианта использования:

  • Добавить на главный экран: возможность для веб-приложения устанавливать значок на главный экран телефона с возможностью запускать веб-приложение с этого значка в полноэкранном режиме.
    ›Эта функция очень удобно, поскольку дегустаторы вин регулярно хотят заходить в свои веб-приложения прямо через главный экран, чтобы вводить новые заметки
  • Кэширование и ускорение: одна очень интересная возможность сервис-воркеров - это их способность получать все запросы в сеть, используя элементы, помещенные в кеш сервис-воркером.
    ›Эта функция делает общий Учитывая, что нам нужно быстрое и надежное веб-приложение
  • Офлайн: возможность сохранять заметки, даже когда пользователь не в сети.
    ›Очень удобная функция для пользователей в любых ситуациях

Добавить на домашний экран

Чтобы соответствовать недавнему выпуску новых шаблонов для грядущего Chrome 68, было важно реализовать эту функцию в соответствии с рекомендуемыми передовыми практиками: «Добавить на главный экран» (A2HS) обычно работает лучше, когда разработчики помещают, перед подсказкой собственного браузера, их собственное приглашение, стилизованное под UX сайта, объясняющее ценностное предложение функции.

Как следствие, приложение должно реализовать событие beforeinstallprompt, как это очень подробно описано в этой статье, очевидно, вместе с базовыми спецификациями, необходимыми для работы A2HS (добавить файл manifest.json и т. Д.)

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

Кеширование с помощью Service Worker

Одной из основных особенностей Service Workers является их способность программно использовать Cache API. Хотя технология Service Worker определенно может быть написана на простом ванильном JS, есть несколько пакетов, которые пригодятся для упрощения и оптимизации развертывания и управления кодом, например sw-preache или Worbox.

Workbox - это самый последний пакет, набор библиотек JavaScript для добавления автономной поддержки веб-приложений, поддерживаемый Google. Это пакет, который использовался Vinivox при разработке технологии SW.

Учитывая, что Vinivox полагается на Webpack для создания как среды разработки, так и производственной среды, мы решили использовать плагин Webpack Workbox, чтобы напрямую интегрировать генерацию SW в процесс сборки.

Вот что делается на сегодняшний день:

  • SkipWaiting: ПО настроено таким образом, что последний работник службы активируется, как только он переходит в фазу ожидания.
  • Предварительное кэширование: по умолчанию Workbox вставляет в список элементов для кеширования во время установки ПО все элементы, сгенерированные Webpack во время сборки (в основном js-файлы). Мы переопределили настройки, чтобы иметь возможность также вставлять в кеш некоторые статические js и файлы, а также несколько необходимых изображений.
  • Кеширование при взаимодействии пользователя с веб-приложением: этого можно достичь с помощью Runtimecaching, используя различные стратегии кеширования (сначала кэширование изображений, гонка сети и кеширования для JS)

Автономное использование с Service Worker

Кэширование с помощью Service Worker также позволяет предоставить пользователям потенциальную возможность работы в автономном режиме, поскольку технология SW позволяет извлекать некоторые активы, хранящиеся в кеше, через Cache API. Предполагая, что конфигурация Workbox выполнена правильно с использованием параметра navigateFallback, в контексте SPA можно обеспечить перенаправление всех маршрутов на резервную страницу, в нашем случае index.html.

Затем мы скорректировали корень App.js приложения React, чтобы иметь возможность использовать сигнал navigator.OnLine, который браузер предоставляет приложению. Теперь у нас есть способ обрабатывать онлайн-запросы и офлайн-запросы, и мы можем предоставить пользователям базовую резервную «офлайн» страницу.

Мы также динамически настраивали внешний вид CSS, чтобы затенять UX страницы в автономном контексте (но это не функция PWA сама по себе), используя navigator.online API.

Оценка результатов

Google Lighthouse очень удобен, когда вам нужно оценить несколько функций вашего веб-сайта и автоматизировать эти тесты: производительность, доступность, лучшие практики для Интернета, SEO, а также внедрение PWA.

Требования для достижения 100/100 баллов и получения значков PWA довольно высоки и фактически становятся все выше и выше с недавними корректировками порога производительности PWA, которые теперь сосредоточены на метрике «Время до интерактивности».

Вот как Vinivox.com набирает баллы в WebPageTest и модуле Google Lighthouse:

Мое заключение

На самом деле у меня были смешанные чувства, когда я начал рассматривать фреймворки SPA как вариант для создания быстрого веб-приложения, так как я беспокоился, что никогда не смогу достичь таких амбициозных целей с точки зрения веб-производительности. Многие ресурсы в Интернете довольно пессимистично относятся к способности разработчиков создавать быстрые веб-приложения с помощью SPA.

Честно говоря, я знаю, что сегодня Vinivox остается относительно легким веб-приложением. Но я считаю, что нам удалось доказать, что можно создать быстрое и надежное веб-приложение, выполнив несколько основных шагов по оптимизации и подтолкнув React и Webpack, чтобы на самом деле сделать за вас тяжелую работу.

Я рекомендую всем, кто сегодня начинает новый проект с этими фреймворками: создайте и внедрите все шаги, которые я выполнял с первого дня. Лучше потратить время на создание этих прочных основ, чем потом возвращаться ...

Хотите узнать больше? Вы можете найти код здесь, на Github.