[{"data":1,"prerenderedAt":1277},["ShallowReactive",2],{"content:\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002Freducing-nuxt-payload-size":3,"surroundings:\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002Freducing-nuxt-payload-size":1268},{"id":4,"title":5,"body":6,"description":1247,"extension":1248,"meta":1249,"navigation":1261,"path":1262,"seo":1263,"stem":1266,"__hash__":1267},"content\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002Freducing-nuxt-payload-size\u002Findex.md","Reducing Nuxt Payload Size",{"type":7,"value":8,"toc":1229},"minimark",[9,14,42,45,133,138,174,178,184,190,196,202,206,211,352,356,363,367,433,437,440,567,571,574,578,581,585,591,595,601,894,1009,1013,1046,1050,1056,1062,1068,1074,1078,1090,1099,1113,1122,1131,1140,1149,1158,1167,1176,1188,1192,1214,1219,1222,1225],[10,11,13],"h1",{"id":12},"how-to-reduce-nuxt-payload-size","How to Reduce Nuxt Payload Size",[15,16,17,18,23,24,28,29,33,34,37,38,41],"p",{},"This guide is part of ",[19,20,22],"a",{"href":21},"\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002F","Vue & Nuxt Performance",", within ",[19,25,27],{"href":26},"\u002Fframework-performance\u002F","Framework Performance",". When Nuxt renders a page on the server, the results of ",[30,31,32],"code",{},"useFetch"," and ",[30,35,36],{},"useAsyncData"," (and state from ",[30,39,40],{},"useState"," and stores) are serialised into the HTML so the client can hydrate without fetching again. This payload is convenient and invisible — until it is hundreds of kilobytes. A product listing that fetches full product records, a blog index that fetches every post's full body, or a page that stores a whole API response in a store can ship more payload than HTML markup.",[15,43,44],{},"A large payload costs twice. It makes the HTML larger, delaying the arrival of content and critical resources referenced later in the document. And the client must parse and revive it into reactive state during hydration, adding main-thread time before the page responds to input.",[15,46,47],{},[48,49,55,56,55,63,55,67,55,70,55,79,55,85,55,92,55,100,55,105,55,109,55,114,55,118,55,122,55,129,55],"svg",{"viewBox":50,"width":51,"role":52,"ariaLabel":53,"style":54},"0 0 760 163","100%","img","Bar chart showing how much of the HTML response is markup versus serialized payload before and after trimming.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[57,58],"rect",{"className":59,"x":61,"y":61,"width":51,"height":51,"fill":62},[60],"svg-canvas","0","#ffffff",[64,65,66],"title",{},"HTML composition for a blog index page",[68,69,53],"desc",{},[57,71],{"x":72,"y":72,"width":73,"height":74,"rx":75,"fill":76,"stroke":77,"style":78},"1","758","161","10","none","currentColor","stroke-opacity:0.18",[80,81,66],"text",{"x":82,"y":83,"fill":77,"style":84},"28.0","34.0","font-size:16px;font-weight:700",[80,86,91],{"x":87,"y":88,"fill":77,"style":89,"textAnchor":90},"220.1","70.0","font-size:13px","end","Markup",[57,93],{"x":94,"y":95,"width":96,"height":97,"rx":98,"fill":77,"stroke":77,"style":99},"232.1","56.0","57.1","19","3","fill-opacity:0.7;stroke-opacity:0.4",[80,101,104],{"x":102,"y":88,"fill":77,"style":103},"295.2","font-size:12px;font-weight:600","38KB",[80,106,108],{"x":87,"y":107,"fill":77,"style":89,"textAnchor":90},"101.0","Payload before (full posts)",[57,110],{"x":94,"y":111,"width":112,"height":97,"rx":98,"fill":76,"stroke":77,"style":113},"87.0","435.9","fill-opacity:0.7;stroke-opacity:0.35",[80,115,117],{"x":116,"y":107,"fill":77,"style":103},"674.0","290KB",[80,119,121],{"x":87,"y":120,"fill":77,"style":89,"textAnchor":90},"132.0","Payload after (title, excerpt, slug)",[57,123],{"x":94,"y":124,"width":125,"height":97,"rx":98,"fill":126,"stroke":127,"style":128},"118.0","21.0","#ffc300","#b8860b","fill-opacity:0.7;stroke-opacity:0.9",[80,130,132],{"x":131,"y":120,"fill":77,"style":103},"259.2","14KB",[134,135,137],"h2",{"id":136},"rapid-diagnosis","Rapid Diagnosis",[139,140,141,153,159,168],"ul",{},[142,143,144,148,149,152],"li",{},[145,146,147],"strong",{},"View source"," and find the ",[30,150,151],{},"__NUXT_DATA__"," script; measure its size.",[142,154,155,158],{},[145,156,157],{},"Compare payload fields with rendered fields",": fields fetched but not displayed are waste.",[142,160,161,167],{},[145,162,163,164],{},"Check prerendered routes' ",[30,165,166],{},"_payload.json"," files in the build output.",[142,169,170,173],{},[145,171,172],{},"Check stores"," (Pinia) populated during SSR; their state is serialised too.",[134,175,177],{"id":176},"root-cause-analysis","Root Cause Analysis",[15,179,180,183],{},[145,181,182],{},"1. Whole API responses."," Endpoints return everything; pages use a fraction.",[15,185,186,189],{},[145,187,188],{},"2. Data for hidden UI."," Tabs, modals and below-the-fold sections fetched during SSR.",[15,191,192,195],{},[145,193,194],{},"3. Duplicated state."," The same data in a composable and a store.",[15,197,198,201],{},[145,199,200],{},"4. Large nested structures."," Reviews, variants and related items embedded in each record.",[134,203,205],{"id":204},"step-by-step-resolution","Step-by-Step Resolution",[207,208,210],"h3",{"id":209},"_1-pick-or-transform-fetched-data","1. Pick or transform fetched data",[212,213,218],"pre",{"className":214,"code":215,"language":216,"meta":217,"style":217},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","const { data: posts } = await useAsyncData('posts', () => $fetch('\u002Fapi\u002Fposts'), {\n  transform: (list) => list.map(({ slug, title, excerpt, date }) => ({ slug, title, excerpt, date })),\n});\n\u002F\u002F trade-off: transform runs on the server before serialisation, but the server still\n\u002F\u002F downloads the full response; trimming at the API is better when you control it.\n","javascript","",[30,219,220,281,333,339,346],{"__ignoreMap":217},[221,222,225,229,233,237,240,244,247,250,253,257,260,264,267,270,273,275,278],"span",{"class":223,"line":224},"line",1,[221,226,228],{"class":227},"sPARh","const",[221,230,232],{"class":231},"saISM"," { ",[221,234,236],{"class":235},"sQw3B","data",[221,238,239],{"class":231},": ",[221,241,243],{"class":242},"sPXB4","posts",[221,245,246],{"class":231}," } ",[221,248,249],{"class":227},"=",[221,251,252],{"class":227}," await",[221,254,256],{"class":255},"smZ65"," useAsyncData",[221,258,259],{"class":231},"(",[221,261,263],{"class":262},"sZ8jY","'posts'",[221,265,266],{"class":231},", () ",[221,268,269],{"class":227},"=>",[221,271,272],{"class":255}," $fetch",[221,274,259],{"class":231},[221,276,277],{"class":262},"'\u002Fapi\u002Fposts'",[221,279,280],{"class":231},"), {\n",[221,282,284,287,290,293,296,298,301,304,307,310,313,315,317,320,322,325,328,330],{"class":223,"line":283},2,[221,285,286],{"class":255},"  transform",[221,288,289],{"class":231},": (",[221,291,292],{"class":235},"list",[221,294,295],{"class":231},") ",[221,297,269],{"class":227},[221,299,300],{"class":231}," list.",[221,302,303],{"class":255},"map",[221,305,306],{"class":231},"(({ ",[221,308,309],{"class":235},"slug",[221,311,312],{"class":231},", ",[221,314,64],{"class":235},[221,316,312],{"class":231},[221,318,319],{"class":235},"excerpt",[221,321,312],{"class":231},[221,323,324],{"class":235},"date",[221,326,327],{"class":231}," }) ",[221,329,269],{"class":227},[221,331,332],{"class":231}," ({ slug, title, excerpt, date })),\n",[221,334,336],{"class":223,"line":335},3,[221,337,338],{"class":231},"});\n",[221,340,342],{"class":223,"line":341},4,[221,343,345],{"class":344},"sjfSM","\u002F\u002F trade-off: transform runs on the server before serialisation, but the server still\n",[221,347,349],{"class":223,"line":348},5,[221,350,351],{"class":344},"\u002F\u002F downloads the full response; trimming at the API is better when you control it.\n",[207,353,355],{"id":354},"_2-return-lean-data-from-server-routes","2. Return lean data from server routes",[15,357,358,359,362],{},"Create Nuxt server routes (",[30,360,361],{},"server\u002Fapi\u002F*.ts",") that query or reshape upstream data and return only the fields pages need.",[207,364,366],{"id":365},"_3-fetch-non-critical-data-lazily-on-the-client","3. Fetch non-critical data lazily on the client",[212,368,370],{"className":214,"code":369,"language":216,"meta":217,"style":217},"const { data: reviews, pending } = useFetch(`\u002Fapi\u002Fproducts\u002F${id}\u002Freviews`, { lazy: true, server: false });\n\u002F\u002F trade-off: server: false keeps reviews out of the payload and SSR HTML; they render\n\u002F\u002F after hydration, so reserve space to avoid layout shifts and accept no SSR for them.\n",[30,371,372,423,428],{"__ignoreMap":217},[221,373,374,376,378,380,382,385,387,390,392,394,397,399,402,405,408,411,414,417,420],{"class":223,"line":224},[221,375,228],{"class":227},[221,377,232],{"class":231},[221,379,236],{"class":235},[221,381,239],{"class":231},[221,383,384],{"class":242},"reviews",[221,386,312],{"class":231},[221,388,389],{"class":242},"pending",[221,391,246],{"class":231},[221,393,249],{"class":227},[221,395,396],{"class":255}," useFetch",[221,398,259],{"class":231},[221,400,401],{"class":262},"`\u002Fapi\u002Fproducts\u002F${",[221,403,404],{"class":231},"id",[221,406,407],{"class":262},"}\u002Freviews`",[221,409,410],{"class":231},", { lazy: ",[221,412,413],{"class":242},"true",[221,415,416],{"class":231},", server: ",[221,418,419],{"class":242},"false",[221,421,422],{"class":231}," });\n",[221,424,425],{"class":223,"line":283},[221,426,427],{"class":344},"\u002F\u002F trade-off: server: false keeps reviews out of the payload and SSR HTML; they render\n",[221,429,430],{"class":223,"line":335},[221,431,432],{"class":344},"\u002F\u002F after hydration, so reserve space to avoid layout shifts and accept no SSR for them.\n",[207,434,436],{"id":435},"_4-avoid-duplicating-state","4. Avoid duplicating state",[15,438,439],{},"Store data once — either in the composable result or a store — and derive views with computed properties.",[15,441,442,494,55,497,55,501],{},[48,443,55,446,55,449,55,452,55,454,55,471,55,474,55,476,55,483,55,490],{"viewBox":444,"width":51,"role":52,"ariaLabel":445,"style":54},"0 0 760 149","Steps to measure and reduce the serialized Nuxt payload.",[57,447],{"className":448,"x":61,"y":61,"width":51,"height":51,"fill":62},[60],[64,450,451],{},"Payload reduction workflow",[68,453,445],{},[455,456,457],"defs",{},[458,459,466],"marker",{"id":460,"viewBox":461,"refX":462,"refY":463,"markerWidth":464,"markerHeight":464,"orient":465},"fab16a836c","0 0 10 10","9","5","7","auto-start-reverse",[467,468],"path",{"d":469,"fill":77,"style":470},"M0 0 L10 5 L0 10 z","fill-opacity:0.7",[57,472],{"x":72,"y":72,"width":73,"height":473,"rx":75,"fill":76,"stroke":77,"style":78},"147",[80,475,451],{"x":82,"y":83,"fill":77,"style":84},[57,477],{"x":82,"y":95,"width":478,"height":479,"rx":480,"fill":481,"stroke":481,"style":482},"108.8","71.0","6","#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[80,484,489],{"x":485,"y":486,"fill":77,"style":487,"textAnchor":488},"82.4","78.0","font-size:13px;font-weight:700","middle","Measure",[80,491],{"x":485,"y":492,"fill":77,"style":493,"textAnchor":488},"96.0","font-size:12px",[145,495,496],{},"NUXT_DATA",[80,498,500],{"x":485,"y":499,"fill":77,"style":493,"text-anchor":488},"112.0","size",[57,502,55,506,55,510,55,513,55,516],{"x":503,"y":95,"width":504,"height":505,"rx":480,"fill":481,"stroke":481,"style":482},"176.8",108.8,71,[80,507,509],{"x":508,"y":486,"fill":77,"style":487,"text-anchor":488},"231.2","Compare",[80,511,512],{"x":508,"y":492,"fill":77,"style":493,"text-anchor":488},"fetched vs",[80,514,515],{"x":508,"y":499,"fill":77,"style":493,"text-anchor":488},"rendered fields",[57,517,55,520,55,524,55,527],{"x":518,"y":95,"width":504,"height":505,"rx":480,"fill":126,"stroke":127,"style":519},"325.6","fill-opacity:0.24;stroke-opacity:0.9",[80,521,523],{"x":522,"y":486,"fill":77,"style":487,"text-anchor":488},"380.0","Trim",[80,525,526],{"x":522,"y":492,"fill":77,"style":493,"text-anchor":488},"pick \u002F transform",[57,528,55,530,55,534,55,537],{"x":529,"y":95,"width":504,"height":505,"rx":480,"fill":481,"stroke":481,"style":482},"474.4",[80,531,533],{"x":532,"y":486,"fill":77,"style":487,"text-anchor":488},"528.8","Lean APIs",[80,535,536],{"x":532,"y":492,"fill":77,"style":493,"text-anchor":488},"server routes",[57,538,55,540,55,544,55,547],{"x":539,"y":95,"width":504,"height":505,"rx":480,"fill":481,"stroke":481,"style":482},"623.2",[80,541,543],{"x":542,"y":486,"fill":77,"style":487,"text-anchor":488},"677.6","Defer",[80,545,546],{"x":542,"y":492,"fill":77,"style":493,"text-anchor":488},"lazy, server false",[223,548,55,555],{"x1":549,"y1":550,"x2":551,"y2":550,"stroke":77,"stroke-width":552,"style":553,"marker-end":554},"136.8","91.5","174.8","1.5","stroke-opacity:0.6","url(#fab16a836c)",[223,556,55,559],{"x1":557,"y1":550,"x2":558,"y2":550,"stroke":77,"stroke-width":552,"style":553,"marker-end":554},"285.6","323.6",[223,560,55,563],{"x1":561,"y1":550,"x2":562,"y2":550,"stroke":77,"stroke-width":552,"style":553,"marker-end":554},"434.4","472.4",[223,564,55],{"x1":565,"y1":550,"x2":566,"y2":550,"stroke":77,"stroke-width":552,"style":553,"marker-end":554},"583.2","621.2",[134,568,570],{"id":569},"verification","Verification",[15,572,573],{},"Measure the payload again on the same pages: it should shrink substantially. Compare HTML transfer size, hydration time in a throttled trace, and field LCP and INP for the routes. Check that pages still render correctly when navigating client-side (data shape changes can break components).",[134,575,577],{"id":576},"worked-example-a-recipe-platform","Worked Example: A Recipe Platform",[15,579,580],{},"A recipe platform's category pages fetched 30 full recipes (ingredients, steps, nutrition, comments) to render cards with a title, image, rating and cooking time. The payload was 520KB per page, and hydration took 700ms on mid-range phones. A server route returning card fields only reduced the payload to 22KB. Comments were already loaded lazily on recipe pages but were also fetched during SSR on category pages through a shared composable, which was fixed. HTML transfer fell by 80%, LCP p75 improved by 400ms (the hero image reference arrived earlier), and hydration dropped to 160ms.",[134,582,584],{"id":583},"payload-extraction-for-prerendered-routes","Payload Extraction for Prerendered Routes",[15,586,587,588,590],{},"For prerendered and cached routes, Nuxt can extract the payload into a separate ",[30,589,166],{}," file. On client-side navigation to those routes, only the JSON is fetched — not the whole HTML — and it can be cached. This reduces navigation cost for static content. The HTML still includes inline payload for the first load. Payload extraction is enabled by default for prerendered routes in recent Nuxt versions; check that it applies to your SWR or ISR routes if you rely on them.",[134,592,594],{"id":593},"measuring-payload-in-ci","Measuring Payload in CI",[15,596,597,598,600],{},"Payload growth is gradual: a new field here, a related-items list there. Add a CI check that renders key pages (or reads prerendered output) and asserts payload size stays under a budget. A simple script can fetch the page from a preview deployment, extract the ",[30,599,151],{}," script and compare its byte length against limits per template. Reporting the top keys by size makes it easy to see which data grew.",[212,602,604],{"className":214,"code":603,"language":216,"meta":217,"style":217},"\u002F\u002F scripts\u002Fpayload-budget.mjs\nconst budgets = { '\u002F': 30_000, '\u002Fblog\u002F': 40_000, '\u002Fproducts\u002Fshoes\u002F': 60_000 };\nfor (const [path, max] of Object.entries(budgets)) {\n  const html = await (await fetch(process.env.PREVIEW_URL + path)).text();\n  const m = html.match(\u002F\u003Cscript[^>]*id=\"__NUXT_DATA__\"[^>]*>([\\s\\S]*?)\u003C\\\u002Fscript>\u002F);\n  const size = m ? m[1].length : 0;\n  if (size > max) { console.error(`${path}: payload ${size} B > ${max} B`); process.exitCode = 1; }\n}\n\u002F\u002F trade-off: byte length of the serialised script approximates its cost; HTML is\n\u002F\u002F compressed in transfer, but parsing and reviving scale with the raw size.\n",[30,605,606,611,654,689,726,791,827,876,882,888],{"__ignoreMap":217},[221,607,608],{"class":223,"line":224},[221,609,610],{"class":344},"\u002F\u002F scripts\u002Fpayload-budget.mjs\n",[221,612,613,615,618,621,623,626,628,631,633,636,638,641,643,646,648,651],{"class":223,"line":283},[221,614,228],{"class":227},[221,616,617],{"class":242}," budgets",[221,619,620],{"class":227}," =",[221,622,232],{"class":231},[221,624,625],{"class":262},"'\u002F'",[221,627,239],{"class":231},[221,629,630],{"class":242},"30_000",[221,632,312],{"class":231},[221,634,635],{"class":262},"'\u002Fblog\u002F'",[221,637,239],{"class":231},[221,639,640],{"class":242},"40_000",[221,642,312],{"class":231},[221,644,645],{"class":262},"'\u002Fproducts\u002Fshoes\u002F'",[221,647,239],{"class":231},[221,649,650],{"class":242},"60_000",[221,652,653],{"class":231}," };\n",[221,655,656,659,662,664,667,669,671,674,677,680,683,686],{"class":223,"line":335},[221,657,658],{"class":227},"for",[221,660,661],{"class":231}," (",[221,663,228],{"class":227},[221,665,666],{"class":231}," [",[221,668,467],{"class":242},[221,670,312],{"class":231},[221,672,673],{"class":242},"max",[221,675,676],{"class":231},"] ",[221,678,679],{"class":227},"of",[221,681,682],{"class":231}," Object.",[221,684,685],{"class":255},"entries",[221,687,688],{"class":231},"(budgets)) {\n",[221,690,691,694,697,699,701,703,706,709,712,715,718,721,723],{"class":223,"line":341},[221,692,693],{"class":227},"  const",[221,695,696],{"class":242}," html",[221,698,620],{"class":227},[221,700,252],{"class":227},[221,702,661],{"class":231},[221,704,705],{"class":227},"await",[221,707,708],{"class":255}," fetch",[221,710,711],{"class":231},"(process.env.",[221,713,714],{"class":242},"PREVIEW_URL",[221,716,717],{"class":227}," +",[221,719,720],{"class":231}," path)).",[221,722,80],{"class":255},[221,724,725],{"class":231},"();\n",[221,727,728,730,733,735,738,741,743,746,749,752,755,758,761,763,765,767,769,772,775,778,781,785,788],{"class":223,"line":348},[221,729,693],{"class":227},[221,731,732],{"class":242}," m",[221,734,620],{"class":227},[221,736,737],{"class":231}," html.",[221,739,740],{"class":255},"match",[221,742,259],{"class":231},[221,744,745],{"class":262},"\u002F\u003Cscript",[221,747,748],{"class":242},"[",[221,750,751],{"class":227},"^",[221,753,754],{"class":242},">]",[221,756,757],{"class":227},"*",[221,759,760],{"class":262},"id=\"__NUXT_DATA__\"",[221,762,748],{"class":242},[221,764,751],{"class":227},[221,766,754],{"class":242},[221,768,757],{"class":227},[221,770,771],{"class":262},">(",[221,773,774],{"class":242},"[\\s\\S]",[221,776,777],{"class":227},"*?",[221,779,780],{"class":262},")\u003C",[221,782,784],{"class":783},"sn2CQ","\\\u002F",[221,786,787],{"class":262},"script>\u002F",[221,789,790],{"class":231},");\n",[221,792,794,796,799,801,804,807,810,812,815,818,821,824],{"class":223,"line":793},6,[221,795,693],{"class":227},[221,797,798],{"class":242}," size",[221,800,620],{"class":227},[221,802,803],{"class":231}," m ",[221,805,806],{"class":227},"?",[221,808,809],{"class":231}," m[",[221,811,72],{"class":242},[221,813,814],{"class":231},"].",[221,816,817],{"class":242},"length",[221,819,820],{"class":227}," :",[221,822,823],{"class":242}," 0",[221,825,826],{"class":231},";\n",[221,828,830,833,836,839,842,845,847,850,852,855,857,860,862,865,868,870,873],{"class":223,"line":829},7,[221,831,832],{"class":227},"  if",[221,834,835],{"class":231}," (size ",[221,837,838],{"class":227},">",[221,840,841],{"class":231}," max) { console.",[221,843,844],{"class":255},"error",[221,846,259],{"class":231},[221,848,849],{"class":262},"`${",[221,851,467],{"class":231},[221,853,854],{"class":262},"}: payload ${",[221,856,500],{"class":231},[221,858,859],{"class":262},"} B > ${",[221,861,673],{"class":231},[221,863,864],{"class":262},"} B`",[221,866,867],{"class":231},"); process.exitCode ",[221,869,249],{"class":227},[221,871,872],{"class":242}," 1",[221,874,875],{"class":231},"; }\n",[221,877,879],{"class":223,"line":878},8,[221,880,881],{"class":231},"}\n",[221,883,885],{"class":223,"line":884},9,[221,886,887],{"class":344},"\u002F\u002F trade-off: byte length of the serialised script approximates its cost; HTML is\n",[221,889,891],{"class":223,"line":890},10,[221,892,893],{"class":344},"\u002F\u002F compressed in transfer, but parsing and reviving scale with the raw size.\n",[15,895,896],{},[48,897,55,900,55,903,55,906,55,908,55,911,55,913,55,918,55,925,55,929,55,933,55,936,55,940,55,944,55,948,55,950,55,953,55,955,55,958,55,961,55,965,55,967,55,970,55,972,55,975,55,978,55,982,55,984,55,987,55,989,55,992,55,995,55,999,55,1001,55,1004,55,1006,55],{"viewBox":898,"width":51,"role":52,"ariaLabel":899,"style":54},"0 0 760 228","Common sources of oversized Nuxt payloads and the usual fix.",[57,901],{"className":902,"x":61,"y":61,"width":51,"height":51,"fill":62},[60],[64,904,905],{},"Where payload bloat comes from",[68,907,899],{},[57,909],{"x":72,"y":72,"width":73,"height":910,"rx":75,"fill":76,"stroke":77,"style":78},"226",[80,912,905],{"x":82,"y":83,"fill":77,"style":84},[57,914],{"x":82,"y":95,"width":915,"height":916,"rx":61,"fill":77,"stroke":77,"style":917},"118.2","30.0","fill-opacity:0.06;stroke-opacity:0.4",[80,919,924],{"x":920,"y":921,"fill":77,"style":922,"textAnchor":923},"38.0","75.5","font-size:12.5px;font-weight:700","start","Source",[57,926],{"x":927,"y":95,"width":928,"height":916,"rx":61,"fill":77,"stroke":77,"style":917},"146.2","292.9",[80,930,932],{"x":931,"y":921,"fill":77,"style":922,"textAnchor":488},"292.7","Example",[57,934],{"x":935,"y":95,"width":928,"height":916,"rx":61,"fill":77,"stroke":77,"style":917},"439.1",[80,937,939],{"x":938,"y":921,"fill":77,"style":922,"textAnchor":488},"585.6","Fix",[57,941],{"x":82,"y":942,"width":915,"height":916,"rx":61,"fill":76,"stroke":77,"style":943},"86.0","stroke-opacity:0.35",[80,945,947],{"x":920,"y":946,"fill":77,"style":922,"textAnchor":923},"105.5","Whole records",[57,949],{"x":927,"y":942,"width":928,"height":916,"rx":61,"fill":76,"stroke":77,"style":943},[80,951,952],{"x":931,"y":946,"fill":77,"style":493,"textAnchor":488},"full product objects for cards",[57,954],{"x":935,"y":942,"width":928,"height":916,"rx":61,"fill":76,"stroke":77,"style":943},[80,956,957],{"x":938,"y":946,"fill":77,"style":493,"textAnchor":488},"transform to card fields",[57,959],{"x":82,"y":960,"width":915,"height":916,"rx":61,"fill":76,"stroke":77,"style":943},"116.0",[80,962,964],{"x":920,"y":963,"fill":77,"style":922,"textAnchor":923},"135.5","Hidden UI data",[57,966],{"x":927,"y":960,"width":928,"height":916,"rx":61,"fill":76,"stroke":77,"style":943},[80,968,969],{"x":931,"y":963,"fill":77,"style":493,"textAnchor":488},"reviews for a closed tab",[57,971],{"x":935,"y":960,"width":928,"height":916,"rx":61,"fill":76,"stroke":77,"style":943},[80,973,974],{"x":938,"y":963,"fill":77,"style":493,"textAnchor":488},"lazy, server: false",[57,976],{"x":82,"y":977,"width":915,"height":916,"rx":61,"fill":76,"stroke":77,"style":943},"146.0",[80,979,981],{"x":920,"y":980,"fill":77,"style":922,"textAnchor":923},"165.5","Store duplication",[57,983],{"x":927,"y":977,"width":928,"height":916,"rx":61,"fill":76,"stroke":77,"style":943},[80,985,986],{"x":931,"y":980,"fill":77,"style":493,"textAnchor":488},"same list in store and composable",[57,988],{"x":935,"y":977,"width":928,"height":916,"rx":61,"fill":76,"stroke":77,"style":943},[80,990,991],{"x":938,"y":980,"fill":77,"style":493,"textAnchor":488},"single source of truth",[57,993],{"x":82,"y":994,"width":915,"height":916,"rx":61,"fill":76,"stroke":77,"style":943},"176.0",[80,996,998],{"x":920,"y":997,"fill":77,"style":922,"textAnchor":923},"195.5","Nested relations",[57,1000],{"x":927,"y":994,"width":928,"height":916,"rx":61,"fill":76,"stroke":77,"style":943},[80,1002,1003],{"x":931,"y":997,"fill":77,"style":493,"textAnchor":488},"related items inside each item",[57,1005],{"x":935,"y":994,"width":928,"height":916,"rx":61,"fill":76,"stroke":77,"style":943},[80,1007,1008],{"x":938,"y":997,"fill":77,"style":493,"textAnchor":488},"separate lazy fetch",[134,1010,1012],{"id":1011},"common-mistakes","Common Mistakes",[139,1014,1015,1028,1034,1040],{},[142,1016,1017,55,1020,1023,1024,1027],{},[145,1018,1019],{},"Trusting that pick handles nesting.",[30,1021,1022],{},"pick"," works on top-level keys; use ",[30,1025,1026],{},"transform"," for deeper shaping.",[142,1029,1030,1033],{},[145,1031,1032],{},"Fetching below-the-fold data on the server."," It goes into the payload and delays HTML.",[142,1035,1036,1039],{},[145,1037,1038],{},"Large store state."," Pinia state populated during SSR is serialised in full.",[142,1041,1042,1045],{},[145,1043,1044],{},"Changing data shapes without updating components."," Client navigations break.",[134,1047,1049],{"id":1048},"edge-cases","Edge Cases",[15,1051,1052,1055],{},[145,1053,1054],{},"SEO-critical content."," Data needed for indexable content must be rendered on the server; trim fields, do not defer them.",[15,1057,1058,1061],{},[145,1059,1060],{},"Dates and special types."," Serialisation handles many types, but custom classes lose their prototypes; transform to plain data.",[15,1063,1064,1067],{},[145,1065,1066],{},"Large static data."," Constants (country lists, config) can be imported in code instead of fetched and serialised.",[15,1069,1070,1073],{},[145,1071,1072],{},"Payload on error pages."," Errors can serialise unexpected data; check error page payloads too.",[134,1075,1077],{"id":1076},"faq","FAQ",[1079,1080,1083,1087],"details",{"className":1081},[1082],"faq-item",[1084,1085,1086],"summary",{},"What is __NUXT_DATA__?",[15,1088,1089],{},"The script element containing the serialised payload Nuxt uses to hydrate the client without refetching data.",[1079,1091,1093,1096],{"className":1092},[1082],[1084,1094,1095],{},"Does payload size affect LCP?",[15,1097,1098],{},"It can. A large payload makes the HTML larger, delaying content and resource references that come after it, and adds hydration work.",[1079,1100,1102,1105],{"className":1101},[1082],[1084,1103,1104],{},"What is the difference between pick and transform?",[15,1106,1107,1109,1110,1112],{},[30,1108,1022],{}," keeps selected top-level keys of the result. ",[30,1111,1026],{}," runs a function on the result, allowing any reshaping.",[1079,1114,1116,1119],{"className":1115},[1082],[1084,1117,1118],{},"Should I use server: false for all non-critical data?",[15,1120,1121],{},"For data below the fold or behind interactions, often yes. It removes the data from SSR and the payload, at the cost of rendering it after hydration.",[1079,1123,1125,1128],{"className":1124},[1082],[1084,1126,1127],{},"Is Pinia state part of the payload?",[15,1129,1130],{},"Yes, state populated during server rendering is serialised for hydration. Keep store state lean.",[1079,1132,1134,1137],{"className":1133},[1082],[1084,1135,1136],{},"How large should a payload be?",[15,1138,1139],{},"As small as the page allows — tens of kilobytes for content pages is reasonable. Hundreds of kilobytes usually signals overfetching.",[1079,1141,1143,1146],{"className":1142},[1082],[1084,1144,1145],{},"Does payload extraction help the first load?",[15,1147,1148],{},"No. It helps client-side navigations to prerendered routes by fetching a small JSON file instead of the full HTML.",[1079,1150,1152,1155],{"className":1151},[1082],[1084,1153,1154],{},"Can I compress the payload further?",[15,1156,1157],{},"The HTML is compressed in transfer already. Reducing the data itself matters more, because parsing and reviving costs scale with raw size.",[1079,1159,1161,1164],{"className":1160},[1082],[1084,1162,1163],{},"Can I see payload contents in development?",[15,1165,1166],{},"Yes. Nuxt DevTools shows payload and state contents, which makes it easy to spot oversized data during development.",[1079,1168,1170,1173],{"className":1169},[1082],[1084,1171,1172],{},"Do prerendered pages still include a payload?",[15,1174,1175],{},"Yes, inline for the first load and, with payload extraction, as a separate JSON file for client-side navigations.",[1079,1177,1179,1182],{"className":1178},[1082],[1084,1180,1181],{},"Does useState add to the payload?",[15,1183,1184,1185,1187],{},"Yes. State created with ",[30,1186,40],{}," during server rendering is serialised; keep it small.",[134,1189,1191],{"id":1190},"related","Related",[139,1193,1194,1201,1208],{},[142,1195,1196,1200],{},[19,1197,1199],{"href":1198},"\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002Flazy-hydration-in-nuxt\u002F","Lazy hydration in Nuxt"," — less hydration work.",[142,1202,1203,1207],{},[19,1204,1206],{"href":1205},"\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002Fnuxt-route-rules-for-hybrid-rendering\u002F","Nuxt route rules for hybrid rendering"," — caching payload-heavy routes.",[142,1209,1210,1213],{},[19,1211,1212],{"href":21},"Vue & Nuxt performance"," — the topic overview.",[1215,1216,1218],"script",{"type":1217},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"How to Reduce Nuxt Payload Size\",\n  \"description\": \"How the Nuxt payload works, how to measure it, and the techniques that keep it small so HTML transfers faster and hydration is cheaper.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Pick or transform fetched data\",\n      \"text\": \"Pick or transform fetched data\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Return lean data from server routes\",\n      \"text\": \"Create Nuxt server routes (server\u002Fapi\u002F*.ts) that query or reshape upstream data and return only the fields pages need.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Fetch non-critical data lazily on the client\",\n      \"text\": \"Fetch non-critical data lazily on the client\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Avoid duplicating state\",\n      \"text\": \"Store data once — either in the composable result or a store — and derive views with computed properties.\"\n    }\n  ]\n}\n",[1215,1220,1221],{"type":1217},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"How to Reduce Nuxt Payload Size\",\n  \"description\": \"How the Nuxt payload works, how to measure it, and the techniques that keep it small so HTML transfers faster and hydration is cheaper.\",\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\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002Freducing-nuxt-payload-size\u002F\"\n  }\n}\n",[1215,1223,1224],{"type":1217},"\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\": \"Framework Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"Vue & Nuxt Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Reducing Nuxt Payload Size\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002Freducing-nuxt-payload-size\u002F\"\n    }\n  ]\n}\n",[1226,1227,1228],"style",{},"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 .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}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 pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}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 .sn2CQ, html code.shiki .sn2CQ{--shiki-default:#024C1A;--shiki-default-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold;--shiki-light:#024C1A;--shiki-light-font-weight:bold}",{"title":217,"searchDepth":283,"depth":283,"links":1230},[1231,1232,1233,1239,1240,1241,1242,1243,1244,1245,1246],{"id":136,"depth":283,"text":137},{"id":176,"depth":283,"text":177},{"id":204,"depth":283,"text":205,"children":1234},[1235,1236,1237,1238],{"id":209,"depth":335,"text":210},{"id":354,"depth":335,"text":355},{"id":365,"depth":335,"text":366},{"id":435,"depth":335,"text":436},{"id":569,"depth":283,"text":570},{"id":576,"depth":283,"text":577},{"id":583,"depth":283,"text":584},{"id":593,"depth":283,"text":594},{"id":1011,"depth":283,"text":1012},{"id":1048,"depth":283,"text":1049},{"id":1076,"depth":283,"text":1077},{"id":1190,"depth":283,"text":1191},"How the Nuxt payload works, how to measure it, and the techniques that keep it small so HTML transfers faster and hydration is cheaper.","md",{"slug":1250,"type":1251,"breadcrumb":1252,"datePublished":1260,"dateModified":1260},"reducing-nuxt-payload-size","article",[1253,1256,1257,1258],{"name":1254,"url":1255},"Home","\u002F",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":1259},"\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002Freducing-nuxt-payload-size\u002F","2026-10-06",true,"\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002Freducing-nuxt-payload-size",{"title":1264,"description":1265},"Reducing Nuxt Payload Size for Faster Hydration","Shrink the serialized Nuxt payload: pick and transform useFetch data, return lean server routes, avoid duplicate state, and use lazy fetching for non-critical data.","framework-performance\u002Fvue-and-nuxt-performance\u002Freducing-nuxt-payload-size\u002Findex","qCDNW25gqWIKsGjGy4zkdT7jeftOCL0KnzfTzW5lAqU",[1269,1273],{"title":1270,"path":1271,"stem":1272},"Nuxt Route Rules for Hybrid Rendering","\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002Fnuxt-route-rules-for-hybrid-rendering","framework-performance\u002Fvue-and-nuxt-performance\u002Fnuxt-route-rules-for-hybrid-rendering\u002Findex",{"title":1274,"path":1275,"stem":1276},"Image & Media Optimization","\u002Fimage-media-optimization","image-media-optimization\u002Findex",1791308072251]