# Сопровождение JavaScript-библиотеки, на которой работают витрины inSales

> Взял заброшенную библиотеку CommonJS, которая отвечает за карточки товаров, корзину и формы на витринах inSales. Уменьшил сжатый бандл с 300+ до 168 КБ и несколько лет развивал её дальше.

- Адрес: https://anu3ev.com/ru/work/commonjs-storefront-library/
- Период: Октябрь 2021 – сентябрь 2026
- Где: inSales
- Роль: Мейнтейнер библиотеки: рефакторинг, сборка, компоненты, публичный API, документация
- Навыки: JavaScript, Web Performance, Webpack, Code Refactoring, AJAX, IndexedDB, Web Caching, Technical Documentation, Debugging, E-Commerce
- Результаты:
  - 300+ КБ → 168 КБ: сжатый production-бандл после переделки сборки и зависимостей

## Задача

CommonJS (в документации ещё Common.js и `common.v2.js`) — JavaScript-библиотека витрин inSales. Она загружает данные товаров, переключает варианты, пересчитывает цены, меняет количество в корзине и отправляет формы. Разработчики магазинов подключают её к шаблонам через `data-*`-атрибуты и вызывают её публичный API из своего кода. У inSales больше 60 000 магазинов, поэтому ошибка в библиотеке могла сломать выбор товара или корзину сразу на многих сайтах.

Я взялся за неё вскоре после перехода из технической поддержки во фронтенд в 2021 году. Библиотека была фактически заброшена: работала, но весила много, собиралась устаревшей сборкой, и серьёзно её менять никто не хотел. Никто не знал, какие шаблоны и клиентские доработки от какой её части зависят.

## Моя роль

Я стал мейнтейнером библиотеки и оставался им несколько лет. Разбирал архитектуру, переделывал сборку, добавлял компоненты и публичные API, писал документацию для разработчиков, готовил сценарии QA и релизы, чинил ошибки в живых магазинах. Серверные API делали бэкенд-разработчики, состав данных я согласовывал с ними. Со временем коллеги и техподдержка стали приходить ко мне с вопросами о том, как работает библиотека.

## Что я сделал

### Карта зависимостей до первых серьёзных изменений

Сначала нужно было понять код, а не менять его. AI-ассистентов в работе тогда ещё не было, так что я читал код и вручную рисовал карту в Miro: откуда берутся данные товара, когда они попадают в кеш, что запускает рендер, как события корзины приводят к новым запросам и какие модули зависят друг от друга. С этой картой было видно, что затронет правка одного метода за его пределами.

### Сборка меньше, поведение то же

Я перевёл сборку на Webpack 5, а модули — с CommonJS-формата `require` на ES `import`/`export`. Название библиотеки осталось прежним. На ES-модулях сборщик видит, что реально используется: tree shaking выкидывает мёртвый код, а code splitting делит сборку на части. Избыточные подключения Lodash я заменил на нужные модули и убрал неиспользуемые зависимости. Сжатый production-бандл уменьшился с более чем 300 КБ до 168 КБ, несжатый файл — примерно с 900 до 600 КБ. Выбор товара, корзина и формы при этом работали как раньше.

### Публичный API, на котором строят свои виджеты

Библиотека связывает Liquid-шаблоны, HTML-разметку и данные магазина. Компоненты подключаются через `data-*`-атрибуты, а `Products`, `Cart`, `ajaxAPI` и `EventBus` дают разработчикам данные, операции с корзиной и события. Поверх этого я добавил AJAX-загрузку списков товаров, отдельного товара и фильтров каталога с новым товарным кешем ([отдельный кейс](https://anu3ev.com/ru/work/storefront-product-loading/)), [товарные опции и дополнительные услуги](https://anu3ev.com/ru/work/product-options/) в карточке и корзине, [мультикорзины](https://anu3ev.com/ru/work/multi-warehouse-carts/) для оптовых магазинов и [невидимую капчу](https://anu3ev.com/ru/work/form-protection/) для стандартных и кастомных форм. Мелкие доработки приходили из реальных запросов: хук перед сборкой формы обратной связи (январь 2026) и `payload` из кнопки, которая открывает форму (июль 2026). В интеграциях корзины я использовал облегчённые события `add_items:insales:cart:light` и `update_items:insales:cart:light`. Они срабатывают раньше, но передают позиции корзины без вложенного объекта `product`, и обработчики приходилось писать под такой формат.

![Карточка товара в шаблоне Stories с выбором размера, ценой и счётчиком товара в корзине](https://anu3ev.com/images/work/commonjs-storefront-library/stories-product-in-cart-counter.webp)
*Стандартный шаблон Stories. Кнопки вариантов, цена и счётчик в корзине работают на CommonJS.*

### Совместимость как правило релиза

Каждая новая версия должна была работать с несколькими поколениями шаблонов и с кодом магазинов, который заранее не увидишь. Я сохранял старые способы подключения компонентов и проверял общий компонент во всех местах витрины, где он встречается. Собирал тестовые версии библиотеки, подключал их к тестовым магазинам, отдавал изменения на ревью и QA и выкатывал по этапам. Для крупных изменений, например выбора провайдера капчи, использовал фича-флаги. Когда после релиза на реальных аккаунтах обнаружился пустой `captcha_type`, я нашёл причину, поправил обработку настройки и подготовил повторную выкатку системных форм.

### Документация и помощь коллегам

Я написал документацию для разработчиков к `ui-ajax-products`, `ui-ajax-product` и API для reCAPTCHA и Yandex SmartCaptcha: какую разметку и `data-*`-атрибуты добавить, какие настройки принимает компонент, как устроены шаблоны отображения, какие события запускают действие и какие сообщают о его завершении. Приводил примеры интеграции. Ещё описал, как подключить к магазину тестовую сборку CommonJS, чтобы проверять изменения до общего обновления. Когда у клиента что-то ломалось, помогал коллегам понять, где причина: в библиотеке, в данных, в ответе сервера или в коде самого магазина.

## Результат

- Сжатый production-бандл уменьшился с более чем 300 КБ до 168 КБ, несжатый — примерно с 900 до 600 КБ.
- У библиотеки, которую никто не хотел трогать, появились мейнтейнер и документация к компонентам и публичным API. В 2026 году в неё всё ещё добавлялись новые API.
- На ней построены новые функции витрин: AJAX-загрузка товаров с кешем по дате изменения, товарные опции, мультикорзины и капча в формах.
- Старые шаблоны и клиентские доработки продолжали работать при поэтапных релизах.
