[{"data":1,"prerenderedAt":67},["ShallowReactive",2],{"blog-ru":3},[4,18,31,43,57],{"slug":5,"title":6,"description":7,"category":8,"date":9,"readingMinutes":10,"cover":11,"coverAlt":12,"tags":13},"vue-3-proxy-deep-comparison","244 650 сравнений: почему после миграции на Vue 3 автокомплит открывался 12 секунд","После перехода на Vue 3 автокомплит с 700 доменными зонами открывался около 12 секунд. Виноват оказался старый квадратичный поиск дублей, который стал дорогим, когда начал читать каждый объект через реактивный Proxy.","Производительность","2026-10-21",6,"\u002Fimages\u002Fblog\u002Fvue-3-proxy-deep-comparison.svg","Схема, на которой 700 элементов дают 244 650 глубоких сравнений через Vue Proxy, и два исправления, которые убрали задержку",[14,15,16,17],"Vue 3","Performance","Reactivity","Migration",{"slug":19,"title":20,"description":21,"category":22,"date":9,"readingMinutes":23,"cover":24,"coverAlt":25,"tags":26},"redesign-recovery-mode","Редизайн убрал сайдбар, а вместе с ним единственный способ починить сломанную страницу","В новом визуальном редакторе управление виджетами переехало в предпросмотр витрины. Если пользовательский код ломает предпросмотр, кнопки пропадают вместе с ним. Как я нашёл эту дыру и какой режим восстановления для неё сделал.","Продуктовый UX",5,"\u002Fimages\u002Fblog\u002Fredesign-recovery-mode.svg","Три схемы: старый сайдбар, редизайн, где сломанный предпросмотр прячет все кнопки виджетов, и режим восстановления со списком виджетов без предпросмотра",[27,28,29,30],"Product UX","Redesign","iframe","Error recovery",{"slug":32,"title":33,"description":34,"category":35,"date":9,"readingMinutes":10,"cover":36,"coverAlt":37,"tags":38},"one-token-two-forms","Один токен капчи, две ждущие формы: что сломала невидимая проверка на целой платформе","Невидимая капча выглядит как один тег script. В формах нескольких поколений она превратилась в ошибки асинхронного состояния и откат в продакшене из-за записи настроек, которой просто не было.","Архитектура","\u002Fimages\u002Fblog\u002Fone-token-two-forms.svg","Схема сравнивает общее событие проверки, которое продолжает не ту ждущую форму, и callback, привязанный к форме, запустившей проверку",[39,40,41,42],"CAPTCHA","Async state","Forms","Rollout",{"slug":44,"title":45,"description":46,"category":47,"date":9,"readingMinutes":48,"cover":49,"coverAlt":50,"tags":51},"monaco-liquid-tokenizer","Учим Monaco читать Liquid-шаблоны: главное — понять, какой язык под курсором","Как собственный токенизатор для HTML с Liquid и вставками JavaScript и CSS научил подсказки следовать за курсором и почему редактор стал версионируемым пакетом с API из трёх функций.","Браузерные редакторы",7,"\u002Fimages\u002Fblog\u002Fmonaco-liquid-tokenizer.svg","Схема одного шаблона витрины, разбитого на области HTML, Liquid, JSON и CSS; редактор спрашивает у модели, какой язык под курсором",[52,53,54,55,56],"Monaco","Liquid","Tokenizer","Web workers","Packaging",{"slug":58,"title":59,"description":60,"category":8,"date":9,"readingMinutes":10,"cover":61,"coverAlt":62,"tags":63},"cache-by-change-not-timer","Как я заменил таймер кеша вопросом «изменился ли товар?»","Библиотека витрин хранила данные товаров фиксированное время, поэтому страницы то показывали устаревшие данные, то заново запрашивали товары, которые не менялись. Проверка даты изменения каждого товара сократила число запросов примерно на 70%.","\u002Fimages\u002Fblog\u002Fcache-by-change-not-timer.svg","Таблица решений, в которой срок жизни кеша сравнивается с проверкой даты изменения каждого товара",[64,65,66,53,15],"Caching","IndexedDB","Storefront",1793195986944]