[{"data":1,"prerenderedAt":299},["ShallowReactive",2],{"project-ru-commonjs-storefront-library":3,"recommendation-mention-sources":237},{"id":4,"title":5,"body":6,"category":203,"context":204,"cover":205,"coverAlt":206,"demo":207,"description":208,"extension":209,"featured":210,"locale":211,"meta":212,"navigation":213,"order":214,"path":215,"published":213,"repository":207,"results":216,"role":220,"seo":221,"slug":222,"stack":223,"stem":234,"year":235,"__hash__":236},"projects\u002Fru\u002Fprojects\u002Fcommonjs-storefront-library.md","Сопровождение JavaScript-библиотеки, на которой работают витрины inSales",{"type":7,"value":8,"toc":188},"minimark",[9,14,27,30,34,37,41,46,49,53,68,72,129,140,144,151,155,168,172],[10,11,13],"h2",{"id":12},"задача","Задача",[15,16,17,18,22,23,26],"p",{},"CommonJS (в документации ещё Common.js и ",[19,20,21],"code",{},"common.v2.js",") — JavaScript-библиотека витрин inSales. Она загружает данные товаров, переключает варианты, пересчитывает цены, меняет количество в корзине и отправляет формы. Разработчики магазинов подключают её к шаблонам через ",[19,24,25],{},"data-*","-атрибуты и вызывают её публичный API из своего кода. У inSales больше 60 000 магазинов, поэтому ошибка в библиотеке могла сломать выбор товара или корзину сразу на многих сайтах.",[15,28,29],{},"Я взялся за неё вскоре после перехода из технической поддержки во фронтенд в 2021 году. Библиотека была фактически заброшена: работала, но весила много, собиралась устаревшей сборкой, и серьёзно её менять никто не хотел. Никто не знал, какие шаблоны и клиентские доработки от какой её части зависят.",[10,31,33],{"id":32},"моя-роль","Моя роль",[15,35,36],{},"Я стал мейнтейнером библиотеки и оставался им несколько лет. Разбирал архитектуру, переделывал сборку, добавлял компоненты и публичные API, писал документацию для разработчиков, готовил сценарии QA и релизы, чинил ошибки в живых магазинах. Серверные API делали бэкенд-разработчики, состав данных я согласовывал с ними. Со временем коллеги и техподдержка стали приходить ко мне с вопросами о том, как работает библиотека.",[10,38,40],{"id":39},"что-я-сделал","Что я сделал",[42,43,45],"h3",{"id":44},"карта-зависимостей-до-первых-серьёзных-изменений","Карта зависимостей до первых серьёзных изменений",[15,47,48],{},"Сначала нужно было понять код, а не менять его. AI-ассистентов в работе тогда ещё не было, так что я читал код и вручную рисовал карту в Miro: откуда берутся данные товара, когда они попадают в кеш, что запускает рендер, как события корзины приводят к новым запросам и какие модули зависят друг от друга. С этой картой было видно, что затронет правка одного метода за его пределами.",[42,50,52],{"id":51},"сборка-меньше-поведение-то-же","Сборка меньше, поведение то же",[15,54,55,56,59,60,63,64,67],{},"Я перевёл сборку на Webpack 5, а модули — с CommonJS-формата ",[19,57,58],{},"require"," на ES ",[19,61,62],{},"import","\u002F",[19,65,66],{},"export",". Название библиотеки осталось прежним. На ES-модулях сборщик видит, что реально используется: tree shaking выкидывает мёртвый код, а code splitting делит сборку на части. Избыточные подключения Lodash я заменил на нужные модули и убрал неиспользуемые зависимости. Сжатый production-бандл уменьшился с более чем 300 КБ до 168 КБ, несжатый файл — примерно с 900 до 600 КБ. Выбор товара, корзина и формы при этом работали как раньше.",[42,69,71],{"id":70},"публичный-api-на-котором-строят-свои-виджеты","Публичный API, на котором строят свои виджеты",[15,73,74,75,77,78,81,82,81,85,88,89,92,93,98,99,103,104,108,109,113,114,117,118,88,121,124,125,128],{},"Библиотека связывает Liquid-шаблоны, HTML-разметку и данные магазина. Компоненты подключаются через ",[19,76,25],{},"-атрибуты, а ",[19,79,80],{},"Products",", ",[19,83,84],{},"Cart",[19,86,87],{},"ajaxAPI"," и ",[19,90,91],{},"EventBus"," дают разработчикам данные, операции с корзиной и события. Поверх этого я добавил AJAX-загрузку списков товаров, отдельного товара и фильтров каталога с новым товарным кешем (",[94,95,97],"a",{"href":96},"\u002Fru\u002Fwork\u002Fstorefront-product-loading\u002F","отдельный кейс","), ",[94,100,102],{"href":101},"\u002Fru\u002Fwork\u002Fproduct-options\u002F","товарные опции и дополнительные услуги"," в карточке и корзине, ",[94,105,107],{"href":106},"\u002Fru\u002Fwork\u002Fmulti-warehouse-carts\u002F","мультикорзины"," для оптовых магазинов и ",[94,110,112],{"href":111},"\u002Fru\u002Fwork\u002Fform-protection\u002F","невидимую капчу"," для стандартных и кастомных форм. Мелкие доработки приходили из реальных запросов: хук перед сборкой формы обратной связи (январь 2026) и ",[19,115,116],{},"payload"," из кнопки, которая открывает форму (июль 2026). В интеграциях корзины я использовал облегчённые события ",[19,119,120],{},"add_items:insales:cart:light",[19,122,123],{},"update_items:insales:cart:light",". Они срабатывают раньше, но передают позиции корзины без вложенного объекта ",[19,126,127],{},"product",", и обработчики приходилось писать под такой формат.",[15,130,131,136],{},[132,133],"img",{"alt":134,"src":135},"Карточка товара в шаблоне Stories с выбором размера, ценой и счётчиком товара в корзине","\u002Fimages\u002Fwork\u002Fcommonjs-storefront-library\u002Fstories-product-in-cart-counter.webp",[137,138,139],"em",{},"Стандартный шаблон Stories. Кнопки вариантов, цена и счётчик в корзине работают на CommonJS.",[42,141,143],{"id":142},"совместимость-как-правило-релиза","Совместимость как правило релиза",[15,145,146,147,150],{},"Каждая новая версия должна была работать с несколькими поколениями шаблонов и с кодом магазинов, который заранее не увидишь. Я сохранял старые способы подключения компонентов и проверял общий компонент во всех местах витрины, где он встречается. Собирал тестовые версии библиотеки, подключал их к тестовым магазинам, отдавал изменения на ревью и QA и выкатывал по этапам. Для крупных изменений, например выбора провайдера капчи, использовал фича-флаги. Когда после релиза на реальных аккаунтах обнаружился пустой ",[19,148,149],{},"captcha_type",", я нашёл причину, поправил обработку настройки и подготовил повторную выкатку системных форм.",[42,152,154],{"id":153},"документация-и-помощь-коллегам","Документация и помощь коллегам",[15,156,157,158,81,161,164,165,167],{},"Я написал документацию для разработчиков к ",[19,159,160],{},"ui-ajax-products",[19,162,163],{},"ui-ajax-product"," и API для reCAPTCHA и Yandex SmartCaptcha: какую разметку и ",[19,166,25],{},"-атрибуты добавить, какие настройки принимает компонент, как устроены шаблоны отображения, какие события запускают действие и какие сообщают о его завершении. Приводил примеры интеграции. Ещё описал, как подключить к магазину тестовую сборку CommonJS, чтобы проверять изменения до общего обновления. Когда у клиента что-то ломалось, помогал коллегам понять, где причина: в библиотеке, в данных, в ответе сервера или в коде самого магазина.",[10,169,171],{"id":170},"результат","Результат",[173,174,175,179,182,185],"ul",{},[176,177,178],"li",{},"Сжатый production-бандл уменьшился с более чем 300 КБ до 168 КБ, несжатый — примерно с 900 до 600 КБ.",[176,180,181],{},"У библиотеки, которую никто не хотел трогать, появились мейнтейнер и документация к компонентам и публичным API. В 2026 году в неё всё ещё добавлялись новые API.",[176,183,184],{},"На ней построены новые функции витрин: AJAX-загрузка товаров с кешем по дате изменения, товарные опции, мультикорзины и капча в формах.",[176,186,187],{},"Старые шаблоны и клиентские доработки продолжали работать при поэтапных релизах.",{"title":189,"searchDepth":190,"depth":190,"links":191},"",2,[192,193,194,202],{"id":12,"depth":190,"text":13},{"id":32,"depth":190,"text":33},{"id":39,"depth":190,"text":40,"children":195},[196,198,199,200,201],{"id":44,"depth":197,"text":45},3,{"id":51,"depth":197,"text":52},{"id":70,"depth":197,"text":71},{"id":142,"depth":197,"text":143},{"id":153,"depth":197,"text":154},{"id":170,"depth":190,"text":171},"Платформа витрин","inSales","\u002Fimages\u002Fwork\u002Fcommonjs-storefront-library\u002Flibrary-modules-and-templates.svg","Схема библиотеки CommonJS: публичный API и компоненты, связанные со стандартными шаблонами, виджетами, кодом магазинов и документацией",null,"Взял заброшенную библиотеку CommonJS, которая отвечает за карточки товаров, корзину и формы на витринах inSales. Уменьшил сжатый бандл с 300+ до 168 КБ и несколько лет развивал её дальше.","md",false,"ru",{},true,7,"\u002Fru\u002Fprojects\u002Fcommonjs-storefront-library",[217],{"value":218,"label":219},"300+ КБ → 168 КБ","сжатый production-бандл после переделки сборки и зависимостей","Мейнтейнер библиотеки: рефакторинг, сборка, компоненты, публичный API, документация",{"title":5,"description":208},"commonjs-storefront-library",[224,225,226,227,228,229,230,231,232,233],"JavaScript","Web Performance","Webpack","Code Refactoring","AJAX","IndexedDB","Web Caching","Technical Documentation","Debugging","E-Commerce","ru\u002Fprojects\u002Fcommonjs-storefront-library","Октябрь 2021 – сентябрь 2026","hnyoyNHH-_M81bBC3t6_R4WraLO3yYdtPr-8wyUDGqc",[238,249,254,269,279,284,289,294],{"stem":239,"name":240,"date":241,"featured":190,"published":213,"mentions":242},"recommendations\u002Fandrey-stikheev","Andrey Stikheev","2026-09-08",[243,246],{"project":244,"quote":245},"product-image-editor","Among his most notable projects was a sophisticated browser-based image editor built with TypeScript and Fabric.js, now used by thousands of merchants.",{"project":247,"quote":248},"abandoned-carts","He also developed the frontend for a paid abandoned-cart product and contributed to the production migration from Vue 2 to Vue 3.",{"stem":250,"name":251,"date":252,"featured":207,"published":213,"mentions":253},"recommendations\u002Fdaniil-churakov","Daniil Churakov","2026-08-27",[],{"stem":255,"name":256,"date":257,"featured":197,"published":213,"mentions":258},"recommendations\u002Fdmitry-sadovsky","Dmitry Sadovsky","2026-08-22",[259,262,264,267],{"project":260,"quote":261},"visual-storefront","For years he was the driving force behind our visual storefront editor — a large, complex application where merchants build their online stores.",{"project":244,"quote":263},"It became the tool merchants use to design product images right inside the admin panel — the kind of component companies usually buy rather than build.",{"project":265,"quote":266},"image-editor","What impressed me most was the infographic editor he built essentially from scratch: a full canvas-based graphic editor with artboards, shapes, text styling, templates, and undo\u002Fredo history, powered by an editor core he developed himself.",{"project":247,"quote":268},"Our abandoned carts functionality — with multi-channel customer messaging, communication history, and analytics — was largely his work, from UI down to the details of how requests are cancelled and states stay in sync.",{"stem":270,"name":271,"date":272,"featured":273,"published":213,"mentions":274},"recommendations\u002Fegor-fedkin","Egor Fedkin","2026-08-31",1,[275,277],{"project":244,"quote":276},"Today, the tool is actively used by around 3,000 users.",{"project":247,"quote":278},"It has already generated approximately twice the revenue needed to cover its development costs.",{"stem":280,"name":281,"date":282,"featured":207,"published":213,"mentions":283},"recommendations\u002Femmanuel-stephen","Emmanuel Stephen","2026-10-11",[],{"stem":285,"name":286,"date":287,"featured":207,"published":213,"mentions":288},"recommendations\u002Fevgeny-lonshakov","Евгений Лоншаков","2026-09-21",[],{"stem":290,"name":291,"date":292,"featured":207,"published":213,"mentions":293},"recommendations\u002Froman-gorbachev","Роман Горбачев","2026-09-17",[],{"stem":295,"name":296,"date":297,"featured":207,"published":213,"mentions":298},"recommendations\u002Fvladimir-bedarev","Bedarev Vladimir","2026-09-16",[],1793195987320]