Учитываем окружение

Используйте прогрессивное улучшение по умолчанию

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

Используя подход adaptive module serving, мы выводим прогрессивное улучшение на другой уровень: для слабых устройств выдаём облегчённую версию, а для более мощных дополняем интерфейс новыми возможностями.

Выберите надёжный базовый уровень производительности

Существует множество факторов, влияющих на загрузку: сеть, thermal throttling, особенности работы кэша, сторонние скрипты, задержка выполнения парсинга операции ввода-вывода, задержка IPC, установленные расширения, антивирусное программное обеспечение и брандмауэры, фоновые задачи ЦП, аппаратные ограничения и ограничения памяти, размеры L2/L3 кэшей, RTTS. При этом большая часть нагрузки обусловлена JavaScript, а также шрифтами, блокирующими рендеринг по умолчанию, и изображениями, часто потребляющими слишком много памяти. Все эти проблемы просачиваются от сервера на клиентскую сторону. Разумеется, вы не можете влиять на эти параметры, но их определенно стоит учитывать

Рекомендуемые 170 КБ уже содержат в себе критический путь HTML/CSS/JavaScript, роутер, стейт менеджеры, различные утилиты, фреймворки и логику приложения. Поэтому следует тщательно следить за объемом передаваемых по сети данных, временем парсинга/компиляции и временем выполнения (runtime) для сторонних библиотек и фреймворков, которые вы используете. К счастью, за последние несколько лет браузеры научились гораздо лучше парсить и компилировать скрипты. Вместе с этим, выполнение JavaScript по-прежнему остается основным узким местом.

Тим Кадлец (Tim Kadlec) провел замечательное исследование производительности современных фреймворков.

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

В целом, современные фреймворки плохо заточены под дешёвые малопроизводительные устройства, поэтому скорость работы интерфейса для телефона и десктопа чаще всего существенно отличаются. По словам Тима:«Если вы используете фреймворк для создания сайта, это всегда компромиссное решение с точки зрения производительности. Даже в лучших сценариях».
Процессорное время разных фреймворков и влияние размера JavaScript для мобильных устройств и для десктопных устройств. Как видно, приложения на основе React или Angular тратят больше процессорного времени, чем другие. Источник: Исследование Тима Кадлека. (Увеличить)

Оцените фреймворк и зависимости

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

Размер всех фреймворков достаточно велик: 58,6% React-страниц весят более 1 МБ JavaScript, а скорость первой значимой отрисовки (First Contentful Paint — FCP) у 36% загрузок на Vue. js составляет больше 1,5 секунд. Согласно исследованию Анкура Сэтхи (Ankur Sethi), на среднем телефоне в Индии React-приложение никогда не будет загружаться быстрее, чем 1,1 секунды. Приложение на Angular загрузится как минимум за 2,7 секунды. Пользователям приложения на Vue придется подождать не менее 1 секунды, прежде чем они смогут его использовать. Возможно, Индия — не ваш целевой рынок. Но у любого пользователя может быть та же картина при работе на медленном соединении. Конечно, можно сделать быстрые SPA (Single Page Application), Но следует учитывать время и усилия, необходимые для того, чтобы обеспечить его высокую производительность. Очевидно, сделать это будет проще, если уже на ранней стадии проекта вы заложите более лёгкий бюджет производительности.

Так как же выбрать фреймворк? Будет здорово для начала уменьшить хотя бы общий размер + начальное время выполнения. Легкие варианты, такие как Preact, Inferno, Vue, Svelte, Alpine или Polymer, могут отлично справиться с этой задачей. Как отметил Себ Маркбоге (Seb Markbåge), лучший способ определить исходные параметры для фреймворков — сначала отрисовать интерфейс, затем удалить его, а затем отрисовать снова. Таким образом вы сможете увидеть, как масштабируется фреймворк и как он соответствует вашим начальным требованиям производительности
Первая отрисовка имеет тенденцию «разогревать» лениво компилируемый код. Второй рендеринг покажет, как влияет переиспользование кода на характеристики производительности при усложнении страницы.

Оценить работу фреймворка (или любой библиотеки JavaScript) можно с помощью 12-балльной системы оценки от Sacha Greif, исследуя возможности, доступность, стабильность, производительность, экосистему пакетов, сообщество, кривую обучения, документацию, инструменты и т. д.

Perf Track. Сравнение фреймворков по разным параметрам (Увеличить)
Вы также можете полагаться на другую статитстику. Например, Perf Track отслеживает производительность фреймворков в динамике и выдает агрегированную оценку Core Web Vitals для веб-сайтов, созданных на Angular, React, Vue, Polymer, Preact, Ember, Svelte и AMP. Вы даже можете указывать и сравнивать веб-сайты, созданные с помощью Gatsby, Next. js или Create React App, а также веб-сайты, созданные с помощью Nuxt.js (Vue) или Sapper (Svelte).

Вы можете начать с выбора хорошего дефолтного стека. У Gatsby (React), Next.js (React), Vuepress (Vue), Preact CLI, и PWA Starter Kit есть возможности для быстрой загрузки контента на среднем мобильном устройстве. Кроме того, обратите внимание на web.dev framework-specific performance guidance for React and Angular.

Производительность процессора и вычислений самых продаваемых телефонов (Источник: Addy Osmani) (Увеличить).
Возможно, вам стоит пересмотреть свой подход к созданию SPA в целом и взглянуть на Turbolinks. Это 15-килобайтная JavaScript-библиотека, которая использует HTML вместо JSON для рендеринга страниц. Когда вы переходите по ссылке, Turbolinks автоматически выбирает страницу, обновляет <body> и объединяет теги <head>. Все это происходит без затрат на полную загрузку страницы. Смотрите краткую информацию и полную документацию о стеке (Hotwire).
Впрочем, сейчас не каждому проекту нужен фреймворк, и не каждая страница приложения должна загружать фреймворк. В примере Netflix удаление React, нескольких библиотек и соответствующего кода на клиентской стороне уменьшило общий объем JavaScript более чем на 200 КБ, что привело к сокращению TTI более чем на 50% для главной страницы Netflix при первоначальной загрузке. При этом, во время пребывания пользователя на целевой странице, шла предварительная загрузка React для последующих страниц (подробности здесь).

А что если полностью удалить существующий фреймворк с критически важных страниц? У Gatsby есть плагин gatsby-plugin-no-javascript, который позволяет удалить весь JavaScript, созданный Gatsby, из статических файлов HTML. В Vercel есть экспериментальная возможность отключить исполнение JavaScript для некоторых страниц.