Как ускорить сайт: быстрые победы для молодого приложения
Как ускорить сайт или веб-приложение без переписывания: картинки, индексы в базе, кеш, меньше запросов, ленивая загрузка — и как замерить результат до и после.
Производительность — это то, насколько быстро приложение показывает человеку нужное и отвечает на его действия. Чтобы ускорить сайт на раннем этапе, почти никогда не нужно переписывать архитектуру: основное время обычно съедают несколько простых вещей — тяжёлые картинки, запросы к базе без индексов и лишние обращения к серверу.
Проект на вайбкоде на пустой базе и быстром ноутбуке летает. Медленным он становится у человека с телефоном среднего уровня, в метро, когда в таблице уже десять тысяч строк. Ниже — порядок действий, который даёт заметный результат за день-два.
Сначала замерь, потом ускоряй
Без замера ты будешь оптимизировать то, что кажется медленным, а не то, что медленное на самом деле. Перед любыми правками запиши исходные цифры.
- Lighthouse во вкладке инструментов разработчика Chrome. Запускай в режиме мобильного устройства и смотри на время до появления основного содержимого и на общий вес страницы.
- Вкладка Network с включённым замедлением сети. Сортировка по размеру сразу показывает самые тяжёлые файлы, по времени — самые медленные запросы.
- Время ответа сервера для основных API — из логов или из мониторинга. Если эндпоинт отвечает дольше секунды, проблема почти наверняка не во фронтенде.
Замеряй одни и те же страницы в одинаковых условиях до и после. Запиши цифры прямо в описание изменения — через месяц пригодится.
Картинки: самый дешёвый выигрыш
Чаще всего страницу тормозит одна-две картинки, загруженные как есть: фотография с телефона на несколько мегабайт, показанная в карточке размером с ладонь.
- Сжимай и уменьшай картинки до того размера, в котором их показывают, с запасом для экранов высокой плотности.
- Используй современные форматы — WebP или AVIF вместо PNG и JPEG там, где это возможно.
- Указывай ширину и высоту, чтобы страница не прыгала при загрузке.
- Если пользователи загружают свои изображения, уменьшай их при загрузке на сервере, а не показывай оригинал.
Индексы в базе данных
Индекс — это оглавление для таблицы. Без него база при каждом запросе просматривает все строки подряд. Пока строк сто, разницы нет; когда их сто тысяч, запрос, который занимал миллисекунды, начинает занимать секунды.
Признак проблемы: страница со списком замедляется по мере роста данных, хотя код не менялся. Чтобы ускорить сайт в таком случае, посмотри, по каким полям чаще всего фильтруют и сортируют, — обычно это user_id, статус и дата создания, — и добавь индексы именно на них:
create index orders_user_created_idx on orders (user_id, created_at desc);
Проверить, использует ли запрос индекс, можно командой explain перед запросом. Индексы на всё подряд ставить не нужно: каждый замедляет запись и занимает место.
Меньше запросов
Вторая частая причина — слишком много обращений к серверу или к базе.
- Проблема N+1. Код получает список из пятидесяти заказов, а потом для каждого отдельно запрашивает покупателя. Пятьдесят один запрос вместо одного-двух. ИИ-ассистенты пишут такой код охотно, потому что он простой.
- Повторы на клиенте. Один и тот же запрос уходит при каждом переходе между экранами. Библиотеки загрузки данных умеют кешировать ответы и не спрашивать заново то, что только что получили.
- Лишние поля. Запрос забирает все колонки, включая большие текстовые, а на экране нужны две.
Кеширование
Кеш — это сохранённый ответ, который можно отдать повторно, не вычисляя заново.
- Статику — скрипты, стили, картинки — отдавай с долгим сроком кеширования и с хешем в имени файла. Большинство сборщиков делают это сами, главное — не сломать настройки хостинга.
- Данные, которые меняются редко, — каталог, настройки, публичные страницы — можно кешировать на сервере на минуты.
- Не кешируй персональные данные там, где их может получить другой пользователь. Это уже не ускорение, а утечка.
Ленивая загрузка
Не всё нужно загружать сразу. Картинки ниже первого экрана получают атрибут loading="lazy". Тяжёлые части интерфейса — редактор, графики, карта — подгружаются, только когда человек до них дошёл. Чем меньше JavaScript на первом экране, тем быстрее страница становится отзывчивой на телефоне.
Коротко
- Ускорить сайт на раннем этапе обычно можно без переписывания: основное время съедают картинки, база и лишние запросы.
- Сначала замер на мобильном режиме и медленной сети, потом правки, потом повторный замер тем же способом.
- Сжатые картинки в современных форматах дают самый дешёвый выигрыш.
- Индексы на полях фильтрации и сортировки и устранение N+1 спасают, когда растут данные.
- Кеш для статики и редких данных, ленивая загрузка для всего, что ниже первого экрана.
Если приложение стало медленным и непонятно почему, SUBXCAT может найти узкие места и убрать их, не переписывая проект.