[{"data":1,"prerenderedAt":1395},["ShallowReactive",2],{"content:\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Ffixing-slow-lcp-in-vue-and-nuxt-apps":3,"surroundings:\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Ffixing-slow-lcp-in-vue-and-nuxt-apps":1386},{"id":4,"title":5,"body":6,"description":1367,"extension":1368,"meta":1369,"navigation":499,"path":1381,"seo":1382,"stem":1384,"__hash__":1385},"content\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Ffixing-slow-lcp-in-vue-and-nuxt-apps\u002Findex.md","Fixing Slow LCP in Vue and Nuxt Apps",{"type":7,"value":8,"toc":1353},"minimark",[9,14,34,50,163,168,237,241,257,270,283,289,436,440,443,448,458,652,658,662,767,774,778,911,973,981,985,988,1070,1073,1077,1088,1208,1211,1215,1231,1241,1251,1276,1280,1303,1312,1316,1339,1343,1346,1349],[10,11,13],"h1",{"id":12},"how-to-fix-lcp-over-25s-in-vue-and-nuxt-apps","How to Fix LCP Over 2.5s in Vue and Nuxt Apps",[15,16,17,18,23,24,28,29,33],"p",{},"This guide adapts the general workflow in ",[19,20,22],"a",{"href":21},"\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002F","Measuring LCP with Chrome DevTools"," to Vue 3 and Nuxt 3\u002F4 applications, as part of ",[19,25,27],{"href":26},"\u002Fcore-web-vitals-measurement\u002F","Core Web Vitals & Measurement",". It is the Vue counterpart to ",[19,30,32],{"href":31},"\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Fhow-to-fix-lcp-over-25-seconds-on-react-apps\u002F","how to fix LCP over 2.5s on React apps",".",[15,35,36,37,41,42,45,46,49],{},"Vue applications fail LCP in two distinct shapes. A plain Vue SPA (Vite + Vue Router, no SSR) ships an empty ",[38,39,40],"code",{},"\u003Cdiv id=\"app\">",", so LCP waits for the entire bundle, the router, the data and the hero image in sequence — routinely ",[38,43,44],{},"4s"," or more on mobile. A Nuxt application renders HTML on the server, so the hero is in the document, but LCP can still miss ",[38,47,48],{},"2.5s"," because of a client-only hero component, an image module configured to lazy-load, a payload that dwarfs the HTML, or a hero that is replaced during hydration.",[15,51,52],{},[53,54,60,61,60,68,60,72,60,75,60,84,60,90,60,99,60,105,60,110,60,115,60,118,60,121,60,124,60,127,60,130,60,133,60,138,60,142,60,144,60,148,60,150,60,153,60,155,60,158,60,160,60],"svg",{"viewBox":55,"width":56,"role":57,"ariaLabel":58,"style":59},"0 0 760 228","100%","img","Comparison of the critical path for LCP in a client-rendered Vue SPA and a server-rendered Nuxt app.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[62,63],"rect",{"className":64,"x":66,"y":66,"width":56,"height":56,"fill":67},[65],"svg-canvas","0","#ffffff",[69,70,71],"title",{},"Two ways Vue apps miss the LCP budget",[73,74,58],"desc",{},[62,76],{"x":77,"y":77,"width":78,"height":79,"rx":80,"fill":81,"stroke":82,"style":83},"1","758","226","10","none","currentColor","stroke-opacity:0.18",[85,86,71],"text",{"x":87,"y":88,"fill":82,"style":89},"28.0","34.0","font-size:16px;font-weight:700",[62,91],{"x":87,"y":92,"width":93,"height":94,"rx":95,"fill":96,"stroke":97,"style":98},"56.0","340.0","150.0","6","#ffc300","#b8860b","fill-opacity:0.24;stroke-opacity:0.9",[85,100,104],{"x":101,"y":102,"fill":82,"style":103},"42.0","82.0","font-size:14px;font-weight:700","Vue SPA (client-rendered)",[85,106,109],{"x":101,"y":107,"fill":82,"style":108},"108.0","font-size:12.5px;font-weight:700","•",[85,111,114],{"x":92,"y":107,"fill":82,"style":112,"textAnchor":113},"font-size:12.5px","start","Empty #app shell in HTML",[85,116,109],{"x":101,"y":117,"fill":82,"style":108},"132.0",[85,119,120],{"x":92,"y":117,"fill":82,"style":112,"textAnchor":113},"Bundle download, parse, execute",[85,122,109],{"x":101,"y":123,"fill":82,"style":108},"156.0",[85,125,126],{"x":92,"y":123,"fill":82,"style":112,"textAnchor":113},"Router resolves, data fetched",[85,128,109],{"x":101,"y":129,"fill":82,"style":108},"180.0",[85,131,132],{"x":92,"y":129,"fill":82,"style":112,"textAnchor":113},"Hero image discovered last",[62,134],{"x":135,"y":92,"width":93,"height":94,"rx":95,"fill":136,"stroke":136,"style":137},"392.0","#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[85,139,141],{"x":140,"y":102,"fill":82,"style":103},"406.0","Nuxt (server-rendered)",[85,143,109],{"x":140,"y":107,"fill":82,"style":108},[85,145,147],{"x":146,"y":107,"fill":82,"style":112,"textAnchor":113},"420.0","Hero markup in HTML early",[85,149,109],{"x":140,"y":117,"fill":82,"style":108},[85,151,152],{"x":146,"y":117,"fill":82,"style":112,"textAnchor":113},"But: ClientOnly hero or lazy image",[85,154,109],{"x":140,"y":123,"fill":82,"style":108},[85,156,157],{"x":146,"y":123,"fill":82,"style":112,"textAnchor":113},"Large _payload delays hydration",[85,159,109],{"x":140,"y":129,"fill":82,"style":108},[85,161,162],{"x":146,"y":129,"fill":82,"style":112,"textAnchor":113},"Hydration can re-render the hero",[164,165,167],"h2",{"id":166},"rapid-diagnosis","Rapid Diagnosis",[169,170,171,194,204,218,231],"ul",{},[172,173,174,60,178,181,182,185,186,189,190,193],"li",{},[175,176,177],"strong",{},"View the raw HTML.",[38,179,180],{},"curl -s https:\u002F\u002Fexample.com\u002F | grep -c 'hero'"," — if the hero markup is missing, it is client-rendered (SPA, ",[38,183,184],{},"\u003CClientOnly>",", ",[38,187,188],{},"ssr: false"," route rule, or a component guarded by ",[38,191,192],{},"onMounted",").",[172,195,196,199,200,203],{},[175,197,198],{},"Find the LCP element in the Performance panel"," and note whether it is an image (check its ",[38,201,202],{},"loading"," attribute in Elements) or text.",[172,205,206,209,210,213,214,217],{},[175,207,208],{},"Check the document size vs payload."," In Network, compare the HTML document with ",[38,211,212],{},"_payload.json"," or the inline ",[38,215,216],{},"__NUXT_DATA__"," script. A payload several times the size of the rendered HTML delays hydration and competes with the hero image for bandwidth.",[172,219,220,223,224,185,227,230],{},[175,221,222],{},"Look for a hydration mismatch warning"," in the console (",[38,225,226],{},"Hydration node mismatch",[38,228,229],{},"Hydration text content mismatch","). Mismatches make Vue patch the DOM, which can repaint the hero later than its SSR paint.",[172,232,233,236],{},[175,234,235],{},"Check image priority."," On the hero image request, the Priority column should read \"High\". \"Low\" means it is lazy or being discovered late.",[164,238,240],{"id":239},"root-cause-analysis","Root Cause Analysis",[15,242,243,246,247,250,251,253,254,256],{},[175,244,245],{},"1. Client-only hero."," A carousel, a personalised banner or a component using ",[38,248,249],{},"window"," is wrapped in ",[38,252,184],{}," or mounted conditionally in ",[38,255,192],{},". The server renders a placeholder; the real hero appears only after hydration.",[15,258,259,60,262,265,266,269],{},[175,260,261],{},"2. NuxtImg\u002FNuxtPicture with lazy loading.",[38,263,264],{},"@nuxt\u002Fimage"," components are often configured site-wide with ",[38,267,268],{},"loading=\"lazy\"",". Applied to the hero, this defers the request until layout confirms visibility — after CSS and often after other images.",[15,271,272,60,275,278,279,282],{},[175,273,274],{},"3. Payload bloat.",[38,276,277],{},"useAsyncData"," and ",[38,280,281],{},"useFetch"," serialise every fetched object into the payload. Returning full API objects (with fields the template never reads) can produce a 300KB+ payload that must download and parse before hydration completes.",[15,284,285,288],{},[175,286,287],{},"4. Plain SPA with sequential loading."," Without SSR, the hero URL is unknown until the component renders after data loads — the browser's preload scanner can never find it.",[15,290,291],{},[53,292,60,295,60,298,60,301,60,303,60,306,60,308,60,317,60,321,60,329,60,336,60,340,60,344,60,347,60,351,60,355,60,359,60,363,60,367,60,372,60,376,60,380,60,385,60,391,60,395,60,399,60,403,60,407,60,410,60,414,60,418,60,422,60,426,60,432,60],{"viewBox":293,"width":56,"role":57,"ariaLabel":294,"style":59},"0 0 760 226","Timeline of a client-rendered Vue app where bundle, data and hero image load sequentially, landing LCP at 4.1 seconds.",[62,296],{"className":297,"x":66,"y":66,"width":56,"height":56,"fill":67},[65],[69,299,300],{},"A Vue SPA LCP waterfall on mid-tier mobile",[73,302,294],{},[62,304],{"x":77,"y":77,"width":78,"height":305,"rx":80,"fill":81,"stroke":82,"style":83},"224",[85,307,300],{"x":87,"y":88,"fill":82,"style":89},[309,310],"line",{"x1":311,"y1":312,"x2":311,"y2":123,"stroke":97,"strokeWidth":313,"strokeDashArray":314,"style":316},"452.8","72.0","1.5",[315,315],"4","stroke-opacity:0.9",[85,318,320],{"x":87,"y":319,"fill":82,"style":108},"96.0","Network",[62,322],{"x":323,"y":324,"width":325,"height":326,"rx":327,"fill":82,"stroke":82,"style":328},"112.0","78.0","60.0","26.0","3","fill-opacity:0.06;stroke-opacity:0.4",[85,330,335],{"x":331,"y":332,"fill":82,"style":333,"textAnchor":334},"141.9","95.5","font-size:11.5px","middle","HTML",[62,337],{"x":338,"y":324,"width":339,"height":326,"rx":327,"fill":136,"stroke":136,"style":137},"173.4","155.6",[85,341,343],{"x":342,"y":332,"fill":82,"style":333,"textAnchor":334},"251.2","app bundle",[62,345],{"x":135,"y":324,"width":346,"height":326,"rx":327,"fill":82,"stroke":82,"style":328},"87.3",[85,348,350],{"x":349,"y":332,"fill":82,"style":333,"textAnchor":334},"435.7","API",[62,352],{"x":353,"y":324,"width":354,"height":326,"rx":327,"fill":96,"stroke":97,"style":98},"515.0","128.3",[85,356,358],{"x":357,"y":332,"fill":82,"style":333,"textAnchor":334},"579.1","hero image",[85,360,362],{"x":87,"y":361,"fill":82,"style":108},"134.0","Main thread",[62,364],{"x":365,"y":366,"width":325,"height":326,"rx":327,"fill":136,"stroke":136,"style":137},"330.5","116.0",[85,368,371],{"x":369,"y":370,"fill":82,"style":333,"textAnchor":334},"360.5","133.5","mount",[62,373],{"x":374,"y":366,"width":375,"height":326,"rx":327,"fill":136,"stroke":136,"style":137},"480.8","32.7",[62,377],{"x":378,"y":366,"width":379,"height":326,"rx":327,"fill":96,"stroke":97,"style":98},"644.8","25.8",[309,381],{"x1":382,"y1":123,"x2":383,"y2":123,"stroke":82,"style":384},"111.2","726.0","stroke-opacity:0.4",[85,386,390],{"x":387,"y":388,"fill":389,"style":333,"textAnchor":334},"121.9","173.0","#51617a","0ms",[85,392,394],{"x":393,"y":388,"fill":389,"style":333,"textAnchor":334},"179.5","500ms",[85,396,398],{"x":397,"y":388,"fill":389,"style":333,"textAnchor":334},"247.8","1000ms",[85,400,402],{"x":401,"y":388,"fill":389,"style":333,"textAnchor":334},"316.1","1500ms",[85,404,406],{"x":405,"y":388,"fill":389,"style":333,"textAnchor":334},"384.4","2000ms",[85,408,409],{"x":311,"y":388,"fill":389,"style":333,"textAnchor":334},"2500ms",[85,411,413],{"x":412,"y":388,"fill":389,"style":333,"textAnchor":334},"521.1","3000ms",[85,415,417],{"x":416,"y":388,"fill":389,"style":333,"textAnchor":334},"589.4","3500ms",[85,419,421],{"x":420,"y":388,"fill":389,"style":333,"textAnchor":334},"657.7","4000ms",[85,423,425],{"x":424,"y":388,"fill":389,"style":333,"textAnchor":334},"712.3","4500ms",[85,427,431],{"x":311,"y":428,"fill":429,"style":430,"textAnchor":334},"68.0","#8a6608","font-size:12px;font-weight:700","LCP 2.5s",[85,433,435],{"x":87,"y":434,"fill":389,"style":112},"204.0","The short main-thread blocks after the API response and the image are the route render and the final paint.",[164,437,439],{"id":438},"step-by-step-resolution","Step-by-Step Resolution",[15,441,442],{},"Ordered by typical impact. Apply the first that matches your diagnosis, measure, then continue.",[444,445,447],"h3",{"id":446},"_1-server-render-the-hero-or-prerender-the-route","1. Server-render the hero (or prerender the route)",[15,449,450,451,454,455,457],{},"For a plain Vue SPA, the largest single win is rendering the above-the-fold HTML ahead of JavaScript — via Nuxt, ",[38,452,453],{},"vite-ssg"," for static routes, or prerendering marketing pages. In Nuxt, remove ",[38,456,184],{}," from the hero and make it SSR-safe instead.",[459,460,465],"pre",{"className":461,"code":462,"language":463,"meta":464,"style":464},"language-vue shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u003C!-- Before: the hero only exists after hydration -->\n\u003CClientOnly>\u003CHeroCarousel :slides=\"slides\" \u002F>\u003C\u002FClientOnly>\n\n\u003C!-- After: render the first slide on the server; enhance on the client -->\n\u003CHeroCarousel :slides=\"slides\" :initial=\"0\" \u002F>\n\u003Cscript setup>\n\u002F\u002F inside HeroCarousel: guard browser APIs instead of the whole component\nconst autoplay = ref(false);\nonMounted(() => { autoplay.value = !matchMedia('(prefers-reduced-motion)').matches; });\n\u003C\u002Fscript>\n\u003C!-- trade-off: SSR-safe components must not read window\u002FlocalStorage during\n     setup. Personalised heroes need a server-side decision (cookie, edge\n     logic) or a neutral default that the client upgrades without layout shift. -->\n","vue","",[38,466,467,475,494,501,507,548,561,567,593,624,634,640,646],{"__ignoreMap":464},[468,469,471],"span",{"class":309,"line":470},1,[468,472,474],{"class":473},"sjfSM","\u003C!-- Before: the hero only exists after hydration -->\n",[468,476,478,482,486,489,491],{"class":309,"line":477},2,[468,479,481],{"class":480},"saISM","\u003C",[468,483,485],{"class":484},"sZBmE","ClientOnly",[468,487,488],{"class":480},">\u003CHeroCarousel :slides=\"slides\" \u002F>\u003C\u002F",[468,490,485],{"class":484},[468,492,493],{"class":480},">\n",[468,495,497],{"class":309,"line":496},3,[468,498,500],{"emptyLinePlaceholder":499},true,"\n",[468,502,504],{"class":309,"line":503},4,[468,505,506],{"class":473},"\u003C!-- After: render the first slide on the server; enhance on the client -->\n",[468,508,510,512,515,518,522,525,528,530,532,534,537,539,541,543,545],{"class":309,"line":509},5,[468,511,481],{"class":480},[468,513,514],{"class":484},"HeroCarousel",[468,516,517],{"class":480}," :",[468,519,521],{"class":520},"sPXB4","slides",[468,523,524],{"class":480},"=",[468,526,527],{"class":480},"\"",[468,529,521],{"class":480},[468,531,527],{"class":480},[468,533,517],{"class":480},[468,535,536],{"class":520},"initial",[468,538,524],{"class":480},[468,540,527],{"class":480},[468,542,66],{"class":520},[468,544,527],{"class":480},[468,546,547],{"class":480}," \u002F>\n",[468,549,551,553,556,559],{"class":309,"line":550},6,[468,552,481],{"class":480},[468,554,555],{"class":484},"script",[468,557,558],{"class":520}," setup",[468,560,493],{"class":480},[468,562,564],{"class":309,"line":563},7,[468,565,566],{"class":473},"\u002F\u002F inside HeroCarousel: guard browser APIs instead of the whole component\n",[468,568,570,574,577,580,584,587,590],{"class":309,"line":569},8,[468,571,573],{"class":572},"sPARh","const",[468,575,576],{"class":520}," autoplay",[468,578,579],{"class":572}," =",[468,581,583],{"class":582},"smZ65"," ref",[468,585,586],{"class":480},"(",[468,588,589],{"class":520},"false",[468,591,592],{"class":480},");\n",[468,594,596,598,601,604,607,609,612,615,617,621],{"class":309,"line":595},9,[468,597,192],{"class":582},[468,599,600],{"class":480},"(() ",[468,602,603],{"class":572},"=>",[468,605,606],{"class":480}," { autoplay.value ",[468,608,524],{"class":572},[468,610,611],{"class":572}," !",[468,613,614],{"class":582},"matchMedia",[468,616,586],{"class":480},[468,618,620],{"class":619},"sZ8jY","'(prefers-reduced-motion)'",[468,622,623],{"class":480},").matches; });\n",[468,625,627,630,632],{"class":309,"line":626},10,[468,628,629],{"class":480},"\u003C\u002F",[468,631,555],{"class":484},[468,633,493],{"class":480},[468,635,637],{"class":309,"line":636},11,[468,638,639],{"class":473},"\u003C!-- trade-off: SSR-safe components must not read window\u002FlocalStorage during\n",[468,641,643],{"class":309,"line":642},12,[468,644,645],{"class":473},"     setup. Personalised heroes need a server-side decision (cookie, edge\n",[468,647,649],{"class":309,"line":648},13,[468,650,651],{"class":473},"     logic) or a neutral default that the client upgrades without layout shift. -->\n",[15,653,654,655,657],{},"Expected outcome: LCP for SPA routes drops by 1–2.5s on mid-tier mobile; for Nuxt pages with a ",[38,656,485],{}," hero, by the hydration time (typically 400–1200ms).",[444,659,661],{"id":660},"_2-make-the-hero-image-eager-and-high-priority","2. Make the hero image eager and high priority",[459,663,665],{"className":461,"code":664,"language":463,"meta":464,"style":464},"\u003CNuxtImg\n  src=\"\u002Fhero\u002Fspring-sale.jpg\"\n  sizes=\"100vw sm:100vw md:1200px\"\n  width=\"1200\" height=\"600\"\n  format=\"avif,webp\"\n  loading=\"eager\"\n  fetchpriority=\"high\"\n  preload\n\u002F>\n\u003C!-- trade-off: the preload prop emits a \u003Clink rel=\"preload\"> in the head. Use it\n     only for the single LCP image per template — preloading several images\n     splits bandwidth and slows all of them. -->\n",[38,666,667,674,684,694,712,722,732,742,747,752,757,762],{"__ignoreMap":464},[468,668,669,671],{"class":309,"line":470},[468,670,481],{"class":480},[468,672,673],{"class":484},"NuxtImg\n",[468,675,676,679,681],{"class":309,"line":477},[468,677,678],{"class":520},"  src",[468,680,524],{"class":480},[468,682,683],{"class":619},"\"\u002Fhero\u002Fspring-sale.jpg\"\n",[468,685,686,689,691],{"class":309,"line":496},[468,687,688],{"class":520},"  sizes",[468,690,524],{"class":480},[468,692,693],{"class":619},"\"100vw sm:100vw md:1200px\"\n",[468,695,696,699,701,704,707,709],{"class":309,"line":503},[468,697,698],{"class":520},"  width",[468,700,524],{"class":480},[468,702,703],{"class":619},"\"1200\"",[468,705,706],{"class":520}," height",[468,708,524],{"class":480},[468,710,711],{"class":619},"\"600\"\n",[468,713,714,717,719],{"class":309,"line":509},[468,715,716],{"class":520},"  format",[468,718,524],{"class":480},[468,720,721],{"class":619},"\"avif,webp\"\n",[468,723,724,727,729],{"class":309,"line":550},[468,725,726],{"class":520},"  loading",[468,728,524],{"class":480},[468,730,731],{"class":619},"\"eager\"\n",[468,733,734,737,739],{"class":309,"line":563},[468,735,736],{"class":520},"  fetchpriority",[468,738,524],{"class":480},[468,740,741],{"class":619},"\"high\"\n",[468,743,744],{"class":309,"line":569},[468,745,746],{"class":520},"  preload\n",[468,748,749],{"class":309,"line":595},[468,750,751],{"class":480},"\u002F>\n",[468,753,754],{"class":309,"line":626},[468,755,756],{"class":480},"\u003C!-- trade-off: the preload prop emits a \u003Clink rel=\"preload\"> in the head. Use it\n",[468,758,759],{"class":309,"line":636},[468,760,761],{"class":480},"     only for the single LCP image per template — preloading several images\n",[468,763,764],{"class":309,"line":642},[468,765,766],{"class":480},"     splits bandwidth and slows all of them. -->\n",[15,768,769,770,33],{},"Expected outcome: the hero request starts during HTML parsing instead of after layout; load delay typically falls 200–600ms. The underlying mechanics are covered in ",[19,771,773],{"href":772},"\u002Fimage-media-optimization\u002Fimage-cdns-and-fetchpriority\u002Fusing-fetchpriority-to-prioritize-the-lcp-image\u002F","using fetchpriority to prioritize the LCP image",[444,775,777],{"id":776},"_3-trim-the-payload-to-what-the-template-uses","3. Trim the payload to what the template uses",[459,779,783],{"className":780,"code":781,"language":782,"meta":464,"style":464},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u002F\u002F Before: the whole product object (reviews, variants, SEO blobs) lands in the payload.\nconst { data } = await useFetch(`\u002Fapi\u002Fproducts\u002F${id}`);\n\n\u002F\u002F After: pick only the fields the page renders above and below the fold.\nconst { data } = await useFetch(`\u002Fapi\u002Fproducts\u002F${id}`, {\n  pick: ['id', 'name', 'price', 'heroImage', 'summary'],\n});\n\u002F\u002F trade-off: pick runs after the fetch on the server, so the API still does the\n\u002F\u002F full work. For big savings, add a lean endpoint or a ?fields= parameter so\n\u002F\u002F the server does not build data it will discard.\n","javascript",[38,784,785,790,824,828,833,860,891,896,901,906],{"__ignoreMap":464},[468,786,787],{"class":309,"line":470},[468,788,789],{"class":473},"\u002F\u002F Before: the whole product object (reviews, variants, SEO blobs) lands in the payload.\n",[468,791,792,794,797,800,803,805,808,811,813,816,819,822],{"class":309,"line":477},[468,793,573],{"class":572},[468,795,796],{"class":480}," { ",[468,798,799],{"class":520},"data",[468,801,802],{"class":480}," } ",[468,804,524],{"class":572},[468,806,807],{"class":572}," await",[468,809,810],{"class":582}," useFetch",[468,812,586],{"class":480},[468,814,815],{"class":619},"`\u002Fapi\u002Fproducts\u002F${",[468,817,818],{"class":480},"id",[468,820,821],{"class":619},"}`",[468,823,592],{"class":480},[468,825,826],{"class":309,"line":496},[468,827,500],{"emptyLinePlaceholder":499},[468,829,830],{"class":309,"line":503},[468,831,832],{"class":473},"\u002F\u002F After: pick only the fields the page renders above and below the fold.\n",[468,834,835,837,839,841,843,845,847,849,851,853,855,857],{"class":309,"line":509},[468,836,573],{"class":572},[468,838,796],{"class":480},[468,840,799],{"class":520},[468,842,802],{"class":480},[468,844,524],{"class":572},[468,846,807],{"class":572},[468,848,810],{"class":582},[468,850,586],{"class":480},[468,852,815],{"class":619},[468,854,818],{"class":480},[468,856,821],{"class":619},[468,858,859],{"class":480},", {\n",[468,861,862,865,868,870,873,875,878,880,883,885,888],{"class":309,"line":550},[468,863,864],{"class":480},"  pick: [",[468,866,867],{"class":619},"'id'",[468,869,185],{"class":480},[468,871,872],{"class":619},"'name'",[468,874,185],{"class":480},[468,876,877],{"class":619},"'price'",[468,879,185],{"class":480},[468,881,882],{"class":619},"'heroImage'",[468,884,185],{"class":480},[468,886,887],{"class":619},"'summary'",[468,889,890],{"class":480},"],\n",[468,892,893],{"class":309,"line":563},[468,894,895],{"class":480},"});\n",[468,897,898],{"class":309,"line":569},[468,899,900],{"class":473},"\u002F\u002F trade-off: pick runs after the fetch on the server, so the API still does the\n",[468,902,903],{"class":309,"line":595},[468,904,905],{"class":473},"\u002F\u002F full work. For big savings, add a lean endpoint or a ?fields= parameter so\n",[468,907,908],{"class":309,"line":626},[468,909,910],{"class":473},"\u002F\u002F the server does not build data it will discard.\n",[15,912,913],{},[53,914,60,917,60,920,60,923,60,925,60,928,60,930,60,937,60,943,60,948,60,952,60,957,60,961,60,964,60,969,60],{"viewBox":915,"width":56,"role":57,"ariaLabel":916,"style":59},"0 0 760 163","Bar chart comparing the size of the rendered HTML with the hydration payload before and after picking only the fields the template uses.",[62,918],{"className":919,"x":66,"y":66,"width":56,"height":56,"fill":67},[65],[69,921,922],{},"Product page payload vs rendered HTML",[73,924,916],{},[62,926],{"x":77,"y":77,"width":78,"height":927,"rx":80,"fill":81,"stroke":82,"style":83},"161",[85,929,922],{"x":87,"y":88,"fill":82,"style":89},[85,931,936],{"x":932,"y":933,"fill":82,"style":934,"textAnchor":935},"160.3","70.0","font-size:13px","end","Rendered HTML (gzip)",[62,938],{"x":939,"y":92,"width":940,"height":941,"rx":327,"fill":82,"stroke":82,"style":942},"172.3","88.9","19","fill-opacity:0.7;stroke-opacity:0.4",[85,944,947],{"x":945,"y":933,"fill":82,"style":946},"267.2","font-size:12px;font-weight:600","38KB",[85,949,951],{"x":932,"y":950,"fill":82,"style":934,"textAnchor":935},"101.0","Payload before pick",[62,953],{"x":939,"y":954,"width":955,"height":941,"rx":327,"fill":96,"stroke":97,"style":956},"87.0","495.7","fill-opacity:0.7;stroke-opacity:0.9",[85,958,960],{"x":959,"y":950,"fill":82,"style":946},"674.0","212KB",[85,962,963],{"x":932,"y":117,"fill":82,"style":934,"textAnchor":935},"Payload after pick",[62,965],{"x":939,"y":966,"width":967,"height":941,"rx":327,"fill":136,"stroke":136,"style":968},"118.0","44.4","fill-opacity:0.55;stroke-opacity:0.9",[85,970,972],{"x":971,"y":117,"fill":82,"style":946},"222.7","19KB",[15,974,975,976,980],{},"Expected outcome: payload size typically falls 50–90%, shortening hydration and freeing bandwidth for the hero image. ",[19,977,979],{"href":978},"\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002Freducing-nuxt-payload-size\u002F","Reducing Nuxt payload size"," covers the remaining techniques.",[444,982,984],{"id":983},"_4-fix-hydration-mismatches-on-the-hero","4. Fix hydration mismatches on the hero",[15,986,987],{},"Mismatches in the hero (a date formatted differently on server and client, a random slide order, a viewport-dependent class) cause Vue to patch the DOM after hydration, which can produce a new, later LCP candidate.",[459,989,991],{"className":461,"code":990,"language":463,"meta":464,"style":464},"\u003C!-- Before: different output on server and client -->\n\u003Cp>{{ new Date().toLocaleDateString() }}\u003C\u002Fp>\n\n\u003C!-- After: render a stable value on the server, refine on the client -->\n\u003Cp>{{ publishedIso }}\u003C\u002Fp>\n\u003CNuxtTime :datetime=\"publishedIso\" \u002F>   \u003C!-- or format in onMounted -->\n\u003C!-- trade-off: deferring client-specific formatting means a brief stable\n     rendering first. Keep the stable version the same size to avoid CLS. -->\n",[38,992,993,998,1011,1015,1020,1033,1060,1065],{"__ignoreMap":464},[468,994,995],{"class":309,"line":470},[468,996,997],{"class":473},"\u003C!-- Before: different output on server and client -->\n",[468,999,1000,1002,1004,1007,1009],{"class":309,"line":477},[468,1001,481],{"class":480},[468,1003,15],{"class":484},[468,1005,1006],{"class":480},">{{ new Date().toLocaleDateString() }}\u003C\u002F",[468,1008,15],{"class":484},[468,1010,493],{"class":480},[468,1012,1013],{"class":309,"line":496},[468,1014,500],{"emptyLinePlaceholder":499},[468,1016,1017],{"class":309,"line":503},[468,1018,1019],{"class":473},"\u003C!-- After: render a stable value on the server, refine on the client -->\n",[468,1021,1022,1024,1026,1029,1031],{"class":309,"line":509},[468,1023,481],{"class":480},[468,1025,15],{"class":484},[468,1027,1028],{"class":480},">{{ publishedIso }}\u003C\u002F",[468,1030,15],{"class":484},[468,1032,493],{"class":480},[468,1034,1035,1037,1040,1042,1045,1047,1049,1052,1054,1057],{"class":309,"line":550},[468,1036,481],{"class":480},[468,1038,1039],{"class":484},"NuxtTime",[468,1041,517],{"class":480},[468,1043,1044],{"class":520},"datetime",[468,1046,524],{"class":480},[468,1048,527],{"class":480},[468,1050,1051],{"class":480},"publishedIso",[468,1053,527],{"class":480},[468,1055,1056],{"class":480}," \u002F>   ",[468,1058,1059],{"class":473},"\u003C!-- or format in onMounted -->\n",[468,1061,1062],{"class":309,"line":563},[468,1063,1064],{"class":473},"\u003C!-- trade-off: deferring client-specific formatting means a brief stable\n",[468,1066,1067],{"class":309,"line":569},[468,1068,1069],{"class":473},"     rendering first. Keep the stable version the same size to avoid CLS. -->\n",[15,1071,1072],{},"Expected outcome: no hydration warnings; the LCP timestamp matches the first SSR paint instead of a post-hydration repaint.",[164,1074,1076],{"id":1075},"verification","Verification",[15,1078,1079,1080,1083,1084,1087],{},"Compare before-and-after traces with identical throttling. For SSR fixes, the LCP marker should move ahead of the hydration long task in the main-thread track. For image fixes, the hero request should start within the first few hundred milliseconds of the HTML arriving. Then guard the gain in CI with Lighthouse CI's ",[38,1081,1082],{},"largest-contentful-paint"," assertion at ",[38,1085,1086],{},"2500"," and a payload size budget:",[459,1089,1091],{"className":780,"code":1090,"language":782,"meta":464,"style":464},"\u002F\u002F scripts\u002Fcheck-payload.mjs — fail CI if any prerendered payload exceeds 60KB.\nimport { globSync, statSync } from 'node:fs';\nconst big = globSync('.output\u002Fpublic\u002F**\u002F_payload.json').filter((f) => statSync(f).size > 60_000);\nif (big.length) { console.error('Payload over budget:', big); process.exit(1); }\n\u002F\u002F trade-off: a flat 60KB cap is crude — data-heavy pages legitimately need more.\n\u002F\u002F Set per-route caps for those instead of raising the global one.\n",[38,1092,1093,1098,1115,1163,1198,1203],{"__ignoreMap":464},[468,1094,1095],{"class":309,"line":470},[468,1096,1097],{"class":473},"\u002F\u002F scripts\u002Fcheck-payload.mjs — fail CI if any prerendered payload exceeds 60KB.\n",[468,1099,1100,1103,1106,1109,1112],{"class":309,"line":477},[468,1101,1102],{"class":572},"import",[468,1104,1105],{"class":480}," { globSync, statSync } ",[468,1107,1108],{"class":572},"from",[468,1110,1111],{"class":619}," 'node:fs'",[468,1113,1114],{"class":480},";\n",[468,1116,1117,1119,1122,1124,1127,1129,1132,1134,1137,1140,1144,1147,1149,1152,1155,1158,1161],{"class":309,"line":496},[468,1118,573],{"class":572},[468,1120,1121],{"class":520}," big",[468,1123,579],{"class":572},[468,1125,1126],{"class":582}," globSync",[468,1128,586],{"class":480},[468,1130,1131],{"class":619},"'.output\u002Fpublic\u002F**\u002F_payload.json'",[468,1133,193],{"class":480},[468,1135,1136],{"class":582},"filter",[468,1138,1139],{"class":480},"((",[468,1141,1143],{"class":1142},"sQw3B","f",[468,1145,1146],{"class":480},") ",[468,1148,603],{"class":572},[468,1150,1151],{"class":582}," statSync",[468,1153,1154],{"class":480},"(f).size ",[468,1156,1157],{"class":572},">",[468,1159,1160],{"class":520}," 60_000",[468,1162,592],{"class":480},[468,1164,1165,1168,1171,1174,1177,1180,1182,1185,1188,1191,1193,1195],{"class":309,"line":503},[468,1166,1167],{"class":572},"if",[468,1169,1170],{"class":480}," (big.",[468,1172,1173],{"class":520},"length",[468,1175,1176],{"class":480},") { console.",[468,1178,1179],{"class":582},"error",[468,1181,586],{"class":480},[468,1183,1184],{"class":619},"'Payload over budget:'",[468,1186,1187],{"class":480},", big); process.",[468,1189,1190],{"class":582},"exit",[468,1192,586],{"class":480},[468,1194,77],{"class":520},[468,1196,1197],{"class":480},"); }\n",[468,1199,1200],{"class":309,"line":509},[468,1201,1202],{"class":473},"\u002F\u002F trade-off: a flat 60KB cap is crude — data-heavy pages legitimately need more.\n",[468,1204,1205],{"class":309,"line":550},[468,1206,1207],{"class":473},"\u002F\u002F Set per-route caps for those instead of raising the global one.\n",[15,1209,1210],{},"In RUM, split LCP by element type and by whether the session was a hard load, so you can confirm the hero-specific fix rather than a general improvement.",[164,1212,1214],{"id":1213},"vue-specific-pitfalls-worth-checking","Vue-Specific Pitfalls Worth Checking",[15,1216,1217,1223,1224,1226,1227,1230],{},[175,1218,1219,1222],{},[38,1220,1221],{},"v-if"," on the hero during SSR."," A hero guarded by a reactive flag that is ",[38,1225,589],{}," on the server (for example, a store value populated in a client plugin) renders nothing in the HTML. Initialise the flag on the server or use ",[38,1228,1229],{},"v-show"," so the markup is present.",[15,1232,1233,1240],{},[175,1234,1235,1236,1239],{},"Global ",[38,1237,1238],{},"defineAsyncComponent"," for layout pieces."," Making the header or hero async splits them into separate chunks; during SSR they render fine, but in SPA mode they add a chunk round trip before LCP. Keep above-the-fold components synchronous.",[15,1242,1243,1246,1247,1250],{},[175,1244,1245],{},"Transitions on page enter."," Nuxt's ",[38,1248,1249],{},"pageTransition"," with an opacity fade means the hero starts invisible. LCP is not recorded until the element is visible. Disable the transition for the initial load or start it from opacity 1.",[15,1252,1253,1259,1260,1263,1264,1267,1268,1271,1272,1275],{},[175,1254,1255,1256,1258],{},"Too many ",[38,1257,277],{}," calls awaited in sequence."," Each top-level ",[38,1261,1262],{},"await"," in ",[38,1265,1266],{},"\u003Cscript setup>"," runs in order on the server, adding to TTFB. Run independent fetches in parallel with ",[38,1269,1270],{},"Promise.all"," or non-blocking ",[38,1273,1274],{},"lazy: true"," for below-the-fold data.",[164,1277,1279],{"id":1278},"faq","FAQ",[1281,1282,1285,1289],"details",{"className":1283},[1284],"faq-item",[1286,1287,1288],"summary",{},"Does Nuxt's lazy hydration help LCP?",[15,1290,1291,1292,185,1295,1298,1299,33],{},"Indirectly. Lazy hydration (",[38,1293,1294],{},"hydrate-on-visible",[38,1296,1297],{},"hydrate-never"," and similar) reduces main-thread work during startup, which mostly benefits INP and Total Blocking Time. It helps LCP only when hydration work was delaying the hero's paint — for instance a client-patched hero, or a hero image whose request was queued behind script. See ",[19,1300,1302],{"href":1301},"\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002Flazy-hydration-in-nuxt\u002F","lazy hydration in Nuxt",[1281,1304,1306,1309],{"className":1305},[1284],[1286,1307,1308],{},"Is a Vue SPA ever fine for LCP?",[15,1310,1311],{},"For authenticated apps where users arrive at a cached shell repeatedly, yes — a service worker or HTTP-cached bundle removes most of the download cost on repeat visits. For any landing page reached from search or ads, the first visit dominates, and an SPA cannot compete with server-rendered HTML.",[164,1313,1315],{"id":1314},"related","Related",[169,1317,1318,1325,1332],{},[172,1319,1320,1324],{},[19,1321,1323],{"href":1322},"\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Fwhy-the-lcp-element-changes-between-loads\u002F","Why the LCP element changes between loads"," — when hydration produces a second LCP candidate.",[172,1326,1327,1331],{},[19,1328,1330],{"href":1329},"\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002F","Vue & Nuxt performance"," — framework-level patterns beyond LCP.",[172,1333,1334,1338],{},[19,1335,1337],{"href":1336},"\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Fdiagnosing-lcp-resource-load-delay\u002F","Diagnosing LCP resource load delay"," — the phase most image fixes shrink.",[555,1340,1342],{"type":1341},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"How to Fix LCP Over 2.5s in Vue and Nuxt Apps\",\n  \"description\": \"The Vue- and Nuxt-specific reasons LCP misses 2.5s, from client-only hero components to oversized payloads, and the fixes for each.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Server-render the hero (or prerender the route)\",\n      \"text\": \"For a plain Vue SPA, the largest single win is rendering the above-the-fold HTML ahead of JavaScript — via Nuxt, vite-ssg for static routes, or prerendering marketing pages.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Make the hero image eager and high priority\",\n      \"text\": \"Expected outcome: the hero request starts during HTML parsing instead of after layout; load delay typically falls 200–600ms.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Trim the payload to what the template uses\",\n      \"text\": \"\u002F\u002F After: pick only the fields the page renders above and below the fold.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Fix hydration mismatches on the hero\",\n      \"text\": \"Mismatches in the hero (a date formatted differently on server and client, a random slide order, a viewport-dependent class) cause Vue to patch the DOM after hydration, which can produce a new, later LCP candidate.\"\n    }\n  ]\n}\n",[555,1344,1345],{"type":1341},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"How to Fix LCP Over 2.5s in Vue and Nuxt Apps\",\n  \"description\": \"The Vue- and Nuxt-specific reasons LCP misses 2.5s, from client-only hero components to oversized payloads, and the fixes for each.\",\n  \"datePublished\": \"2026-10-06\",\n  \"dateModified\": \"2026-10-06\",\n  \"author\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"mainEntityOfPage\": {\n    \"@type\": \"WebPage\",\n    \"@id\": \"https:\u002F\u002Ffrontend-performance.com\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Ffixing-slow-lcp-in-vue-and-nuxt-apps\u002F\"\n  }\n}\n",[555,1347,1348],{"type":1341},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"BreadcrumbList\",\n  \"itemListElement\": [\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 1,\n      \"name\": \"Home\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 2,\n      \"name\": \"Core Web Vitals & Measurement\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fcore-web-vitals-measurement\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"Measuring LCP with Chrome DevTools\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Fixing Slow LCP in Vue and Nuxt Apps\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Ffixing-slow-lcp-in-vue-and-nuxt-apps\u002F\"\n    }\n  ]\n}\n",[1350,1351,1352],"style",{},"html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}html pre.shiki code .smZ65, html code.shiki .smZ65{--shiki-default:#622CBC;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}html pre.shiki code .sZ8jY, html code.shiki .sZ8jY{--shiki-default:#032563;--shiki-dark:#ADDCFF;--shiki-light:#032563}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html pre.shiki code .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}html pre.shiki code .sZBmE, html code.shiki .sZBmE{--shiki-default:#024C1A;--shiki-dark:#72F088;--shiki-light:#024C1A}",{"title":464,"searchDepth":477,"depth":477,"links":1354},[1355,1356,1357,1363,1364,1365,1366],{"id":166,"depth":477,"text":167},{"id":239,"depth":477,"text":240},{"id":438,"depth":477,"text":439,"children":1358},[1359,1360,1361,1362],{"id":446,"depth":496,"text":447},{"id":660,"depth":496,"text":661},{"id":776,"depth":496,"text":777},{"id":983,"depth":496,"text":984},{"id":1075,"depth":477,"text":1076},{"id":1213,"depth":477,"text":1214},{"id":1278,"depth":477,"text":1279},{"id":1314,"depth":477,"text":1315},"The Vue- and Nuxt-specific reasons LCP misses 2.5s, from client-only hero components to oversized payloads, and the fixes for each.","md",{"slug":1370,"type":1371,"breadcrumb":1372,"datePublished":1380,"dateModified":1380},"fixing-slow-lcp-in-vue-and-nuxt-apps","article",[1373,1376,1377,1378],{"name":1374,"url":1375},"Home","\u002F",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":1379},"\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Ffixing-slow-lcp-in-vue-and-nuxt-apps\u002F","2026-10-06","\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Ffixing-slow-lcp-in-vue-and-nuxt-apps",{"title":13,"description":1383},"Diagnose slow LCP in Vue SPAs and Nuxt SSR apps — payload bloat, client-only heroes, lazy images and hydration — and apply fixes ordered by impact.","core-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Ffixing-slow-lcp-in-vue-and-nuxt-apps\u002Findex","OxLGw5bYImSh0X-PFI999iw8ufY1epJIFi3c9LtYbso",[1387,1391],{"title":1388,"path":1389,"stem":1390},"Fixing LCP When the H1 Is the LCP Element","\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Ffixing-lcp-when-the-h1-is-the-lcp-element","core-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Ffixing-lcp-when-the-h1-is-the-lcp-element\u002Findex",{"title":1392,"path":1393,"stem":1394},"Fix LCP Over 2.5s on React Apps","\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Fhow-to-fix-lcp-over-25-seconds-on-react-apps","core-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Fhow-to-fix-lcp-over-25-seconds-on-react-apps\u002Findex",1791308078347]