Сайты девелоперов почти всегда медленные. И причина у этого одна: слишком много тяжёлого визуала и сложного функционала.
Интерактивные генпланы;
обводки этажей;
планировки в SVG;
рендеры корпусов;
галереи квартир на сотни фотографий.
Всё это сайту современного застройщика жизнено необходимо, покупатель именно за этим и приходит. Но грузится оно долго, и с этим приходится что-то делать.

Главная загвоздка в том, что просто «выкинуть лишнее» тут не получится. Клиент хочет свой красивый генплан и детальные рендеры, и он прав. Значит, нужно ускорять всё, что вокруг. Мы прошли через это на нескольких проектах застройщиков и получившейся опыт собрали в разбор для тех, кому та же задача только предстоит: где реально терялись секунды, обо что мы споткнулись и что в итоге осталось работать в продакшене.
Самое частое, на чём обжигаются, это начать чинить сразу наугад. Подумать, что все проблемы одинаковые и все просто. Взял, раскидал ленивую загрузку по всем блокам подряд, закрыл тикет, красавчик. По факту эффект часто околонулевой, а местами становится даже хуже, чем было.

Поэтому мы каждую страницу сначала прогоняли через Google PageSpeed и смотрели, на что конкретно он ругается. А ругался он на очень разное и на очень многое.
У одних картинок не заданы размеры, и вёрстка дёргается на загрузке.
На другой странице сервер тупит с первым ответом.
Ещё где-то тяжёлый скрипт держит отрисовку.
Болячки разные, лечатся по-разному, и лечить их вслепую значит просто угробить время заказчика и свое. Так что порядок был железный: сначала метрики, потом уже правки.
На сайте застройщика картинки съедают львиную долю веса страницы. И, к счастью, самый быстрый выигрыш тоже лежит именно тут.
Мы написали скрипт, который сам нарезает набор изображений под все нужные разрешения экрана. Телефон тянет лёгкую версию, а не тот же гигантский файл, что уходит на большой десктоп. Банально? Возможно. Но именно этого PageSpeed требовал в первую очередь, и именно это сильнее всего разгрузило мобилку. Отдельно для первого экрана мы прикрутили подмену картинки под мобильную вёрстку: то, что классно смотрится широким баннером, на узком экране частенько превращается в кашу с учетом смены ориентации экрана с горизонтальной на вертикальную.

Вторая штука вообще на полчаса работы, а отдачи прилично. Мы проставили всем изображениям точные width и height. Без них браузер не знает заранее, сколько места отвести под картинку, и страница прыгает по мере подгрузки. Это отдельно бьёт по Core Web Vitals, так что игнорировать не стоит.
Дальше взялись за отложенную подгрузку. Идея понятная: не грузить сразу всё содержимое страницы, а подтягивать по мере того, как пользователь продвигается по странице. Но с одной оговоркой: подтягивать надо заранее, с запасом, чтобы человек не доскроливал до прелоадера и не втыкал в пустой блок.
В каталоге квартир мы перекроили вывод под постраничную ленивую загрузку. Карточки подгружаются порциями, а не вываливаются все тысячи разом, но все равно подгружаются с запасом, чтобы пользователь не ждал. На главной по той же схеме подгружаются блоки ниже первого экрана: пока человек читает шапку, до остального очередь ещё даже не дошла, сервер его пока и не запрашивал.

А вот теперь, пожалуй, одно из самых важных, чему мы научились на своей шкуре. Ленивая загрузка не серебряная пуля, и лепить её везде подряд на все страницы и разделы - нельзя. На одном проекте пришлось, наоборот, пройтись по всему сайту и повыключать её там, где она уже стояла: она конфликтовала с логикой интерфейса и ломала пользователю сценарий и то суперпроработанный CJM разбивался о реальность. Так что это инструмент под конкретное место, а не галочка «включить везде и забыть».
Наша система сама подберет вам исполнителей на услуги, связанные с разработкой сайта или приложения, поисковой оптимизацией, контекстной рекламой, маркетингом, SMM и PR.
Заполнить заявку
13691 тендер
проведено за восемь лет работы нашего сайта.
Есть у застройщиков отдельная головная боль, это интерактивные планы. Особенно паркинг на пару-тройку сотен машиномест.
Такая схема это SVG, набитый элементами векторными под завязку. По размеру он весит всего ничего, но браузер прорисовывает эти полигоны и тратит вычислительные мощности. Здесь компьютер пользователя начинает подтормаживать буквально на наведении: ведёшь курсором, а он думает с задержкой в несколько секунд.

Тут уже ни кэш, ни вес картинок ни при чём, всё упирается в сам объём векторной графики. Помогло упрощение схемы и паркинга. Мы убрали ту детализацию, которую пользователь на таком масштабе всё равно не разглядит, но из-за которой браузер отрисовывал лишние сотни полигонов. Схема парковки, которая откликается мгновенно, на практике полезнее той, что нарисована идеально, но тупит три секунды на наведение.
С визуалом разобрались, дальше пошла серверная часть: как быстро страница вообще собирается и уходит клиенту на устройство.
Начали с кэша средствами самого Django. Уже полегчало — часто запрашиваемые данные сервер перестал пересобирать на каждый заход. Потом перешли на Redis, прописали кэш под все тяжёлые запросы и аккуратно настроили сброс. И тут был тонкий момент: чистить кэш надо так, чтобы не задеть пользовательские сессии, иначе людей начнёт выкидывать из личного кабинета или пользователь может случайно попасть в кабинет другого человека. Пришлось отдельно разбираться, как инвалидировать выборочно.
А потом вылез еще один неприятный баг. Данные о квартирах приходят из 1С при выгрузке, и как-то раз после синхронизации кэш не сбросился как надо. В итоге сайт какое-то время показывал старые цены и остатки, которых уже не было. Вылечили автосбросом кэша сразу после каждой выгрузки, чтобы свежие данные подхватывались без ручного вмешательства.

Самая муторная часть всей истории по ускорению это время ответа сервера до первого байта. PageSpeed ругался на него отдельно, и очевидные ходы тут не сработали ни разу.
Первая ассоциация, что напрашивалась, это подкинуть серверу мощности и все ок. Подняли CPU и RAM в конфигурации. Ноль эффекта. Полезли разбираться и выяснили, что дело вообще не в железе и его хватает с избытком: Docker не раскидывал нагрузку на все ядра. Проверили у себя на локалке: контейнер бэкенда работает на все 100% на одном ядре, а виртуалка при этом забирает от силы шесть-семь процентов ресурсов машины. Мощность есть, а сайт и контейнер докера её не берут. Корень оказался в особенностях многопоточности Python, и гигабайтами памяти это не лечится. Хорошая прививка от иллюзии «купим сервак пожирнее и всё полетит».

Заодно бодались с кэшем статики на nginx. Включить-то включили, но он конфликтовал с файрволом, и настройку откатили. Потом попробовали CDN: трафик через него пошёл, а PageSpeed всё равно ругался на кэш изображений. В конце концов прописали правила кэширования прямо на бакете, и только тогда претензии по статике закончились.
Если отбросить всю техническую мишуру, полезных выводов остаётся немного, зато все прикладное.
Первое. Скорость сайта это не про эстетику, это про деньги. Планировка, которая не открылась вовремя, теряет уже заинтересованного покупателя, а слабый балл PageSpeed роняет позиции в поиске и делает клики в контексте дороже. То есть уходит и тот трафик, за который клиент честно заплатил.
Второе. Плясать надо от замеров, а не от догадок. Мы каждый раз сначала смотрели, на что именно ругается PageSpeed, и только потом брались за дело. Иначе легко угробить неделю команды на то, что в итоге почти не сдвигает метрику.

И главное, в чём мы убедились: быстрый сайт застройщика не собирается одним героическим рывком. Это набор мелочей.
Нарезка картинок под разрешения плюс проставленные width и height.
Ленивая загрузка там, где к месту, и её отключение там, где мешает.
Упрощённые тяжёлые SVG без потери смысла для пользователя.
Серверный кэш с нормальным сбросом после каждой выгрузки из 1С.
Расшитое узкое место с распределением нагрузки на контейнерах.
Поодиночке каждый пункт добавляет чуть-чуть. А в сумме из медленного перегруженного сайта получается тот, где планировка открывается моментально — и человек долистывает до заявки, а не до кнопки закрыть страницу.