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