[{"data":1,"prerenderedAt":1543},["ShallowReactive",2],{"article-alternates":3,"cat-en-tech":4},null,[5],{"_path":6,"_dir":7,"_draft":8,"_partial":8,"_locale":9,"title":10,"description":11,"publishedAt":12,"modifiedAt":12,"category":7,"i18nKey":13,"tags":14,"readingTime":20,"author":21,"body":22,"_type":1537,"_id":1538,"_source":1539,"_file":1540,"_stem":1541,"_extension":1542},"\u002Fen\u002Ftech\u002Fnuxt-3-cloudflare-pages-lcp-optimization","tech",false,"","Nuxt 3 + Cloudflare Pages: From 10s to 2s LCP","Self-hosted fonts, lazy hydration, content-visibility, and edge caching reduced LCP by 80%. Real benchmarks, code examples, and tradeoffs.","2026-05-07","tech-001-2026-05",[15,16,17,18,19],"nuxt3","cloudflare-pages","web-performance","lcp","edge-caching",8,"Roibase",{"type":23,"children":24,"toc":1526},"root",[25,33,40,45,91,96,102,140,543,560,572,593,701,714,800,823,829,850,994,1004,1019,1025,1037,1199,1212,1229,1235,1240,1370,1386,1392,1424,1434,1444,1461,1467,1472,1516,1521],{"type":26,"tag":27,"props":28,"children":29},"element","p",{},[30],{"type":31,"value":32},"text","After Google's Core Web Vitals update, LCP (Largest Contentful Paint) must stay below 2.5 seconds—otherwise both organic rankings and conversion rates suffer. When we migrated an e-commerce site to Nuxt 3 + Cloudflare Pages, initial deployment landed LCP at 10.2 seconds. Combining self-hosted fonts, selective hydration, CSS content-visibility, and edge caching brought it down to 2.1 seconds. Below, we detail step-by-step which change delivered which gain, the tradeoffs, and the code.",{"type":26,"tag":34,"props":35,"children":37},"h2",{"id":36},"diagnosing-the-problem-anatomy-of-10s-lcp",[38],{"type":31,"value":39},"Diagnosing the problem: anatomy of 10s LCP",{"type":26,"tag":27,"props":41,"children":42},{},[43],{"type":31,"value":44},"The initial CrUX report showed median LCP 10.2s and TBT (Total Blocking Time) 2190ms. Chrome DevTools Lighthouse profiling revealed:",{"type":26,"tag":46,"props":47,"children":48},"ul",{},[49,61,71,81],{"type":26,"tag":50,"props":51,"children":52},"li",{},[53,59],{"type":26,"tag":54,"props":55,"children":56},"strong",{},[57],{"type":31,"value":58},"Font loading:",{"type":31,"value":60}," Three font families from Google Fonts CDN, render-blocking",{"type":26,"tag":50,"props":62,"children":63},{},[64,69],{"type":26,"tag":54,"props":65,"children":66},{},[67],{"type":31,"value":68},"JavaScript hydration:",{"type":31,"value":70}," 420kB bundle, entire page hydrated",{"type":26,"tag":50,"props":72,"children":73},{},[74,79],{"type":26,"tag":54,"props":75,"children":76},{},[77],{"type":31,"value":78},"Above-the-fold image:",{"type":31,"value":80}," 1.2MB JPEG, no lazy loading",{"type":26,"tag":50,"props":82,"children":83},{},[84,89],{"type":26,"tag":54,"props":85,"children":86},{},[87],{"type":31,"value":88},"Cloudflare cache:",{"type":31,"value":90}," SSR responses not cached, every request hits origin",{"type":26,"tag":27,"props":92,"children":93},{},[94],{"type":31,"value":95},"Baseline: PageSpeed Insights mobile score 34\u002F100, desktop 62\u002F100. These numbers came after migrating from Shopify Liquid to Nuxt 3—framework change alone doesn't deliver performance gains; architectural optimization is essential.",{"type":26,"tag":34,"props":97,"children":99},{"id":98},"self-hosted-fonts-preload-strategy",[100],{"type":31,"value":101},"Self-hosted fonts + preload strategy",{"type":26,"tag":27,"props":103,"children":104},{},[105,107,114,116,122,124,130,132,138],{"type":31,"value":106},"We downloaded the same font files from Google Fonts into ",{"type":26,"tag":108,"props":109,"children":111},"code",{"className":110},[],[112],{"type":31,"value":113},"public\u002Ffonts\u002F",{"type":31,"value":115}," and moved the ",{"type":26,"tag":108,"props":117,"children":119},{"className":118},[],[120],{"type":31,"value":121},"@font-face",{"type":31,"value":123}," declaration to ",{"type":26,"tag":108,"props":125,"children":127},{"className":126},[],[128],{"type":31,"value":129},"app.vue",{"type":31,"value":131},". The critical difference: using ",{"type":26,"tag":108,"props":133,"children":135},{"className":134},[],[136],{"type":31,"value":137},"\u003Clink rel=\"preload\">",{"type":31,"value":139}," triggers font file requests inside the initial HTML response, before CSS is parsed.",{"type":26,"tag":141,"props":142,"children":146},"pre",{"className":143,"code":144,"language":145,"meta":9,"style":9},"language-vue shiki shiki-themes github-dark","\u003C!-- app.vue -->\n\u003Cscript setup>\nuseHead({\n  link: [\n    {\n      rel: 'preload',\n      href: '\u002Ffonts\u002Finter-var.woff2',\n      as: 'font',\n      type: 'font\u002Fwoff2',\n      crossorigin: 'anonymous'\n    }\n  ]\n})\n\u003C\u002Fscript>\n\n\u003Cstyle>\n@font-face {\n  font-family: 'Inter';\n  src: url('\u002Ffonts\u002Finter-var.woff2') format('woff2');\n  font-display: swap;\n  font-weight: 100 900;\n}\n\u003C\u002Fstyle>\n","vue",[147],{"type":26,"tag":108,"props":148,"children":149},{"__ignoreMap":9},[150,162,189,203,212,221,241,259,276,294,308,317,326,335,352,362,379,393,418,469,491,518,527],{"type":26,"tag":151,"props":152,"children":155},"span",{"class":153,"line":154},"line",1,[156],{"type":26,"tag":151,"props":157,"children":159},{"style":158},"--shiki-default:#6A737D",[160],{"type":31,"value":161},"\u003C!-- app.vue -->\n",{"type":26,"tag":151,"props":163,"children":165},{"class":153,"line":164},2,[166,172,178,184],{"type":26,"tag":151,"props":167,"children":169},{"style":168},"--shiki-default:#E1E4E8",[170],{"type":31,"value":171},"\u003C",{"type":26,"tag":151,"props":173,"children":175},{"style":174},"--shiki-default:#85E89D",[176],{"type":31,"value":177},"script",{"type":26,"tag":151,"props":179,"children":181},{"style":180},"--shiki-default:#B392F0",[182],{"type":31,"value":183}," setup",{"type":26,"tag":151,"props":185,"children":186},{"style":168},[187],{"type":31,"value":188},">\n",{"type":26,"tag":151,"props":190,"children":192},{"class":153,"line":191},3,[193,198],{"type":26,"tag":151,"props":194,"children":195},{"style":180},[196],{"type":31,"value":197},"useHead",{"type":26,"tag":151,"props":199,"children":200},{"style":168},[201],{"type":31,"value":202},"({\n",{"type":26,"tag":151,"props":204,"children":206},{"class":153,"line":205},4,[207],{"type":26,"tag":151,"props":208,"children":209},{"style":168},[210],{"type":31,"value":211},"  link: [\n",{"type":26,"tag":151,"props":213,"children":215},{"class":153,"line":214},5,[216],{"type":26,"tag":151,"props":217,"children":218},{"style":168},[219],{"type":31,"value":220},"    {\n",{"type":26,"tag":151,"props":222,"children":224},{"class":153,"line":223},6,[225,230,236],{"type":26,"tag":151,"props":226,"children":227},{"style":168},[228],{"type":31,"value":229},"      rel: ",{"type":26,"tag":151,"props":231,"children":233},{"style":232},"--shiki-default:#9ECBFF",[234],{"type":31,"value":235},"'preload'",{"type":26,"tag":151,"props":237,"children":238},{"style":168},[239],{"type":31,"value":240},",\n",{"type":26,"tag":151,"props":242,"children":244},{"class":153,"line":243},7,[245,250,255],{"type":26,"tag":151,"props":246,"children":247},{"style":168},[248],{"type":31,"value":249},"      href: ",{"type":26,"tag":151,"props":251,"children":252},{"style":232},[253],{"type":31,"value":254},"'\u002Ffonts\u002Finter-var.woff2'",{"type":26,"tag":151,"props":256,"children":257},{"style":168},[258],{"type":31,"value":240},{"type":26,"tag":151,"props":260,"children":261},{"class":153,"line":20},[262,267,272],{"type":26,"tag":151,"props":263,"children":264},{"style":168},[265],{"type":31,"value":266},"      as: ",{"type":26,"tag":151,"props":268,"children":269},{"style":232},[270],{"type":31,"value":271},"'font'",{"type":26,"tag":151,"props":273,"children":274},{"style":168},[275],{"type":31,"value":240},{"type":26,"tag":151,"props":277,"children":279},{"class":153,"line":278},9,[280,285,290],{"type":26,"tag":151,"props":281,"children":282},{"style":168},[283],{"type":31,"value":284},"      type: ",{"type":26,"tag":151,"props":286,"children":287},{"style":232},[288],{"type":31,"value":289},"'font\u002Fwoff2'",{"type":26,"tag":151,"props":291,"children":292},{"style":168},[293],{"type":31,"value":240},{"type":26,"tag":151,"props":295,"children":297},{"class":153,"line":296},10,[298,303],{"type":26,"tag":151,"props":299,"children":300},{"style":168},[301],{"type":31,"value":302},"      crossorigin: ",{"type":26,"tag":151,"props":304,"children":305},{"style":232},[306],{"type":31,"value":307},"'anonymous'\n",{"type":26,"tag":151,"props":309,"children":311},{"class":153,"line":310},11,[312],{"type":26,"tag":151,"props":313,"children":314},{"style":168},[315],{"type":31,"value":316},"    }\n",{"type":26,"tag":151,"props":318,"children":320},{"class":153,"line":319},12,[321],{"type":26,"tag":151,"props":322,"children":323},{"style":168},[324],{"type":31,"value":325},"  ]\n",{"type":26,"tag":151,"props":327,"children":329},{"class":153,"line":328},13,[330],{"type":26,"tag":151,"props":331,"children":332},{"style":168},[333],{"type":31,"value":334},"})\n",{"type":26,"tag":151,"props":336,"children":338},{"class":153,"line":337},14,[339,344,348],{"type":26,"tag":151,"props":340,"children":341},{"style":168},[342],{"type":31,"value":343},"\u003C\u002F",{"type":26,"tag":151,"props":345,"children":346},{"style":174},[347],{"type":31,"value":177},{"type":26,"tag":151,"props":349,"children":350},{"style":168},[351],{"type":31,"value":188},{"type":26,"tag":151,"props":353,"children":355},{"class":153,"line":354},15,[356],{"type":26,"tag":151,"props":357,"children":359},{"emptyLinePlaceholder":358},true,[360],{"type":31,"value":361},"\n",{"type":26,"tag":151,"props":363,"children":365},{"class":153,"line":364},16,[366,370,375],{"type":26,"tag":151,"props":367,"children":368},{"style":168},[369],{"type":31,"value":171},{"type":26,"tag":151,"props":371,"children":372},{"style":174},[373],{"type":31,"value":374},"style",{"type":26,"tag":151,"props":376,"children":377},{"style":168},[378],{"type":31,"value":188},{"type":26,"tag":151,"props":380,"children":382},{"class":153,"line":381},17,[383,388],{"type":26,"tag":151,"props":384,"children":386},{"style":385},"--shiki-default:#F97583",[387],{"type":31,"value":121},{"type":26,"tag":151,"props":389,"children":390},{"style":168},[391],{"type":31,"value":392}," {\n",{"type":26,"tag":151,"props":394,"children":396},{"class":153,"line":395},18,[397,403,408,413],{"type":26,"tag":151,"props":398,"children":400},{"style":399},"--shiki-default:#79B8FF",[401],{"type":31,"value":402},"  font-family",{"type":26,"tag":151,"props":404,"children":405},{"style":168},[406],{"type":31,"value":407},": ",{"type":26,"tag":151,"props":409,"children":410},{"style":232},[411],{"type":31,"value":412},"'Inter'",{"type":26,"tag":151,"props":414,"children":415},{"style":168},[416],{"type":31,"value":417},";\n",{"type":26,"tag":151,"props":419,"children":421},{"class":153,"line":420},19,[422,427,431,436,441,445,450,455,459,464],{"type":26,"tag":151,"props":423,"children":424},{"style":399},[425],{"type":31,"value":426},"  src",{"type":26,"tag":151,"props":428,"children":429},{"style":168},[430],{"type":31,"value":407},{"type":26,"tag":151,"props":432,"children":433},{"style":399},[434],{"type":31,"value":435},"url",{"type":26,"tag":151,"props":437,"children":438},{"style":168},[439],{"type":31,"value":440},"(",{"type":26,"tag":151,"props":442,"children":443},{"style":232},[444],{"type":31,"value":254},{"type":26,"tag":151,"props":446,"children":447},{"style":168},[448],{"type":31,"value":449},") ",{"type":26,"tag":151,"props":451,"children":452},{"style":399},[453],{"type":31,"value":454},"format",{"type":26,"tag":151,"props":456,"children":457},{"style":168},[458],{"type":31,"value":440},{"type":26,"tag":151,"props":460,"children":461},{"style":232},[462],{"type":31,"value":463},"'woff2'",{"type":26,"tag":151,"props":465,"children":466},{"style":168},[467],{"type":31,"value":468},");\n",{"type":26,"tag":151,"props":470,"children":472},{"class":153,"line":471},20,[473,478,482,487],{"type":26,"tag":151,"props":474,"children":475},{"style":399},[476],{"type":31,"value":477},"  font-display",{"type":26,"tag":151,"props":479,"children":480},{"style":168},[481],{"type":31,"value":407},{"type":26,"tag":151,"props":483,"children":484},{"style":399},[485],{"type":31,"value":486},"swap",{"type":26,"tag":151,"props":488,"children":489},{"style":168},[490],{"type":31,"value":417},{"type":26,"tag":151,"props":492,"children":494},{"class":153,"line":493},21,[495,500,504,509,514],{"type":26,"tag":151,"props":496,"children":497},{"style":399},[498],{"type":31,"value":499},"  font-weight",{"type":26,"tag":151,"props":501,"children":502},{"style":168},[503],{"type":31,"value":407},{"type":26,"tag":151,"props":505,"children":506},{"style":399},[507],{"type":31,"value":508},"100",{"type":26,"tag":151,"props":510,"children":511},{"style":399},[512],{"type":31,"value":513}," 900",{"type":26,"tag":151,"props":515,"children":516},{"style":168},[517],{"type":31,"value":417},{"type":26,"tag":151,"props":519,"children":521},{"class":153,"line":520},22,[522],{"type":26,"tag":151,"props":523,"children":524},{"style":168},[525],{"type":31,"value":526},"}\n",{"type":26,"tag":151,"props":528,"children":530},{"class":153,"line":529},23,[531,535,539],{"type":26,"tag":151,"props":532,"children":533},{"style":168},[534],{"type":31,"value":343},{"type":26,"tag":151,"props":536,"children":537},{"style":174},[538],{"type":31,"value":374},{"type":26,"tag":151,"props":540,"children":541},{"style":168},[542],{"type":31,"value":188},{"type":26,"tag":27,"props":544,"children":545},{},[546,551,553,558],{"type":26,"tag":54,"props":547,"children":548},{},[549],{"type":31,"value":550},"Gain:",{"type":31,"value":552}," LCP 10.2s → 7.8s (2.4s drop). Font loading shifts from render-blocking to non-blocking; FOIT (Flash of Invisible Text) duration 1200ms → 180ms. ",{"type":26,"tag":54,"props":554,"children":555},{},[556],{"type":31,"value":557},"Tradeoff:",{"type":31,"value":559}," font files now live in your own CDN, version management is manual (we solved this with Cloudflare R2 bucket + Cache-Control headers).",{"type":26,"tag":34,"props":561,"children":563},{"id":562},"selective-hydration-content-visibility",[564,566],{"type":31,"value":565},"Selective hydration + ",{"type":26,"tag":108,"props":567,"children":569},{"className":568},[],[570],{"type":31,"value":571},"content-visibility",{"type":26,"tag":27,"props":573,"children":574},{},[575,577,583,585,591],{"type":31,"value":576},"Nuxt 3's default hydrates every component. But components below the fold (footer, comments, related products) don't need to hydrate before the user scrolls. We wrapped below-fold components with ",{"type":26,"tag":108,"props":578,"children":580},{"className":579},[],[581],{"type":31,"value":582},"LazyHydrate",{"type":31,"value":584}," from ",{"type":26,"tag":108,"props":586,"children":588},{"className":587},[],[589],{"type":31,"value":590},"@nuxt\u002Flazy-hydration",{"type":31,"value":592},".",{"type":26,"tag":141,"props":594,"children":596},{"className":143,"code":595,"language":145,"meta":9,"style":9},"\u003Ctemplate>\n  \u003CLazyHydrate when-visible>\n    \u003CProductRecommendations :product-id=\"productId\" \u002F>\n  \u003C\u002FLazyHydrate>\n\u003C\u002Ftemplate>\n",[597],{"type":26,"tag":108,"props":598,"children":599},{"__ignoreMap":9},[600,616,637,670,686],{"type":26,"tag":151,"props":601,"children":602},{"class":153,"line":154},[603,607,612],{"type":26,"tag":151,"props":604,"children":605},{"style":168},[606],{"type":31,"value":171},{"type":26,"tag":151,"props":608,"children":609},{"style":174},[610],{"type":31,"value":611},"template",{"type":26,"tag":151,"props":613,"children":614},{"style":168},[615],{"type":31,"value":188},{"type":26,"tag":151,"props":617,"children":618},{"class":153,"line":164},[619,624,628,633],{"type":26,"tag":151,"props":620,"children":621},{"style":168},[622],{"type":31,"value":623},"  \u003C",{"type":26,"tag":151,"props":625,"children":626},{"style":174},[627],{"type":31,"value":582},{"type":26,"tag":151,"props":629,"children":630},{"style":180},[631],{"type":31,"value":632}," when-visible",{"type":26,"tag":151,"props":634,"children":635},{"style":168},[636],{"type":31,"value":188},{"type":26,"tag":151,"props":638,"children":639},{"class":153,"line":191},[640,645,650,655,660,665],{"type":26,"tag":151,"props":641,"children":642},{"style":168},[643],{"type":31,"value":644},"    \u003C",{"type":26,"tag":151,"props":646,"children":647},{"style":174},[648],{"type":31,"value":649},"ProductRecommendations",{"type":26,"tag":151,"props":651,"children":652},{"style":180},[653],{"type":31,"value":654}," :product-id",{"type":26,"tag":151,"props":656,"children":657},{"style":168},[658],{"type":31,"value":659},"=",{"type":26,"tag":151,"props":661,"children":662},{"style":232},[663],{"type":31,"value":664},"\"productId\"",{"type":26,"tag":151,"props":666,"children":667},{"style":168},[668],{"type":31,"value":669}," \u002F>\n",{"type":26,"tag":151,"props":671,"children":672},{"class":153,"line":205},[673,678,682],{"type":26,"tag":151,"props":674,"children":675},{"style":168},[676],{"type":31,"value":677},"  \u003C\u002F",{"type":26,"tag":151,"props":679,"children":680},{"style":174},[681],{"type":31,"value":582},{"type":26,"tag":151,"props":683,"children":684},{"style":168},[685],{"type":31,"value":188},{"type":26,"tag":151,"props":687,"children":688},{"class":153,"line":214},[689,693,697],{"type":26,"tag":151,"props":690,"children":691},{"style":168},[692],{"type":31,"value":343},{"type":26,"tag":151,"props":694,"children":695},{"style":174},[696],{"type":31,"value":611},{"type":26,"tag":151,"props":698,"children":699},{"style":168},[700],{"type":31,"value":188},{"type":26,"tag":27,"props":702,"children":703},{},[704,706,712],{"type":31,"value":705},"On the CSS side, ",{"type":26,"tag":108,"props":707,"children":709},{"className":708},[],[710],{"type":31,"value":711},"content-visibility: auto",{"type":31,"value":713}," signals the browser: \"skip rendering this element if it's not in the viewport.\"",{"type":26,"tag":141,"props":715,"children":719},{"className":716,"code":717,"language":718,"meta":9,"style":9},"language-css shiki shiki-themes github-dark",".product-recommendations {\n  content-visibility: auto;\n  contain-intrinsic-size: 0 500px; \u002F* placeholder height *\u002F\n}\n","css",[720],{"type":26,"tag":108,"props":721,"children":722},{"__ignoreMap":9},[723,735,756,793],{"type":26,"tag":151,"props":724,"children":725},{"class":153,"line":154},[726,731],{"type":26,"tag":151,"props":727,"children":728},{"style":180},[729],{"type":31,"value":730},".product-recommendations",{"type":26,"tag":151,"props":732,"children":733},{"style":168},[734],{"type":31,"value":392},{"type":26,"tag":151,"props":736,"children":737},{"class":153,"line":164},[738,743,747,752],{"type":26,"tag":151,"props":739,"children":740},{"style":399},[741],{"type":31,"value":742},"  content-visibility",{"type":26,"tag":151,"props":744,"children":745},{"style":168},[746],{"type":31,"value":407},{"type":26,"tag":151,"props":748,"children":749},{"style":399},[750],{"type":31,"value":751},"auto",{"type":26,"tag":151,"props":753,"children":754},{"style":168},[755],{"type":31,"value":417},{"type":26,"tag":151,"props":757,"children":758},{"class":153,"line":191},[759,764,768,773,778,783,788],{"type":26,"tag":151,"props":760,"children":761},{"style":399},[762],{"type":31,"value":763},"  contain-intrinsic-size",{"type":26,"tag":151,"props":765,"children":766},{"style":168},[767],{"type":31,"value":407},{"type":26,"tag":151,"props":769,"children":770},{"style":399},[771],{"type":31,"value":772},"0",{"type":26,"tag":151,"props":774,"children":775},{"style":399},[776],{"type":31,"value":777}," 500",{"type":26,"tag":151,"props":779,"children":780},{"style":385},[781],{"type":31,"value":782},"px",{"type":26,"tag":151,"props":784,"children":785},{"style":168},[786],{"type":31,"value":787},"; ",{"type":26,"tag":151,"props":789,"children":790},{"style":158},[791],{"type":31,"value":792},"\u002F* placeholder height *\u002F\n",{"type":26,"tag":151,"props":794,"children":795},{"class":153,"line":205},[796],{"type":26,"tag":151,"props":797,"children":798},{"style":168},[799],{"type":31,"value":526},{"type":26,"tag":27,"props":801,"children":802},{},[803,807,809,813,815,821],{"type":26,"tag":54,"props":804,"children":805},{},[806],{"type":31,"value":550},{"type":31,"value":808}," TBT 2190ms → 420ms, LCP 7.8s → 4.1s. Initial JS bundle 420kB → 180kB (brotli-compressed). ",{"type":26,"tag":54,"props":810,"children":811},{},[812],{"type":31,"value":557},{"type":31,"value":814}," ",{"type":26,"tag":108,"props":816,"children":818},{"className":817},[],[819],{"type":31,"value":820},"when-visible",{"type":31,"value":822}," uses Intersection Observer; old browsers like IE11 need polyfills (not a concern for us since we target modern browsers).",{"type":26,"tag":34,"props":824,"children":826},{"id":825},"edge-caching-isr-hybrid-approach",[827],{"type":31,"value":828},"Edge caching + ISR hybrid approach",{"type":26,"tag":27,"props":830,"children":831},{},[832,834,840,842,848],{"type":31,"value":833},"Cloudflare Pages caches static assets by default but doesn't cache SSR endpoints (outside ",{"type":26,"tag":108,"props":835,"children":837},{"className":836},[],[838],{"type":31,"value":839},"\u002F_nuxt\u002F...",{"type":31,"value":841},"). We defined route-specific cache rules in ",{"type":26,"tag":108,"props":843,"children":845},{"className":844},[],[846],{"type":31,"value":847},"nuxt.config.ts",{"type":31,"value":849},":",{"type":26,"tag":141,"props":851,"children":855},{"className":852,"code":853,"language":854,"meta":9,"style":9},"language-ts shiki shiki-themes github-dark","\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  routeRules: {\n    '\u002F': { swr: 3600 }, \u002F\u002F homepage 1h stale-while-revalidate\n    '\u002Fproduct\u002F**': { swr: 1800 }, \u002F\u002F product pages 30m\n    '\u002Fcategory\u002F**': { static: true } \u002F\u002F category pages build-time static\n  }\n})\n","ts",[856],{"type":26,"tag":108,"props":857,"children":858},{"__ignoreMap":9},[859,867,889,897,925,951,979,987],{"type":26,"tag":151,"props":860,"children":861},{"class":153,"line":154},[862],{"type":26,"tag":151,"props":863,"children":864},{"style":158},[865],{"type":31,"value":866},"\u002F\u002F nuxt.config.ts\n",{"type":26,"tag":151,"props":868,"children":869},{"class":153,"line":164},[870,875,880,885],{"type":26,"tag":151,"props":871,"children":872},{"style":385},[873],{"type":31,"value":874},"export",{"type":26,"tag":151,"props":876,"children":877},{"style":385},[878],{"type":31,"value":879}," default",{"type":26,"tag":151,"props":881,"children":882},{"style":180},[883],{"type":31,"value":884}," defineNuxtConfig",{"type":26,"tag":151,"props":886,"children":887},{"style":168},[888],{"type":31,"value":202},{"type":26,"tag":151,"props":890,"children":891},{"class":153,"line":191},[892],{"type":26,"tag":151,"props":893,"children":894},{"style":168},[895],{"type":31,"value":896},"  routeRules: {\n",{"type":26,"tag":151,"props":898,"children":899},{"class":153,"line":205},[900,905,910,915,920],{"type":26,"tag":151,"props":901,"children":902},{"style":232},[903],{"type":31,"value":904},"    '\u002F'",{"type":26,"tag":151,"props":906,"children":907},{"style":168},[908],{"type":31,"value":909},": { swr: ",{"type":26,"tag":151,"props":911,"children":912},{"style":399},[913],{"type":31,"value":914},"3600",{"type":26,"tag":151,"props":916,"children":917},{"style":168},[918],{"type":31,"value":919}," }, ",{"type":26,"tag":151,"props":921,"children":922},{"style":158},[923],{"type":31,"value":924},"\u002F\u002F homepage 1h stale-while-revalidate\n",{"type":26,"tag":151,"props":926,"children":927},{"class":153,"line":214},[928,933,937,942,946],{"type":26,"tag":151,"props":929,"children":930},{"style":232},[931],{"type":31,"value":932},"    '\u002Fproduct\u002F**'",{"type":26,"tag":151,"props":934,"children":935},{"style":168},[936],{"type":31,"value":909},{"type":26,"tag":151,"props":938,"children":939},{"style":399},[940],{"type":31,"value":941},"1800",{"type":26,"tag":151,"props":943,"children":944},{"style":168},[945],{"type":31,"value":919},{"type":26,"tag":151,"props":947,"children":948},{"style":158},[949],{"type":31,"value":950},"\u002F\u002F product pages 30m\n",{"type":26,"tag":151,"props":952,"children":953},{"class":153,"line":223},[954,959,964,969,974],{"type":26,"tag":151,"props":955,"children":956},{"style":232},[957],{"type":31,"value":958},"    '\u002Fcategory\u002F**'",{"type":26,"tag":151,"props":960,"children":961},{"style":168},[962],{"type":31,"value":963},": { static: ",{"type":26,"tag":151,"props":965,"children":966},{"style":399},[967],{"type":31,"value":968},"true",{"type":26,"tag":151,"props":970,"children":971},{"style":168},[972],{"type":31,"value":973}," } ",{"type":26,"tag":151,"props":975,"children":976},{"style":158},[977],{"type":31,"value":978},"\u002F\u002F category pages build-time static\n",{"type":26,"tag":151,"props":980,"children":981},{"class":153,"line":243},[982],{"type":26,"tag":151,"props":983,"children":984},{"style":168},[985],{"type":31,"value":986},"  }\n",{"type":26,"tag":151,"props":988,"children":989},{"class":153,"line":20},[990],{"type":26,"tag":151,"props":991,"children":992},{"style":168},[993],{"type":31,"value":334},{"type":26,"tag":27,"props":995,"children":996},{},[997,1002],{"type":26,"tag":54,"props":998,"children":999},{},[1000],{"type":31,"value":1001},"SWR strategy:",{"type":31,"value":1003}," the first request SSR-renders; subsequent requests serve from cache; the background re-renders silently. We used URL + user segment (logged-in\u002Fanonymous) as the cache key in Cloudflare KV.",{"type":26,"tag":27,"props":1005,"children":1006},{},[1007,1011,1013,1017],{"type":26,"tag":54,"props":1008,"children":1009},{},[1010],{"type":31,"value":550},{"type":31,"value":1012}," TTFB (Time to First Byte) 840ms → 120ms, LCP 4.1s → 2.3s. Cache hit rate reached 78% in week one. ",{"type":26,"tag":54,"props":1014,"children":1015},{},[1016],{"type":31,"value":557},{"type":31,"value":1018}," personalization binds to the cache key—user-specific data like cart item count can't be cached; we fetch those client-side.",{"type":26,"tag":34,"props":1020,"children":1022},{"id":1021},"above-the-fold-image-optimization",[1023],{"type":31,"value":1024},"Above-the-fold image optimization",{"type":26,"tag":27,"props":1026,"children":1027},{},[1028,1030,1036],{"type":31,"value":1029},"We converted the 1.2MB JPEG hero image to 180kB WebP and added responsive breakpoints with ",{"type":26,"tag":108,"props":1031,"children":1033},{"className":1032},[],[1034],{"type":31,"value":1035},"\u003Cpicture>",{"type":31,"value":849},{"type":26,"tag":141,"props":1038,"children":1040},{"className":143,"code":1039,"language":145,"meta":9,"style":9},"\u003Cpicture>\n  \u003Csource\n    srcset=\"\u002Fimages\u002Fhero-mobile.webp\"\n    media=\"(max-width: 640px)\"\n    type=\"image\u002Fwebp\"\n  \u002F>\n  \u003Csource\n    srcset=\"\u002Fimages\u002Fhero-desktop.webp\"\n    media=\"(min-width: 641px)\"\n    type=\"image\u002Fwebp\"\n  \u002F>\n  \u003Cimg\n    src=\"\u002Fimages\u002Fhero-desktop.jpg\"\n    alt=\"New season collection\"\n    fetchpriority=\"high\"\n    decoding=\"async\"\n  \u002F>\n\u003C\u002Fpicture>\n",[1041],{"type":26,"tag":108,"props":1042,"children":1043},{"__ignoreMap":9},[1044,1060,1068,1076,1084,1092,1100,1107,1115,1123,1130,1137,1145,1153,1161,1169,1177,1184],{"type":26,"tag":151,"props":1045,"children":1046},{"class":153,"line":154},[1047,1051,1056],{"type":26,"tag":151,"props":1048,"children":1049},{"style":168},[1050],{"type":31,"value":171},{"type":26,"tag":151,"props":1052,"children":1053},{"style":174},[1054],{"type":31,"value":1055},"picture",{"type":26,"tag":151,"props":1057,"children":1058},{"style":168},[1059],{"type":31,"value":188},{"type":26,"tag":151,"props":1061,"children":1062},{"class":153,"line":164},[1063],{"type":26,"tag":151,"props":1064,"children":1065},{"style":168},[1066],{"type":31,"value":1067},"  \u003Csource\n",{"type":26,"tag":151,"props":1069,"children":1070},{"class":153,"line":191},[1071],{"type":26,"tag":151,"props":1072,"children":1073},{"style":168},[1074],{"type":31,"value":1075},"    srcset=\"\u002Fimages\u002Fhero-mobile.webp\"\n",{"type":26,"tag":151,"props":1077,"children":1078},{"class":153,"line":205},[1079],{"type":26,"tag":151,"props":1080,"children":1081},{"style":168},[1082],{"type":31,"value":1083},"    media=\"(max-width: 640px)\"\n",{"type":26,"tag":151,"props":1085,"children":1086},{"class":153,"line":214},[1087],{"type":26,"tag":151,"props":1088,"children":1089},{"style":168},[1090],{"type":31,"value":1091},"    type=\"image\u002Fwebp\"\n",{"type":26,"tag":151,"props":1093,"children":1094},{"class":153,"line":223},[1095],{"type":26,"tag":151,"props":1096,"children":1097},{"style":168},[1098],{"type":31,"value":1099},"  \u002F>\n",{"type":26,"tag":151,"props":1101,"children":1102},{"class":153,"line":243},[1103],{"type":26,"tag":151,"props":1104,"children":1105},{"style":168},[1106],{"type":31,"value":1067},{"type":26,"tag":151,"props":1108,"children":1109},{"class":153,"line":20},[1110],{"type":26,"tag":151,"props":1111,"children":1112},{"style":168},[1113],{"type":31,"value":1114},"    srcset=\"\u002Fimages\u002Fhero-desktop.webp\"\n",{"type":26,"tag":151,"props":1116,"children":1117},{"class":153,"line":278},[1118],{"type":26,"tag":151,"props":1119,"children":1120},{"style":168},[1121],{"type":31,"value":1122},"    media=\"(min-width: 641px)\"\n",{"type":26,"tag":151,"props":1124,"children":1125},{"class":153,"line":296},[1126],{"type":26,"tag":151,"props":1127,"children":1128},{"style":168},[1129],{"type":31,"value":1091},{"type":26,"tag":151,"props":1131,"children":1132},{"class":153,"line":310},[1133],{"type":26,"tag":151,"props":1134,"children":1135},{"style":168},[1136],{"type":31,"value":1099},{"type":26,"tag":151,"props":1138,"children":1139},{"class":153,"line":319},[1140],{"type":26,"tag":151,"props":1141,"children":1142},{"style":168},[1143],{"type":31,"value":1144},"  \u003Cimg\n",{"type":26,"tag":151,"props":1146,"children":1147},{"class":153,"line":328},[1148],{"type":26,"tag":151,"props":1149,"children":1150},{"style":168},[1151],{"type":31,"value":1152},"    src=\"\u002Fimages\u002Fhero-desktop.jpg\"\n",{"type":26,"tag":151,"props":1154,"children":1155},{"class":153,"line":337},[1156],{"type":26,"tag":151,"props":1157,"children":1158},{"style":168},[1159],{"type":31,"value":1160},"    alt=\"New season collection\"\n",{"type":26,"tag":151,"props":1162,"children":1163},{"class":153,"line":354},[1164],{"type":26,"tag":151,"props":1165,"children":1166},{"style":168},[1167],{"type":31,"value":1168},"    fetchpriority=\"high\"\n",{"type":26,"tag":151,"props":1170,"children":1171},{"class":153,"line":364},[1172],{"type":26,"tag":151,"props":1173,"children":1174},{"style":168},[1175],{"type":31,"value":1176},"    decoding=\"async\"\n",{"type":26,"tag":151,"props":1178,"children":1179},{"class":153,"line":381},[1180],{"type":26,"tag":151,"props":1181,"children":1182},{"style":168},[1183],{"type":31,"value":1099},{"type":26,"tag":151,"props":1185,"children":1186},{"class":153,"line":395},[1187,1191,1195],{"type":26,"tag":151,"props":1188,"children":1189},{"style":168},[1190],{"type":31,"value":343},{"type":26,"tag":151,"props":1192,"children":1193},{"style":174},[1194],{"type":31,"value":1055},{"type":26,"tag":151,"props":1196,"children":1197},{"style":168},[1198],{"type":31,"value":188},{"type":26,"tag":27,"props":1200,"children":1201},{},[1202,1204,1210],{"type":31,"value":1203},"The ",{"type":26,"tag":108,"props":1205,"children":1207},{"className":1206},[],[1208],{"type":31,"value":1209},"fetchpriority=\"high\"",{"type":31,"value":1211}," attribute signals to the browser: \"load this image first.\" Cloudflare Image Resizing automatically converts formats at the edge (serving JPEG to browsers without WebP support).",{"type":26,"tag":27,"props":1213,"children":1214},{},[1215,1219,1221,1227],{"type":26,"tag":54,"props":1216,"children":1217},{},[1218],{"type":31,"value":550},{"type":31,"value":1220}," LCP 2.3s → 2.1s, image load time 1200ms → 320ms. CLS (Cumulative Layout Shift) 0.12 → 0.02—we reserved placeholder space with the ",{"type":26,"tag":108,"props":1222,"children":1224},{"className":1223},[],[1225],{"type":31,"value":1226},"aspect-ratio",{"type":31,"value":1228}," CSS property.",{"type":26,"tag":34,"props":1230,"children":1232},{"id":1231},"benchmark-results-real-user-impact",[1233],{"type":31,"value":1234},"Benchmark results + real-user impact",{"type":26,"tag":27,"props":1236,"children":1237},{},[1238],{"type":31,"value":1239},"PageSpeed Insights mobile score 34 → 92, desktop 62 → 98. 28-day CrUX averages:",{"type":26,"tag":1241,"props":1242,"children":1243},"table",{},[1244,1273],{"type":26,"tag":1245,"props":1246,"children":1247},"thead",{},[1248],{"type":26,"tag":1249,"props":1250,"children":1251},"tr",{},[1252,1258,1263,1268],{"type":26,"tag":1253,"props":1254,"children":1255},"th",{},[1256],{"type":31,"value":1257},"Metric",{"type":26,"tag":1253,"props":1259,"children":1260},{},[1261],{"type":31,"value":1262},"Before",{"type":26,"tag":1253,"props":1264,"children":1265},{},[1266],{"type":31,"value":1267},"After",{"type":26,"tag":1253,"props":1269,"children":1270},{},[1271],{"type":31,"value":1272},"Change",{"type":26,"tag":1274,"props":1275,"children":1276},"tbody",{},[1277,1301,1324,1347],{"type":26,"tag":1249,"props":1278,"children":1279},{},[1280,1286,1291,1296],{"type":26,"tag":1281,"props":1282,"children":1283},"td",{},[1284],{"type":31,"value":1285},"LCP",{"type":26,"tag":1281,"props":1287,"children":1288},{},[1289],{"type":31,"value":1290},"10.2s",{"type":26,"tag":1281,"props":1292,"children":1293},{},[1294],{"type":31,"value":1295},"2.1s",{"type":26,"tag":1281,"props":1297,"children":1298},{},[1299],{"type":31,"value":1300},"−79%",{"type":26,"tag":1249,"props":1302,"children":1303},{},[1304,1309,1314,1319],{"type":26,"tag":1281,"props":1305,"children":1306},{},[1307],{"type":31,"value":1308},"TBT",{"type":26,"tag":1281,"props":1310,"children":1311},{},[1312],{"type":31,"value":1313},"2190ms",{"type":26,"tag":1281,"props":1315,"children":1316},{},[1317],{"type":31,"value":1318},"420ms",{"type":26,"tag":1281,"props":1320,"children":1321},{},[1322],{"type":31,"value":1323},"−81%",{"type":26,"tag":1249,"props":1325,"children":1326},{},[1327,1332,1337,1342],{"type":26,"tag":1281,"props":1328,"children":1329},{},[1330],{"type":31,"value":1331},"CLS",{"type":26,"tag":1281,"props":1333,"children":1334},{},[1335],{"type":31,"value":1336},"0.12",{"type":26,"tag":1281,"props":1338,"children":1339},{},[1340],{"type":31,"value":1341},"0.02",{"type":26,"tag":1281,"props":1343,"children":1344},{},[1345],{"type":31,"value":1346},"−83%",{"type":26,"tag":1249,"props":1348,"children":1349},{},[1350,1355,1360,1365],{"type":26,"tag":1281,"props":1351,"children":1352},{},[1353],{"type":31,"value":1354},"TTFB",{"type":26,"tag":1281,"props":1356,"children":1357},{},[1358],{"type":31,"value":1359},"840ms",{"type":26,"tag":1281,"props":1361,"children":1362},{},[1363],{"type":31,"value":1364},"120ms",{"type":26,"tag":1281,"props":1366,"children":1367},{},[1368],{"type":31,"value":1369},"−86%",{"type":26,"tag":27,"props":1371,"children":1372},{},[1373,1375,1384],{"type":31,"value":1374},"Google Analytics checkout funnel: checkout initiation rate 3.2% → 4.8% (+50% relative lift). Bounce rate 68% → 52%. Search Console: organic traffic grew 34% over 2 months (other SEO changes held constant). These numbers align with Roibase's ",{"type":26,"tag":1376,"props":1377,"children":1381},"a",{"href":1378,"rel":1379},"https:\u002F\u002Fwww.roibase.com.tr\u002Fen\u002Fheadless",[1380],"nofollow",[1382],{"type":31,"value":1383},"Headless",{"type":31,"value":1385}," standards—if performance doesn't drive business metrics, the architecture change isn't successful.",{"type":26,"tag":34,"props":1387,"children":1389},{"id":1388},"tradeoffs-and-decision-criteria",[1390],{"type":31,"value":1391},"Tradeoffs and decision criteria",{"type":26,"tag":27,"props":1393,"children":1394},{},[1395,1400,1402,1407,1409,1414,1416,1422],{"type":26,"tag":54,"props":1396,"children":1397},{},[1398],{"type":31,"value":1399},"Developer experience:",{"type":31,"value":1401}," wrapping components in ",{"type":26,"tag":108,"props":1403,"children":1405},{"className":1404},[],[1406],{"type":31,"value":582},{"type":31,"value":1408}," expands the API surface; new developers must learn the difference between ",{"type":26,"tag":108,"props":1410,"children":1412},{"className":1411},[],[1413],{"type":31,"value":820},{"type":31,"value":1415}," and ",{"type":26,"tag":108,"props":1417,"children":1419},{"className":1418},[],[1420],{"type":31,"value":1421},"when-idle",{"type":31,"value":1423},". We addressed this with Storybook documentation + ESLint rules.",{"type":26,"tag":27,"props":1425,"children":1426},{},[1427,1432],{"type":26,"tag":54,"props":1428,"children":1429},{},[1430],{"type":31,"value":1431},"Bundle size vs. runtime cost:",{"type":31,"value":1433}," self-hosted fonts add ~60kB to the initial bundle but eliminate DNS lookup + TLS handshake overhead. This tradeoff pays off on mobile 3G networks and is neutral on fiber.",{"type":26,"tag":27,"props":1435,"children":1436},{},[1437,1442],{"type":26,"tag":54,"props":1438,"children":1439},{},[1440],{"type":31,"value":1441},"Cache invalidation:",{"type":31,"value":1443}," SWR carries stale-data risk. We handle critical data (inventory) with client-side real-time fetches using 30-second polling instead of WebSocket—lower edge function costs.",{"type":26,"tag":27,"props":1445,"children":1446},{},[1447,1452,1453,1459],{"type":26,"tag":54,"props":1448,"children":1449},{},[1450],{"type":31,"value":1451},"Cloudflare vendor lock-in:",{"type":31,"value":814},{"type":26,"tag":108,"props":1454,"children":1456},{"className":1455},[],[1457],{"type":31,"value":1458},"routeRules",{"type":31,"value":1460}," caching is Cloudflare-specific; porting to another platform requires re-implementation. But Vercel and Netlify offer equivalent primitives; migration effort is acceptable.",{"type":26,"tag":34,"props":1462,"children":1464},{"id":1463},"next-steps",[1465],{"type":31,"value":1466},"Next steps",{"type":26,"tag":27,"props":1468,"children":1469},{},[1470],{"type":31,"value":1471},"2.1s LCP is solid, but CrUX P75 (75th percentile) still sits at 3.2s. Our roadmap:",{"type":26,"tag":1473,"props":1474,"children":1475},"ol",{},[1476,1486,1496,1506],{"type":26,"tag":50,"props":1477,"children":1478},{},[1479,1484],{"type":26,"tag":54,"props":1480,"children":1481},{},[1482],{"type":31,"value":1483},"Image CDN + automatic format negotiation:",{"type":31,"value":1485}," Imgix instead of Cloudflare Polish, AVIF support",{"type":26,"tag":50,"props":1487,"children":1488},{},[1489,1494],{"type":26,"tag":54,"props":1490,"children":1491},{},[1492],{"type":31,"value":1493},"Prefetch strategy:",{"type":31,"value":1495}," Intersection Observer to prefetch data for product cards approaching the viewport",{"type":26,"tag":50,"props":1497,"children":1498},{},[1499,1504],{"type":26,"tag":54,"props":1500,"children":1501},{},[1502],{"type":31,"value":1503},"Service Worker + offline-first:",{"type":31,"value":1505}," Workbox for critical asset caching, network-first fallback",{"type":26,"tag":50,"props":1507,"children":1508},{},[1509,1514],{"type":26,"tag":54,"props":1510,"children":1511},{},[1512],{"type":31,"value":1513},"Aggressive bundle splitting:",{"type":31,"value":1515}," Nuxt 3's code splitting with route-based chunking",{"type":26,"tag":27,"props":1517,"children":1518},{},[1519],{"type":31,"value":1520},"Performance optimization is an endless game—every 100ms gain delivers 1–2% conversion lift. Nuxt 3 + Cloudflare Pages balances edge rendering with modern JS framework ergonomics. When choosing a stack, define LCP targets as business requirements, then evaluate architectural options within that constraint.",{"type":26,"tag":374,"props":1522,"children":1523},{},[1524],{"type":31,"value":1525},"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);}",{"title":9,"searchDepth":191,"depth":191,"links":1527},[1528,1529,1530,1532,1533,1534,1535,1536],{"id":36,"depth":164,"text":39},{"id":98,"depth":164,"text":101},{"id":562,"depth":164,"text":1531},"Selective hydration + content-visibility",{"id":825,"depth":164,"text":828},{"id":1021,"depth":164,"text":1024},{"id":1231,"depth":164,"text":1234},{"id":1388,"depth":164,"text":1391},{"id":1463,"depth":164,"text":1466},"markdown","content:en:tech:nuxt-3-cloudflare-pages-lcp-optimization.md","content","en\u002Ftech\u002Fnuxt-3-cloudflare-pages-lcp-optimization.md","en\u002Ftech\u002Fnuxt-3-cloudflare-pages-lcp-optimization","md",1778164175964]