[{"data":1,"prerenderedAt":1534},["ShallowReactive",2],{"article-alternates":3,"article-\u002Fes\u002Ftech\u002Fnuxt3-cloudflare-pages-lcp-optimizacion":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":8,"_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":1528,"_id":1529,"_source":1530,"_file":1531,"_stem":1532,"_extension":1533},"tech",false,"","Nuxt 3 + Cloudflare Pages: de 10s LCP a 2s","Fonts auto-hospedadas, lazy hydration, content-visibility y edge caching redujeron LCP 80%. Benchmark real, código y trade-offs incluidos.","2026-05-07",[21,22,23,24,25],"nuxt3","cloudflare-pages","web-performance","lcp","edge-caching",8,"Roibase",{"type":29,"children":30,"toc":1517},"root",[31,39,46,51,97,102,108,146,549,559,571,592,700,713,799,816,822,851,995,1008,1017,1023,1036,1198,1211,1227,1233,1238,1368,1384,1390,1415,1425,1442,1452,1458,1463,1507,1512],{"type":32,"tag":33,"props":34,"children":35},"element","p",{},[36],{"type":37,"value":38},"text","Tras la actualización de Core Web Vitals de Google, LCP (Largest Contentful Paint) debe estar por debajo de 2.5 segundos, de lo contrario tanto el ranking orgánico como la tasa de conversión caen. Cuando migramos un sitio de e-commerce a la stack Nuxt 3 + Cloudflare Pages, el LCP inicial fue de 10.2 segundos post-deploy. Usando una combinación de estrategia de fuentes auto-hospedadas, selective hydration, CSS content-visibility y edge caching, lo redujimos a 2.1 segundos. A continuación detallamos qué cambio aportó qué ganancia, los trade-offs y el código.",{"type":32,"tag":40,"props":41,"children":43},"h2",{"id":42},"diagnosticar-el-problema-anatomía-del-lcp-de-10s",[44],{"type":37,"value":45},"Diagnosticar el problema: anatomía del LCP de 10s",{"type":32,"tag":33,"props":47,"children":48},{},[49],{"type":37,"value":50},"El reporte inicial de CrUX mostró LCP mediano de 10.2s y TBT (Total Blocking Time) de 2190ms. El análisis de profiling de Chrome DevTools Lighthouse reveló:",{"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},"Carga de fuentes:",{"type":37,"value":66}," 3 familias de fuentes desde CDN de Google Fonts, 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},"Hydration de JavaScript:",{"type":37,"value":76}," bundle de 420kB, página completa siendo hidratada",{"type":32,"tag":56,"props":78,"children":79},{},[80,85],{"type":32,"tag":60,"props":81,"children":82},{},[83],{"type":37,"value":84},"Imagen above-the-fold:",{"type":37,"value":86}," JPEG de 1.2MB, sin lazy load",{"type":32,"tag":56,"props":88,"children":89},{},[90,95],{"type":32,"tag":60,"props":91,"children":92},{},[93],{"type":37,"value":94},"Caché de Cloudflare:",{"type":37,"value":96}," respuesta SSR no cacheada, cada request llega al origen",{"type":32,"tag":33,"props":98,"children":99},{},[100],{"type":37,"value":101},"Medición inicial: PageSpeed Insights móvil 34\u002F100, desktop 62\u002F100. Estas métricas son posteriores a migración desde Shopify Liquid a Nuxt 3 — el cambio de framework por sí solo no genera ganancia de performance, requiere optimización arquitectónica.",{"type":32,"tag":40,"props":103,"children":105},{"id":104},"estrategia-de-fuentes-auto-hospedadas-preload",[106],{"type":37,"value":107},"Estrategia de fuentes auto-hospedadas + preload",{"type":32,"tag":33,"props":109,"children":110},{},[111,113,120,122,128,130,136,138,144],{"type":37,"value":112},"Descargamos los mismos archivos de fuente desde Google Fonts al directorio ",{"type":32,"tag":114,"props":115,"children":117},"code",{"className":116},[],[118],{"type":37,"value":119},"public\u002Ffonts\u002F",{"type":37,"value":121}," y movimos la definición ",{"type":32,"tag":114,"props":123,"children":125},{"className":124},[],[126],{"type":37,"value":127},"@font-face",{"type":37,"value":129}," a ",{"type":32,"tag":114,"props":131,"children":133},{"className":132},[],[134],{"type":37,"value":135},"app.vue",{"type":37,"value":137},". La diferencia crítica: usamos ",{"type":32,"tag":114,"props":139,"children":141},{"className":140},[],[142],{"type":37,"value":143},"\u003Clink rel=\"preload\">",{"type":37,"value":145}," para iniciar la solicitud de fuentes dentro de la respuesta HTML inicial, antes de que se analice el CSS.",{"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],{"type":32,"tag":60,"props":553,"children":554},{},[555],{"type":37,"value":556},"Ganancia:",{"type":37,"value":558}," LCP 10.2s → 7.8s (caída de 2.4s). Carga de fuentes dejó de ser render-blocking, FOIT (Flash of Invisible Text) redujo de 1200ms a 180ms. Trade-off: los archivos de fuente ahora están en nuestro propio CDN, requiere gestión manual de versiones (lo resolvimos con bucket de Cloudflare R2 + headers Cache-Control).",{"type":32,"tag":40,"props":560,"children":562},{"id":561},"selective-hydration-content-visibility",[563,565],{"type":37,"value":564},"Selective hydration + ",{"type":32,"tag":114,"props":566,"children":568},{"className":567},[],[569],{"type":37,"value":570},"content-visibility",{"type":32,"tag":33,"props":572,"children":573},{},[574,576,582,584,590],{"type":37,"value":575},"El comportamiento predeterminado de Nuxt 3 es hidratar todos los componentes. Pero componentes no presentes en above-the-fold (footer, sección de comentarios, productos relacionados) no necesitan hidratación antes de que el usuario haga scroll. Envolvimos estos componentes en ",{"type":32,"tag":114,"props":577,"children":579},{"className":578},[],[580],{"type":37,"value":581},"LazyHydrate",{"type":37,"value":583}," usando el módulo ",{"type":32,"tag":114,"props":585,"children":587},{"className":586},[],[588],{"type":37,"value":589},"@nuxt\u002Flazy-hydration",{"type":37,"value":591},".",{"type":32,"tag":147,"props":593,"children":595},{"className":149,"code":594,"language":151,"meta":16,"style":16},"\u003Ctemplate>\n  \u003CLazyHydrate when-visible>\n    \u003CProductRecommendations :product-id=\"productId\" \u002F>\n  \u003C\u002FLazyHydrate>\n\u003C\u002Ftemplate>\n",[596],{"type":32,"tag":114,"props":597,"children":598},{"__ignoreMap":16},[599,615,636,669,685],{"type":32,"tag":157,"props":600,"children":601},{"class":159,"line":160},[602,606,611],{"type":32,"tag":157,"props":603,"children":604},{"style":174},[605],{"type":37,"value":177},{"type":32,"tag":157,"props":607,"children":608},{"style":180},[609],{"type":37,"value":610},"template",{"type":32,"tag":157,"props":612,"children":613},{"style":174},[614],{"type":37,"value":194},{"type":32,"tag":157,"props":616,"children":617},{"class":159,"line":170},[618,623,627,632],{"type":32,"tag":157,"props":619,"children":620},{"style":174},[621],{"type":37,"value":622},"  \u003C",{"type":32,"tag":157,"props":624,"children":625},{"style":180},[626],{"type":37,"value":581},{"type":32,"tag":157,"props":628,"children":629},{"style":186},[630],{"type":37,"value":631}," when-visible",{"type":32,"tag":157,"props":633,"children":634},{"style":174},[635],{"type":37,"value":194},{"type":32,"tag":157,"props":637,"children":638},{"class":159,"line":197},[639,644,649,654,659,664],{"type":32,"tag":157,"props":640,"children":641},{"style":174},[642],{"type":37,"value":643},"    \u003C",{"type":32,"tag":157,"props":645,"children":646},{"style":180},[647],{"type":37,"value":648},"ProductRecommendations",{"type":32,"tag":157,"props":650,"children":651},{"style":186},[652],{"type":37,"value":653}," :product-id",{"type":32,"tag":157,"props":655,"children":656},{"style":174},[657],{"type":37,"value":658},"=",{"type":32,"tag":157,"props":660,"children":661},{"style":238},[662],{"type":37,"value":663},"\"productId\"",{"type":32,"tag":157,"props":665,"children":666},{"style":174},[667],{"type":37,"value":668}," \u002F>\n",{"type":32,"tag":157,"props":670,"children":671},{"class":159,"line":211},[672,677,681],{"type":32,"tag":157,"props":673,"children":674},{"style":174},[675],{"type":37,"value":676},"  \u003C\u002F",{"type":32,"tag":157,"props":678,"children":679},{"style":180},[680],{"type":37,"value":581},{"type":32,"tag":157,"props":682,"children":683},{"style":174},[684],{"type":37,"value":194},{"type":32,"tag":157,"props":686,"children":687},{"class":159,"line":220},[688,692,696],{"type":32,"tag":157,"props":689,"children":690},{"style":174},[691],{"type":37,"value":349},{"type":32,"tag":157,"props":693,"children":694},{"style":180},[695],{"type":37,"value":610},{"type":32,"tag":157,"props":697,"children":698},{"style":174},[699],{"type":37,"value":194},{"type":32,"tag":33,"props":701,"children":702},{},[703,705,711],{"type":37,"value":704},"En CSS, aplicamos ",{"type":32,"tag":114,"props":706,"children":708},{"className":707},[],[709],{"type":37,"value":710},"content-visibility: auto",{"type":37,"value":712}," para indicar al navegador \"si este elemento no está en viewport, no hagas cálculos de renderizado\":",{"type":32,"tag":147,"props":714,"children":718},{"className":715,"code":716,"language":717,"meta":16,"style":16},"language-css shiki shiki-themes github-dark",".product-recommendations {\n  content-visibility: auto;\n  contain-intrinsic-size: 0 500px; \u002F* altura placeholder *\u002F\n}\n","css",[719],{"type":32,"tag":114,"props":720,"children":721},{"__ignoreMap":16},[722,734,755,792],{"type":32,"tag":157,"props":723,"children":724},{"class":159,"line":160},[725,730],{"type":32,"tag":157,"props":726,"children":727},{"style":186},[728],{"type":37,"value":729},".product-recommendations",{"type":32,"tag":157,"props":731,"children":732},{"style":174},[733],{"type":37,"value":398},{"type":32,"tag":157,"props":735,"children":736},{"class":159,"line":170},[737,742,746,751],{"type":32,"tag":157,"props":738,"children":739},{"style":405},[740],{"type":37,"value":741},"  content-visibility",{"type":32,"tag":157,"props":743,"children":744},{"style":174},[745],{"type":37,"value":413},{"type":32,"tag":157,"props":747,"children":748},{"style":405},[749],{"type":37,"value":750},"auto",{"type":32,"tag":157,"props":752,"children":753},{"style":174},[754],{"type":37,"value":423},{"type":32,"tag":157,"props":756,"children":757},{"class":159,"line":197},[758,763,767,772,777,782,787],{"type":32,"tag":157,"props":759,"children":760},{"style":405},[761],{"type":37,"value":762},"  contain-intrinsic-size",{"type":32,"tag":157,"props":764,"children":765},{"style":174},[766],{"type":37,"value":413},{"type":32,"tag":157,"props":768,"children":769},{"style":405},[770],{"type":37,"value":771},"0",{"type":32,"tag":157,"props":773,"children":774},{"style":405},[775],{"type":37,"value":776}," 500",{"type":32,"tag":157,"props":778,"children":779},{"style":391},[780],{"type":37,"value":781},"px",{"type":32,"tag":157,"props":783,"children":784},{"style":174},[785],{"type":37,"value":786},"; ",{"type":32,"tag":157,"props":788,"children":789},{"style":164},[790],{"type":37,"value":791},"\u002F* altura placeholder *\u002F\n",{"type":32,"tag":157,"props":793,"children":794},{"class":159,"line":211},[795],{"type":32,"tag":157,"props":796,"children":797},{"style":174},[798],{"type":37,"value":532},{"type":32,"tag":33,"props":800,"children":801},{},[802,806,808,814],{"type":32,"tag":60,"props":803,"children":804},{},[805],{"type":37,"value":556},{"type":37,"value":807}," TBT 2190ms → 420ms, LCP 7.8s → 4.1s. Bundle de JS inicial cargado: 420kB → 180kB (comprimido con brotli). Trade-off: ",{"type":32,"tag":114,"props":809,"children":811},{"className":810},[],[812],{"type":37,"value":813},"when-visible",{"type":37,"value":815}," usa Intersection Observer, requiere polyfill en navegadores antiguos como IE11 (no fue problema en nuestro caso con browser moderno como target).",{"type":32,"tag":40,"props":817,"children":819},{"id":818},"edge-caching-enfoque-isr-híbrido",[820],{"type":37,"value":821},"Edge caching + enfoque ISR híbrido",{"type":32,"tag":33,"props":823,"children":824},{},[825,827,833,835,841,843,849],{"type":37,"value":826},"Cloudflare Pages cachea archivos estáticos por defecto, pero los endpoints SSR (",{"type":32,"tag":114,"props":828,"children":830},{"className":829},[],[831],{"type":37,"value":832},"\u002F_nuxt\u002F...",{"type":37,"value":834}," excluido) no se cachean. En ",{"type":32,"tag":114,"props":836,"children":838},{"className":837},[],[839],{"type":37,"value":840},"nuxt.config.ts",{"type":37,"value":842}," definimos ",{"type":32,"tag":114,"props":844,"children":846},{"className":845},[],[847],{"type":37,"value":848},"routeRules",{"type":37,"value":850}," para especificar qué paths se cachean y por cuánto tiempo:",{"type":32,"tag":147,"props":852,"children":856},{"className":853,"code":854,"language":855,"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    '\u002Fproducto\u002F**': { swr: 1800 }, \u002F\u002F product pages 30m\n    '\u002Fcategoria\u002F**': { static: true } \u002F\u002F category pages static en build\n  }\n})\n","ts",[857],{"type":32,"tag":114,"props":858,"children":859},{"__ignoreMap":16},[860,868,890,898,926,952,980,988],{"type":32,"tag":157,"props":861,"children":862},{"class":159,"line":160},[863],{"type":32,"tag":157,"props":864,"children":865},{"style":164},[866],{"type":37,"value":867},"\u002F\u002F nuxt.config.ts\n",{"type":32,"tag":157,"props":869,"children":870},{"class":159,"line":170},[871,876,881,886],{"type":32,"tag":157,"props":872,"children":873},{"style":391},[874],{"type":37,"value":875},"export",{"type":32,"tag":157,"props":877,"children":878},{"style":391},[879],{"type":37,"value":880}," default",{"type":32,"tag":157,"props":882,"children":883},{"style":186},[884],{"type":37,"value":885}," defineNuxtConfig",{"type":32,"tag":157,"props":887,"children":888},{"style":174},[889],{"type":37,"value":208},{"type":32,"tag":157,"props":891,"children":892},{"class":159,"line":197},[893],{"type":32,"tag":157,"props":894,"children":895},{"style":174},[896],{"type":37,"value":897},"  routeRules: {\n",{"type":32,"tag":157,"props":899,"children":900},{"class":159,"line":211},[901,906,911,916,921],{"type":32,"tag":157,"props":902,"children":903},{"style":238},[904],{"type":37,"value":905},"    '\u002F'",{"type":32,"tag":157,"props":907,"children":908},{"style":174},[909],{"type":37,"value":910},": { swr: ",{"type":32,"tag":157,"props":912,"children":913},{"style":405},[914],{"type":37,"value":915},"3600",{"type":32,"tag":157,"props":917,"children":918},{"style":174},[919],{"type":37,"value":920}," }, ",{"type":32,"tag":157,"props":922,"children":923},{"style":164},[924],{"type":37,"value":925},"\u002F\u002F homepage 1h stale-while-revalidate\n",{"type":32,"tag":157,"props":927,"children":928},{"class":159,"line":220},[929,934,938,943,947],{"type":32,"tag":157,"props":930,"children":931},{"style":238},[932],{"type":37,"value":933},"    '\u002Fproducto\u002F**'",{"type":32,"tag":157,"props":935,"children":936},{"style":174},[937],{"type":37,"value":910},{"type":32,"tag":157,"props":939,"children":940},{"style":405},[941],{"type":37,"value":942},"1800",{"type":32,"tag":157,"props":944,"children":945},{"style":174},[946],{"type":37,"value":920},{"type":32,"tag":157,"props":948,"children":949},{"style":164},[950],{"type":37,"value":951},"\u002F\u002F product pages 30m\n",{"type":32,"tag":157,"props":953,"children":954},{"class":159,"line":229},[955,960,965,970,975],{"type":32,"tag":157,"props":956,"children":957},{"style":238},[958],{"type":37,"value":959},"    '\u002Fcategoria\u002F**'",{"type":32,"tag":157,"props":961,"children":962},{"style":174},[963],{"type":37,"value":964},": { static: ",{"type":32,"tag":157,"props":966,"children":967},{"style":405},[968],{"type":37,"value":969},"true",{"type":32,"tag":157,"props":971,"children":972},{"style":174},[973],{"type":37,"value":974}," } ",{"type":32,"tag":157,"props":976,"children":977},{"style":164},[978],{"type":37,"value":979},"\u002F\u002F category pages static en build\n",{"type":32,"tag":157,"props":981,"children":982},{"class":159,"line":249},[983],{"type":32,"tag":157,"props":984,"children":985},{"style":174},[986],{"type":37,"value":987},"  }\n",{"type":32,"tag":157,"props":989,"children":990},{"class":159,"line":26},[991],{"type":32,"tag":157,"props":992,"children":993},{"style":174},[994],{"type":37,"value":340},{"type":32,"tag":33,"props":996,"children":997},{},[998,1000,1006],{"type":37,"value":999},"La estrategia ",{"type":32,"tag":114,"props":1001,"children":1003},{"className":1002},[],[1004],{"type":37,"value":1005},"swr",{"type":37,"value":1007}," (stale-while-revalidate): el primer request renderiza SSR, los siguientes requests vienen del caché, y en background se re-renderiza. Usamos Cloudflare KV store con URL + segmento de usuario (logged-in\u002Fanónimo) como cache key.",{"type":32,"tag":33,"props":1009,"children":1010},{},[1011,1015],{"type":32,"tag":60,"props":1012,"children":1013},{},[1014],{"type":37,"value":556},{"type":37,"value":1016}," TTFB (Time to First Byte) 840ms → 120ms, LCP 4.1s → 2.3s. Cache hit rate alcanzó 78% en la primera semana. Trade-off: la personalización depende de la cache key; datos específicos del usuario como cantidad de items en carrito no pueden cachearse, se obtienen con fetch client-side.",{"type":32,"tag":40,"props":1018,"children":1020},{"id":1019},"optimización-de-imagen-above-the-fold",[1021],{"type":37,"value":1022},"Optimización de imagen above-the-fold",{"type":32,"tag":33,"props":1024,"children":1025},{},[1026,1028,1034],{"type":37,"value":1027},"Convertimos la imagen hero de JPEG 1.2MB a WebP 180kB e incluimos breakpoints responsivos con elemento ",{"type":32,"tag":114,"props":1029,"children":1031},{"className":1030},[],[1032],{"type":37,"value":1033},"\u003Cpicture>",{"type":37,"value":1035},":",{"type":32,"tag":147,"props":1037,"children":1039},{"className":149,"code":1038,"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=\"Nueva colección de temporada\"\n    fetchpriority=\"high\"\n    decoding=\"async\"\n  \u002F>\n\u003C\u002Fpicture>\n",[1040],{"type":32,"tag":114,"props":1041,"children":1042},{"__ignoreMap":16},[1043,1059,1067,1075,1083,1091,1099,1106,1114,1122,1129,1136,1144,1152,1160,1168,1176,1183],{"type":32,"tag":157,"props":1044,"children":1045},{"class":159,"line":160},[1046,1050,1055],{"type":32,"tag":157,"props":1047,"children":1048},{"style":174},[1049],{"type":37,"value":177},{"type":32,"tag":157,"props":1051,"children":1052},{"style":180},[1053],{"type":37,"value":1054},"picture",{"type":32,"tag":157,"props":1056,"children":1057},{"style":174},[1058],{"type":37,"value":194},{"type":32,"tag":157,"props":1060,"children":1061},{"class":159,"line":170},[1062],{"type":32,"tag":157,"props":1063,"children":1064},{"style":174},[1065],{"type":37,"value":1066},"  \u003Csource\n",{"type":32,"tag":157,"props":1068,"children":1069},{"class":159,"line":197},[1070],{"type":32,"tag":157,"props":1071,"children":1072},{"style":174},[1073],{"type":37,"value":1074},"    srcset=\"\u002Fimages\u002Fhero-mobile.webp\"\n",{"type":32,"tag":157,"props":1076,"children":1077},{"class":159,"line":211},[1078],{"type":32,"tag":157,"props":1079,"children":1080},{"style":174},[1081],{"type":37,"value":1082},"    media=\"(max-width: 640px)\"\n",{"type":32,"tag":157,"props":1084,"children":1085},{"class":159,"line":220},[1086],{"type":32,"tag":157,"props":1087,"children":1088},{"style":174},[1089],{"type":37,"value":1090},"    type=\"image\u002Fwebp\"\n",{"type":32,"tag":157,"props":1092,"children":1093},{"class":159,"line":229},[1094],{"type":32,"tag":157,"props":1095,"children":1096},{"style":174},[1097],{"type":37,"value":1098},"  \u002F>\n",{"type":32,"tag":157,"props":1100,"children":1101},{"class":159,"line":249},[1102],{"type":32,"tag":157,"props":1103,"children":1104},{"style":174},[1105],{"type":37,"value":1066},{"type":32,"tag":157,"props":1107,"children":1108},{"class":159,"line":26},[1109],{"type":32,"tag":157,"props":1110,"children":1111},{"style":174},[1112],{"type":37,"value":1113},"    srcset=\"\u002Fimages\u002Fhero-desktop.webp\"\n",{"type":32,"tag":157,"props":1115,"children":1116},{"class":159,"line":284},[1117],{"type":32,"tag":157,"props":1118,"children":1119},{"style":174},[1120],{"type":37,"value":1121},"    media=\"(min-width: 641px)\"\n",{"type":32,"tag":157,"props":1123,"children":1124},{"class":159,"line":302},[1125],{"type":32,"tag":157,"props":1126,"children":1127},{"style":174},[1128],{"type":37,"value":1090},{"type":32,"tag":157,"props":1130,"children":1131},{"class":159,"line":316},[1132],{"type":32,"tag":157,"props":1133,"children":1134},{"style":174},[1135],{"type":37,"value":1098},{"type":32,"tag":157,"props":1137,"children":1138},{"class":159,"line":325},[1139],{"type":32,"tag":157,"props":1140,"children":1141},{"style":174},[1142],{"type":37,"value":1143},"  \u003Cimg\n",{"type":32,"tag":157,"props":1145,"children":1146},{"class":159,"line":334},[1147],{"type":32,"tag":157,"props":1148,"children":1149},{"style":174},[1150],{"type":37,"value":1151},"    src=\"\u002Fimages\u002Fhero-desktop.jpg\"\n",{"type":32,"tag":157,"props":1153,"children":1154},{"class":159,"line":343},[1155],{"type":32,"tag":157,"props":1156,"children":1157},{"style":174},[1158],{"type":37,"value":1159},"    alt=\"Nueva colección de temporada\"\n",{"type":32,"tag":157,"props":1161,"children":1162},{"class":159,"line":360},[1163],{"type":32,"tag":157,"props":1164,"children":1165},{"style":174},[1166],{"type":37,"value":1167},"    fetchpriority=\"high\"\n",{"type":32,"tag":157,"props":1169,"children":1170},{"class":159,"line":370},[1171],{"type":32,"tag":157,"props":1172,"children":1173},{"style":174},[1174],{"type":37,"value":1175},"    decoding=\"async\"\n",{"type":32,"tag":157,"props":1177,"children":1178},{"class":159,"line":387},[1179],{"type":32,"tag":157,"props":1180,"children":1181},{"style":174},[1182],{"type":37,"value":1098},{"type":32,"tag":157,"props":1184,"children":1185},{"class":159,"line":401},[1186,1190,1194],{"type":32,"tag":157,"props":1187,"children":1188},{"style":174},[1189],{"type":37,"value":349},{"type":32,"tag":157,"props":1191,"children":1192},{"style":180},[1193],{"type":37,"value":1054},{"type":32,"tag":157,"props":1195,"children":1196},{"style":174},[1197],{"type":37,"value":194},{"type":32,"tag":33,"props":1199,"children":1200},{},[1201,1203,1209],{"type":37,"value":1202},"Con atributo ",{"type":32,"tag":114,"props":1204,"children":1206},{"className":1205},[],[1207],{"type":37,"value":1208},"fetchpriority=\"high\"",{"type":37,"value":1210}," indicamos al navegador \"prioriza la carga de esta imagen\". Cloudflare Image Resizing realiza conversión automática de formato en edge (serve JPEG a navegadores sin soporte WebP).",{"type":32,"tag":33,"props":1212,"children":1213},{},[1214,1218,1220,1226],{"type":32,"tag":60,"props":1215,"children":1216},{},[1217],{"type":37,"value":556},{"type":37,"value":1219}," LCP 2.3s → 2.1s, tiempo de carga de imagen 1200ms → 320ms. CLS (Cumulative Layout Shift) 0.12 → 0.02 — reservamos espacio con propiedad CSS ",{"type":32,"tag":114,"props":1221,"children":1223},{"className":1222},[],[1224],{"type":37,"value":1225},"aspect-ratio",{"type":37,"value":591},{"type":32,"tag":40,"props":1228,"children":1230},{"id":1229},"resultados-de-benchmark-impacto-en-usuarios-reales",[1231],{"type":37,"value":1232},"Resultados de benchmark + impacto en usuarios reales",{"type":32,"tag":33,"props":1234,"children":1235},{},[1236],{"type":37,"value":1237},"PageSpeed Insights móvil 34 → 92, desktop 62 → 98. Promedio de CrUX a 28 días:",{"type":32,"tag":1239,"props":1240,"children":1241},"table",{},[1242,1271],{"type":32,"tag":1243,"props":1244,"children":1245},"thead",{},[1246],{"type":32,"tag":1247,"props":1248,"children":1249},"tr",{},[1250,1256,1261,1266],{"type":32,"tag":1251,"props":1252,"children":1253},"th",{},[1254],{"type":37,"value":1255},"Métrica",{"type":32,"tag":1251,"props":1257,"children":1258},{},[1259],{"type":37,"value":1260},"Antes",{"type":32,"tag":1251,"props":1262,"children":1263},{},[1264],{"type":37,"value":1265},"Después",{"type":32,"tag":1251,"props":1267,"children":1268},{},[1269],{"type":37,"value":1270},"Cambio",{"type":32,"tag":1272,"props":1273,"children":1274},"tbody",{},[1275,1299,1322,1345],{"type":32,"tag":1247,"props":1276,"children":1277},{},[1278,1284,1289,1294],{"type":32,"tag":1279,"props":1280,"children":1281},"td",{},[1282],{"type":37,"value":1283},"LCP",{"type":32,"tag":1279,"props":1285,"children":1286},{},[1287],{"type":37,"value":1288},"10.2s",{"type":32,"tag":1279,"props":1290,"children":1291},{},[1292],{"type":37,"value":1293},"2.1s",{"type":32,"tag":1279,"props":1295,"children":1296},{},[1297],{"type":37,"value":1298},"-79%",{"type":32,"tag":1247,"props":1300,"children":1301},{},[1302,1307,1312,1317],{"type":32,"tag":1279,"props":1303,"children":1304},{},[1305],{"type":37,"value":1306},"TBT",{"type":32,"tag":1279,"props":1308,"children":1309},{},[1310],{"type":37,"value":1311},"2190ms",{"type":32,"tag":1279,"props":1313,"children":1314},{},[1315],{"type":37,"value":1316},"420ms",{"type":32,"tag":1279,"props":1318,"children":1319},{},[1320],{"type":37,"value":1321},"-81%",{"type":32,"tag":1247,"props":1323,"children":1324},{},[1325,1330,1335,1340],{"type":32,"tag":1279,"props":1326,"children":1327},{},[1328],{"type":37,"value":1329},"CLS",{"type":32,"tag":1279,"props":1331,"children":1332},{},[1333],{"type":37,"value":1334},"0.12",{"type":32,"tag":1279,"props":1336,"children":1337},{},[1338],{"type":37,"value":1339},"0.02",{"type":32,"tag":1279,"props":1341,"children":1342},{},[1343],{"type":37,"value":1344},"-83%",{"type":32,"tag":1247,"props":1346,"children":1347},{},[1348,1353,1358,1363],{"type":32,"tag":1279,"props":1349,"children":1350},{},[1351],{"type":37,"value":1352},"TTFB",{"type":32,"tag":1279,"props":1354,"children":1355},{},[1356],{"type":37,"value":1357},"840ms",{"type":32,"tag":1279,"props":1359,"children":1360},{},[1361],{"type":37,"value":1362},"120ms",{"type":32,"tag":1279,"props":1364,"children":1365},{},[1366],{"type":37,"value":1367},"-86%",{"type":32,"tag":33,"props":1369,"children":1370},{},[1371,1373,1382],{"type":37,"value":1372},"Google Analytics en embudo de conversión: tasa de inicio checkout pasó de 3.2% a 4.8% (+50% en lift relativo). Bounce rate 68% → 52%. Search Console: tráfico orgánico aumentó 34% en 2 meses (otros cambios SEO controlados). Estas métricas alineadas con los estándares de Roibase en ",{"type":32,"tag":1374,"props":1375,"children":1379},"a",{"href":1376,"rel":1377},"https:\u002F\u002Fwww.roibase.com.tr\u002Fes\u002Fheadless",[1378],"nofollow",[1380],{"type":37,"value":1381},"Headless Commerce",{"type":37,"value":1383}," — si la performance no se traduce en métrica de negocio, el cambio arquitectónico no cuenta como exitoso.",{"type":32,"tag":40,"props":1385,"children":1387},{"id":1386},"trade-offs-y-criterios-de-decisión",[1388],{"type":37,"value":1389},"Trade-offs y criterios de decisión",{"type":32,"tag":33,"props":1391,"children":1392},{},[1393,1398,1400,1405,1407,1413],{"type":32,"tag":60,"props":1394,"children":1395},{},[1396],{"type":37,"value":1397},"Developer experience:",{"type":37,"value":1399}," Agregar wrapper de lazy hydration incrementó la surface area del API de componentes; nuevos developers necesitaban aprender la diferencia entre ",{"type":32,"tag":114,"props":1401,"children":1403},{"className":1402},[],[1404],{"type":37,"value":813},{"type":37,"value":1406}," vs ",{"type":32,"tag":114,"props":1408,"children":1410},{"className":1409},[],[1411],{"type":37,"value":1412},"when-idle",{"type":37,"value":1414},". Lo resolvimos con documentación en Storybook + reglas ESLint.",{"type":32,"tag":33,"props":1416,"children":1417},{},[1418,1423],{"type":32,"tag":60,"props":1419,"children":1420},{},[1421],{"type":37,"value":1422},"Bundle size vs costo en runtime:",{"type":37,"value":1424}," Archivos de fuentes auto-hospedadas sumaron +60kB al bundle inicial, pero eliminaron el costo de DNS lookup + TLS handshake. Este trade-off es ganancia neta en 3G móvil, neutral en fibra.",{"type":32,"tag":33,"props":1426,"children":1427},{},[1428,1433,1435,1440],{"type":32,"tag":60,"props":1429,"children":1430},{},[1431],{"type":37,"value":1432},"Cache invalidation:",{"type":37,"value":1434}," La estrategia ",{"type":32,"tag":114,"props":1436,"children":1438},{"className":1437},[],[1439],{"type":37,"value":1005},{"type":37,"value":1441}," conlleva riesgo de datos stale. Datos críticos como disponibilidad de stock se mantienen actualizados con fetch client-side en tiempo real (polling cada 30s en lugar de WebSocket — costo más bajo en edge functions).",{"type":32,"tag":33,"props":1443,"children":1444},{},[1445,1450],{"type":32,"tag":60,"props":1446,"children":1447},{},[1448],{"type":37,"value":1449},"Vendor lock-in de Cloudflare:",{"type":37,"value":1451}," El caching basado en KV es específico de Cloudflare; portabilidad a otra plataforma requeriría re-implementación. Pero Vercel\u002FNetlify tienen primitivas equivalentes, el esfuerzo de migración es aceptable.",{"type":32,"tag":40,"props":1453,"children":1455},{"id":1454},"próximos-pasos",[1456],{"type":37,"value":1457},"Próximos pasos",{"type":32,"tag":33,"props":1459,"children":1460},{},[1461],{"type":37,"value":1462},"2.1s LCP es sólido, pero CrUX P75 (percentil 75) aún está en 3.2s. El roadmap es:",{"type":32,"tag":1464,"props":1465,"children":1466},"ol",{},[1467,1477,1487,1497],{"type":32,"tag":56,"props":1468,"children":1469},{},[1470,1475],{"type":32,"tag":60,"props":1471,"children":1472},{},[1473],{"type":37,"value":1474},"Image CDN + negotiación automática de formato:",{"type":37,"value":1476}," Integración con Imgix en lugar de Cloudflare Polish, soporte AVIF",{"type":32,"tag":56,"props":1478,"children":1479},{},[1480,1485],{"type":32,"tag":60,"props":1481,"children":1482},{},[1483],{"type":37,"value":1484},"Estrategia de prefetch:",{"type":37,"value":1486}," Intersection Observer prefetches datos de product cards aproximándose a viewport",{"type":32,"tag":56,"props":1488,"children":1489},{},[1490,1495],{"type":32,"tag":60,"props":1491,"children":1492},{},[1493],{"type":37,"value":1494},"Service Worker + offline-first:",{"type":37,"value":1496}," Workbox cachea assets críticos, fallback network-first",{"type":32,"tag":56,"props":1498,"children":1499},{},[1500,1505],{"type":32,"tag":60,"props":1501,"children":1502},{},[1503],{"type":37,"value":1504},"Bundle splitting agresivo:",{"type":37,"value":1506}," Code splitting de Nuxt 3 más agresivo, chunking basado en rutas",{"type":32,"tag":33,"props":1508,"children":1509},{},[1510],{"type":37,"value":1511},"La optimización de performance es un juego sin fin — cada 100ms ganado genera +1-2% lift en conversión. La combinación Nuxt 3 + Cloudflare Pages ofrece equilibrio entre edge rendering y ergonomía de framework JS moderno. Al decidir la stack, definir el target LCP como requisito de negocio, luego evaluar opciones arquitectónicas dentro de esa restricción.",{"type":32,"tag":380,"props":1513,"children":1514},{},[1515],{"type":37,"value":1516},"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":1518},[1519,1520,1521,1523,1524,1525,1526,1527],{"id":42,"depth":170,"text":45},{"id":104,"depth":170,"text":107},{"id":561,"depth":170,"text":1522},"Selective hydration + content-visibility",{"id":818,"depth":170,"text":821},{"id":1019,"depth":170,"text":1022},{"id":1229,"depth":170,"text":1232},{"id":1386,"depth":170,"text":1389},{"id":1454,"depth":170,"text":1457},"markdown","content:es:tech:nuxt3-cloudflare-pages-lcp-optimizacion.md","content","es\u002Ftech\u002Fnuxt3-cloudflare-pages-lcp-optimizacion.md","es\u002Ftech\u002Fnuxt3-cloudflare-pages-lcp-optimizacion","md",1778164175897]