[{"data":1,"prerenderedAt":707},["ShallowReactive",2],{"navigation_docs_ru":3,"-ru-reference-performance":167,"-ru-reference-performance-surround":702},[4,61,101,146],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":60},"Руководство","i-lucide-book-open","\u002Fru\u002Fguide","ru\u002F1.guide",[10,15,20,25,30,35,40,45,50,55],{"title":11,"path":12,"stem":13,"icon":14},"Введение","\u002Fru\u002Fguide\u002Fintroduction","ru\u002F1.guide\u002F01.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Установка","\u002Fru\u002Fguide\u002Finstallation","ru\u002F1.guide\u002F02.installation","i-lucide-smartphone",{"title":21,"path":22,"stem":23,"icon":24},"Авторизация","\u002Fru\u002Fguide\u002Fauth","ru\u002F1.guide\u002F03.auth","i-lucide-lock",{"title":26,"path":27,"stem":28,"icon":29},"Кошельки","\u002Fru\u002Fguide\u002Fwallets","ru\u002F1.guide\u002F04.wallets","i-lucide-wallet",{"title":31,"path":32,"stem":33,"icon":34},"Категории","\u002Fru\u002Fguide\u002Fcategories","ru\u002F1.guide\u002F05.categories","i-lucide-tags",{"title":36,"path":37,"stem":38,"icon":39},"Транзакции","\u002Fru\u002Fguide\u002Ftransactions","ru\u002F1.guide\u002F06.transactions","i-lucide-receipt",{"title":41,"path":42,"stem":43,"icon":44},"Переводы","\u002Fru\u002Fguide\u002Ftransfers","ru\u002F1.guide\u002F07.transfers","i-lucide-arrow-left-right",{"title":46,"path":47,"stem":48,"icon":49},"Статистика","\u002Fru\u002Fguide\u002Fstatistics","ru\u002F1.guide\u002F08.statistics","i-lucide-bar-chart-3",{"title":51,"path":52,"stem":53,"icon":54},"Тема","\u002Fru\u002Fguide\u002Ftheme","ru\u002F1.guide\u002F09.theme","i-lucide-palette",{"title":56,"path":57,"stem":58,"icon":59},"Настройки","\u002Fru\u002Fguide\u002Fsettings","ru\u002F1.guide\u002F10.settings","i-lucide-settings",false,{"title":62,"icon":63,"path":64,"stem":65,"children":66,"page":60},"Разработка","i-lucide-code","\u002Fru\u002Fdevelopment","ru\u002F2.development",[67,71,76,81,86,91,96],{"title":16,"path":68,"stem":69,"icon":70},"\u002Fru\u002Fdevelopment\u002Finstallation","ru\u002F2.development\u002F01.installation","i-lucide-download",{"title":72,"path":73,"stem":74,"icon":75},"Граф кодовой базы","\u002Fru\u002Fdevelopment\u002Funderstand-anything","ru\u002F2.development\u002F02.understand-anything","i-lucide-network",{"title":77,"path":78,"stem":79,"icon":80},"Офлайн и PWA","\u002Fru\u002Fdevelopment\u002Foffline","ru\u002F2.development\u002F03.offline","i-lucide-wifi-off",{"title":82,"path":83,"stem":84,"icon":85},"История миграций данных","\u002Fru\u002Fdevelopment\u002Fmigration","ru\u002F2.development\u002F04.migration","i-lucide-database",{"title":87,"path":88,"stem":89,"icon":90},"Деплой","\u002Fru\u002Fdevelopment\u002Fdeployment","ru\u002F2.development\u002F05.deployment","i-lucide-rocket",{"title":92,"path":93,"stem":94,"icon":95},"Тестирование","\u002Fru\u002Fdevelopment\u002Ftesting","ru\u002F2.development\u002F06.testing","i-lucide-flask-conical",{"title":97,"path":98,"stem":99,"icon":100},"Дата-утилиты","\u002Fru\u002Fdevelopment\u002Fdate-utilities","ru\u002F2.development\u002F07.date-utilities","i-lucide-calendar",{"title":102,"icon":103,"path":104,"stem":105,"children":106,"page":60},"Справочник","i-lucide-file-code","\u002Fru\u002Freference","ru\u002F3.reference",[107,112,116,121,126,131,136,141],{"title":108,"path":109,"stem":110,"icon":111},"Архитектура","\u002Fru\u002Freference\u002Farchitecture","ru\u002F3.reference\u002F01.architecture","i-lucide-boxes",{"title":113,"path":114,"stem":115,"icon":44},"Типы транзакций","\u002Fru\u002Freference\u002Ftransaction-types","ru\u002F3.reference\u002F02.transaction-types",{"title":117,"path":118,"stem":119,"icon":120},"Синхронизация","\u002Fru\u002Freference\u002Fsync","ru\u002F3.reference\u002F03.sync","i-lucide-refresh-cw",{"title":122,"path":123,"stem":124,"icon":125},"Офлайн-first","\u002Fru\u002Freference\u002Foffline-first","ru\u002F3.reference\u002F04.offline-first","i-lucide-list-ordered",{"title":127,"path":128,"stem":129,"icon":130},"Тех. решения","\u002Fru\u002Freference\u002Ftech-decisions","ru\u002F3.reference\u002F05.tech-decisions","i-lucide-lightbulb",{"title":132,"path":133,"stem":134,"icon":135},"Валидация","\u002Fru\u002Freference\u002Fvalidation-strategy","ru\u002F3.reference\u002F06.validation-strategy","i-lucide-shield-check",{"title":137,"path":138,"stem":139,"icon":140},"Что изменилось со времён Firebase","\u002Fru\u002Freference\u002Ffirebase-migration","ru\u002F3.reference\u002F07.firebase-migration","i-lucide-hamburger",{"title":142,"path":143,"stem":144,"icon":145},"Производительность","\u002Fru\u002Freference\u002Fperformance","ru\u002F3.reference\u002F08.performance","i-lucide-gauge",{"title":147,"icon":148,"path":149,"stem":150,"children":151,"page":60},"Премиум","i-lucide-star","\u002Fru\u002Fpremium","ru\u002F4.premium",[152,157,162],{"title":153,"path":154,"stem":155,"icon":156},"Обзор","\u002Fru\u002Fpremium\u002Foverview","ru\u002F4.premium\u002F01.overview","i-lucide-layers",{"title":158,"path":159,"stem":160,"icon":161},"Telegram-бот","\u002Fru\u002Fpremium\u002Ftelegram-bot","ru\u002F4.premium\u002F02.telegram-bot","i-lucide-send",{"title":163,"path":164,"stem":165,"icon":166},"AI Chat","\u002Fru\u002Fpremium\u002Fai-chat","ru\u002F4.premium\u002F03.ai-chat","i-lucide-sparkles",{"id":168,"title":142,"body":169,"description":694,"extension":695,"links":696,"meta":697,"navigation":698,"path":143,"seo":699,"stem":144,"__hash__":701},"docs_ru\u002Fru\u002F3.reference\u002F08.performance.md",{"type":170,"value":171,"toc":688},"minimark",[172,181,186,189,233,242,276,280,386,390,393,569,614,618,629,684],[173,174,175,176,180],"p",{},"Что держит холодный старт быстрым и как его измерять. Контрольные цифры ниже сняты на прод-сборке (",[177,178,179],"code",{},"pnpm generate",") с реальным аккаунтом в ~8 000 транзакций, на десктопном железе, с ассетами из service worker - воспринимайте их как относительные, а не абсолютные.",[182,183,185],"h2",{"id":184},"бюджет-холодного-старта","Бюджет холодного старта",[173,187,188],{},"В загрузке доминирует выполнение JS, а не сеть (всё закешировано в SW). Хранилища наполняются двумя путями:",[190,191,192,205],"table",{},[193,194,195],"thead",{},[196,197,198,202],"tr",{},[199,200,201],"th",{},"Путь",[199,203,204],{},"Данные на экране",[206,207,208,221],"tbody",{},[196,209,210,218],{},[211,212,213,214,217],"td",{},"Наполнение из blob-кеша (",[177,215,216],{},"cache:prime",", чтение ~70 мс)",[211,219,220],{},"~280 мс",[196,222,223,230],{},[211,224,225,226,229],{},"Первая эмиссия watch для ",[177,227,228],{},"trns"," из SQLite",[211,231,232],{},"~730 мс",[173,234,235,236,241],{},"Этот разрыв в ~450 мс - причина существования ",[237,238,240],"a",{"href":239},"\u002Fru\u002Freference\u002Farchitecture#cache-first-%D1%85%D0%BE%D0%BB%D0%BE%D0%B4%D0%BD%D1%8B%D0%B9-%D1%81%D1%82%D0%B0%D1%80%D1%82","blob-кеша",": его ценность в ранней отрисовке, а не в пропуске трансформации строк (трансформация 8k строк занимает ~3 мс - стоимость в скане SQLite + передаче из воркера, а не в JS).",[173,243,244,245,249,250,253,254,253,257,253,260,253,263,265,266,268,269,271,272,275],{},"Пять загрузочных подписок ",[246,247,248],"strong",{},"сериализованы"," на единственном worker-подключении PowerSync - их первые эмиссии приходят лесенкой (",[177,251,252],{},"user_settings"," → ",[177,255,256],{},"rates",[177,258,259],{},"categories",[177,261,262],{},"wallets",[177,264,228],{},"), и доминирует скан всей таблицы ",[177,267,228],{},". Слияние четырёх маленьких запросов дало бы мало; оконная выборка ",[177,270,228],{}," по дате отвергнута, потому что итогам кошельков нужна полная история (см. ",[237,273,274],{"href":128},"Технические решения",").",[182,277,279],{"id":278},"бандл-что-и-когда-загружается","Бандл: что и когда загружается",[281,282,283,313,327,341,350,372],"ul",{},[284,285,286,292,293,296,297,300,301,304,305,308,309,312],"li",{},[246,287,288,291],{},[177,289,290],{},"@powersync\u002Fweb"," ленивый."," ",[177,294,295],{},"getPowerSyncDb()"," (",[177,298,299],{},"app\u002Fservices\u002Fpowersync\u002Fdb.ts",") динамически импортирует библиотеку, схему и коннектор при первом использовании, убирая ~230 КБ из входного чанка - страница логина и демо-режим его вообще не парсят. Это охраняют две детали: ",[177,302,303],{},"uploadErrorHandler.ts"," существует, чтобы статический импорт плагина не дотягивался до connector.ts, а ",[177,306,307],{},"uploadReconcile.ts"," сравнивает строки операций вместо импорта enum ",[177,310,311],{},"UpdateType",".",[284,314,315,318,319,322,323,326],{},[246,316,317],{},"swiper ленивый."," Форма транзакции (",[177,320,321],{},"LazyTrnFormBottom"," \u002F ",[177,324,325],{},"LazyTrnFormSidebar"," в дефолтном layout) монтируется после первого открытия; idle-префетч делает это первое открытие мгновенным.",[284,328,329,332,333,336,337,340],{},[246,330,331],{},"echarts монтируется в idle."," Графики спрятаны за ",[177,334,335],{},"useIdleMount()"," с плейсхолдером равной высоты (",[177,338,339],{},"stat\u002Fchart\u002FWrap.vue","), поэтому чанк echarts в 450 КБ никогда не конкурирует с первой отрисовкой.",[284,342,343,292,346,349],{},[246,344,345],{},"Скелетон дашборда.",[177,347,348],{},"StatPageSkeleton"," резервирует форму страницы, пока хранилища гидрируются, поэтому приходящие данные не сдвигают layout.",[284,351,352,355,356,359,360,363,364,367,368,371],{},[246,353,354],{},"Иконки в бандле."," Все статически используемые имена иконок поставляются в клиентском бандле (",[177,357,358],{},"icon.clientBundle.icons"," в ",[177,361,362],{},"nuxt.config.ts",", включая коллекцию ",[177,365,366],{},"hugeicons",") - иконки, загружаемые с ",[177,369,370],{},"api.iconify.design"," в рантайме, появляются после первой отрисовки и сдвигают layout (CLS). Сканер иконок не видит имена внутри динамических тернарников, отсюда явный список. Только иконки пользовательских данных (иконки категорий\u002Fкошельков вне бандла) по-прежнему загружаются в рантайме и кешируются SW (CacheFirst).",[284,373,374,377,378,381,382,385],{},[246,375,376],{},"Прекеш SW сужен."," Из восьми эмитируемых WASM-вариантов wa-sqlite прекешируется только ",[177,379,380],{},"wa-sqlite-async.\u003Chash>.wasm"," (тот, который воркер действительно загружает - cipher-сборкам нужен ",[177,383,384],{},"encryptionKey",", который мы никогда не передаём), что экономит ~12 МБ на каждую установку service worker.",[182,387,389],{"id":388},"инструментирование","Инструментирование",[173,391,392],{},"Метки холодного старта включены всегда (они ничего не стоят). В консоли браузера после перезагрузки:",[394,395,400],"pre",{"className":396,"code":397,"language":398,"meta":399,"style":399},"language-js shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","performance.getEntriesByType('measure')\n  .filter(m => \u002F^(ps:watch|cache:|trns:)\u002F.test(m.name))\n  .map(m => `${m.name}: ${Math.round(m.startTime)}ms +${Math.round(m.duration)}ms`)\n","js","",[177,401,402,433,491],{"__ignoreMap":399},[403,404,407,411,414,418,421,424,428,430],"span",{"class":405,"line":406},"line",1,[403,408,410],{"class":409},"sTEyZ","performance",[403,412,312],{"class":413},"sMK4o",[403,415,417],{"class":416},"s2Zo4","getEntriesByType",[403,419,420],{"class":409},"(",[403,422,423],{"class":413},"'",[403,425,427],{"class":426},"sfazB","measure",[403,429,423],{"class":413},[403,431,432],{"class":409},")\n",[403,434,436,439,442,444,448,452,455,459,461,464,467,470,472,475,478,480,483,486,488],{"class":405,"line":435},2,[403,437,438],{"class":413},"  .",[403,440,441],{"class":416},"filter",[403,443,420],{"class":409},[403,445,447],{"class":446},"sHdIc","m",[403,449,451],{"class":450},"spNyl"," =>",[403,453,454],{"class":413}," \u002F",[403,456,458],{"class":457},"s7zQu","^",[403,460,420],{"class":413},[403,462,463],{"class":426},"ps:watch",[403,465,466],{"class":413},"|",[403,468,469],{"class":426},"cache:",[403,471,466],{"class":413},[403,473,474],{"class":426},"trns:",[403,476,477],{"class":413},")\u002F",[403,479,312],{"class":413},[403,481,482],{"class":416},"test",[403,484,485],{"class":409},"(m",[403,487,312],{"class":413},[403,489,490],{"class":409},"name))\n",[403,492,494,496,499,501,503,505,508,510,512,515,518,521,524,527,529,532,534,536,539,541,544,546,548,550,552,554,556,559,561,564,567],{"class":405,"line":493},3,[403,495,438],{"class":413},[403,497,498],{"class":416},"map",[403,500,420],{"class":409},[403,502,447],{"class":446},[403,504,451],{"class":450},[403,506,507],{"class":413}," `${",[403,509,447],{"class":409},[403,511,312],{"class":413},[403,513,514],{"class":409},"name",[403,516,517],{"class":413},"}",[403,519,520],{"class":426},": ",[403,522,523],{"class":413},"${",[403,525,526],{"class":409},"Math",[403,528,312],{"class":413},[403,530,531],{"class":416},"round",[403,533,485],{"class":409},[403,535,312],{"class":413},[403,537,538],{"class":409},"startTime)",[403,540,517],{"class":413},[403,542,543],{"class":426},"ms +",[403,545,523],{"class":413},[403,547,526],{"class":409},[403,549,312],{"class":413},[403,551,531],{"class":416},[403,553,485],{"class":409},[403,555,312],{"class":413},[403,557,558],{"class":409},"duration)",[403,560,517],{"class":413},[403,562,563],{"class":426},"ms",[403,565,566],{"class":413},"`",[403,568,432],{"class":409},[190,570,571,581],{},[193,572,573],{},[196,574,575,578],{},[199,576,577],{},"Метка",[199,579,580],{},"Значение",[206,582,583,592,602],{},[196,584,585,589],{},[211,586,587],{},[177,588,216],{},[211,590,591],{},"Чтение blob-кеша + наполнение хранилищ (путь отрисовки холодного старта)",[196,593,594,599],{},[211,595,596],{},[177,597,598],{},"ps:watch:\u003Ctable>",[211,600,601],{},"Подписка → первая эмиссия SQLite для каждой загрузочной подписки",[196,603,604,609],{},[211,605,606],{},[177,607,608],{},"trns:first-transform",[211,610,611,612],{},"Стоимость трансформации строка → элемент для первой эмиссии ",[177,613,228],{},[182,615,617],{"id":616},"отвергнутые-подходы","Отвергнутые подходы",[173,619,620,621,624,625,628],{},"Задокументированы, чтобы их не пробовали заново без новых данных (детали в ",[237,622,623],{"href":128},"Технических решениях"," и ",[177,626,627],{},"todo.md","):",[281,630,631,645,654,671],{},[284,632,633,636,637,640,641,644],{},[246,634,635],{},"OPFS VFS"," вместо ",[177,638,639],{},"IDBBatchAtomicVFS"," - холодный старт ограничен ",[177,642,643],{},"db.init"," + сериализацией запросов, а не страничным I\u002FO.",[284,646,647,653],{},[246,648,649,650,652],{},"Оконная подписка ",[177,651,228],{}," по дате"," - ломает итоги кошельков, которым нужна полная история.",[284,655,656,662,663,666,667,670],{},[246,657,658,659],{},"Разделение vendor-чанков через ",[177,660,661],{},"manualChunks"," - фрагментация reka-ui ломает ",[177,664,665],{},"inject","\u002F",[177,668,669],{},"createContext"," в продакшен-сборках.",[284,672,673,679,680,683],{},[246,674,675,676],{},"Хранение items в ",[177,677,678],{},"Map"," - экономит единицы миллисекунд на запись при 8k строк, но ломает всех читателей ",[177,681,682],{},"items"," как обычного объекта.",[685,686,687],"style",{},"html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":399,"searchDepth":435,"depth":435,"links":689},[690,691,692,693],{"id":184,"depth":435,"text":185},{"id":278,"depth":435,"text":279},{"id":388,"depth":435,"text":389},{"id":616,"depth":435,"text":617},"Бюджет холодного старта, ленивые чанки, бандлинг иконок и встроенные метки инструментирования.","md",null,{},{"icon":145},{"title":142,"description":700},"Как Финапка держит холодный старт быстрым - cache-first отрисовка, ленивые чанки PowerSync\u002Fswiper\u002Fecharts, бандлинг иконок, суженный прекеш SW и performance-метки.","SEUIxlLcAVZMXAPJXdfo47x6034K6tm0gh6b1id9aWg",[703,705],{"title":137,"path":138,"stem":139,"description":704,"icon":140,"children":-1},"Что изменилось между v6 (Firebase) и текущим приложением на Supabase + PowerSync - бэкенд, производительность, безопасность, тесты, архитектура.",{"title":153,"path":154,"stem":155,"description":706,"icon":156,"children":-1},"Добавьте Telegram-бота и AI-разбор транзакций в Финапку через Premium Nuxt Layer.",1782114341160]