Избранные проекты
Назад к проектам

Платформа витрин

Быстрая загрузка и кеширование товаров на витринах

Переделал загрузку и кеширование товаров в JavaScript-библиотеке витрин inSales. Запросов за данными товаров стало примерно на 70% меньше, тяжёлые страницы открываются за 2–3 секунды вместо 5+.

  • ≈70% меньше запросов за данными товаров — по сравнению числа запросов до и после изменений
  • 2–3 с загрузка тяжёлых товарных страниц, которые раньше грузились больше 5 с, в характерных замерах
  • 10+ стандартных шаблонов проверено, а также реальные страницы клиентов
Моя роль
Мейнтейнер библиотеки: AJAX-компоненты, клиентский кеш, выкатка и документация
Период
Декабрь 2024 – май 2025
Навыки
  • JavaScript
  • IndexedDB
  • Web Performance
  • AJAX
  • Web Caching
  • Debugging
  • API Integration
  • Technical Documentation
  • Cross-browser Compatibility
  • Liquid
Схема проверки кеша. Liquid передаёт дату изменения товара, библиотека сверяет её с IndexedDB и запрашивает только изменившиеся товары
На этой странице

Задача

Витрины inSales работают на CommonJS — общей JavaScript-библиотеке, которая загружает данные товаров, пересчитывает цены и обслуживает корзину. Владелец магазина может поставить на страницу несколько товарных подборок, и на главной набирается 60–200 товаров. Liquid генерировал эти блоки ещё до отдачи страницы, а потом библиотека в браузере снова запрашивала по ним данные.

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

Моя роль

Я сопровождал библиотеку и отвечал за эту работу на фронтенде: AJAX-компоненты, правила кеша, обработку ошибок, сценарии QA, план выкатки и документацию для разработчиков. Облегчённые ответы API делали бэкенд-разработчики: я описал, какие данные нужны превью, и встроил результат в библиотеку. Изменения проверял на более чем 10 стандартных шаблонах и на реальных страницах клиентов.

Что я сделал

AJAX-компоненты для товаров и фильтров

Товарные блоки больше не нужно было целиком генерировать в Liquid заранее. Я написал ui-ajax-products для списков товаров из категории и слайдеров, ui-ajax-product для загрузки одного товара по ID (например, в модальном окне выбора варианта) и AJAX-загрузку фильтров каталога. Разметку карточки разработчик магазина задаёт шаблонами внутри виджета. После отрисовки компоненты отправляют события вроде init-products:ui-ajax-products, и слайдер запускается только тогда, когда в нём уже есть товары. Цены, варианты и добавление в корзину идут через тот же товарный компонент, что и на остальной витрине, поэтому AJAX-карточки ведут себя как обычные.

Страница ui-ajax-products в документации inSales для разработчиковПубличная документация к ui-ajax-products, которую я написал.

Проверка по дате изменения вместо таймера

По таймеру не понять, изменился товар или нет. Я передал дату изменения каждого товара через Liquid в data-product-updated-at и стал хранить её вместе с записью в IndexedDB в поле originalUpdatedAt. При следующей загрузке страницы библиотека берёт из кеша товары с совпадающей датой и запрашивает только новые и изменившиеся. Товары, которые лежат в корзине, но не выведены на странице, берутся из сохранённых данных, а если записи нет — из products_with_variants.json. Весь видимый список при этом не перезагружается. Кеш живёт в браузере, сервер отдаёт только даты изменения.

Лёгкие превью без потери вариантов

В крупных магазинах встречаются товары с 500–1000 вариантами, и список из 20 таких товаров мог грузиться 20–30 секунд или падать по таймауту. Превью в слайдере все варианты не нужны, поэтому я перевёл превью на облегчённый ответ (without_many_variants), а полные данные оставил там, где покупатель выбирает вариант. Из-за этого появился конфликт в кеше: один товар может одновременно быть в превью, в полном выборе вариантов, в модальном окне и в корзине. Если облегчённый ответ перезапишет полную запись, следующий виджет останется без вариантов. Если брать кеш без проверки, модальному окну не хватит данных. Я добавил правила полноты: каждое место отображения знает, какие данные ему нужны, а недостающие догружаются по требованию.

Ошибки, которые проявлялись только в живых магазинах

На мобильном Safari карточка товара иногда не инициализировалась после «Загрузить ещё» в каталоге. Сначала это выглядело как зависание хранилища в самой карточке. Пошаговое воспроизведение показало, что каждый подгруженный товар запускал свою инициализацию и заново проходил по хранилищу. Я сделал пакетную инициализацию подгруженных товаров. В другом случае один товарный запрос с ответом 555 ронял инициализацию всех товаров, даже успешно загруженных. Я поправил обработку ошибок, и такие товары теперь инициализируются. Ещё я продлил показ прелоадера до конца отрисовки, подготовил изображения под нужные размеры и обсуждал с партнёрами заглушки для картинок, чтобы страница меньше прыгала при загрузке.

Выкатка в два этапа

У магазинов разные поколения шаблонов и свои доработки, поэтому включить новый кеш везде сразу было нельзя. Сначала вышла новая версия библиотеки, которая для разметки без даты изменения сохраняла старую проверку по времени. Потом data-product-updated-at добавили в виджеты. В сценариях QA я описал переходы между страницами, изменение цены в админке, повторное открытие страницы после старого TTL, смешение облегчённых и полных данных, товары только в корзине и товары сразу в нескольких виджетах.

Результат

  • Запросов за данными товаров стало примерно на 70% меньше: так показало сравнение числа запросов до и после изменений.
  • В характерных замерах тяжёлые товарные страницы стали загружаться за 2–3 секунды вместо больше чем 5. Результат зависит от числа виджетов, устройства, сети и состояния кеша.
  • Изменения проверил на 10+ стандартных шаблонах и реальных страницах клиентов, в том числе со 60–200 товарами.
  • Старые шаблоны продолжили работать во время выкатки, а разработчики магазинов получили документацию к новым компонентам.

Про саму библиотеку, её сборку и уменьшение бандла — в отдельном кейсе о CommonJS.

Написать мне

Ищете senior frontend-разработчика?

Готов к удалённой работе и релокации. Напишите мне или запишитесь на звонок.

Написать мне