[{"data":1,"prerenderedAt":1307},["ShallowReactive",2],{"content:\u002Fframework-performance\u002Fastro-and-sveltekit-performance":3,"surroundings:\u002Fframework-performance\u002Fastro-and-sveltekit-performance":1298},{"id":4,"title":5,"body":6,"description":1278,"extension":1279,"meta":1280,"navigation":1291,"path":1292,"seo":1293,"stem":1296,"__hash__":1297},"content\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002Findex.md","Astro & SvelteKit Performance",{"type":7,"value":8,"toc":1254},"minimark",[9,14,55,69,78,216,221,248,252,272,276,293,297,300,304,311,315,333,505,586,590,593,596,600,606,612,618,630,641,645,648,713,717,729,848,852,870,874,885,889,916,920,931,935,956,960,991,995,998,1002,1009,1013,1045,1049,1061,1070,1079,1092,1101,1110,1119,1128,1137,1146,1155,1168,1177,1186,1190,1213,1217,1239,1244,1247,1250],[10,11,13],"h1",{"id":12},"astro-sveltekit-performance-shipping-less-loading-smarter","Astro & SvelteKit Performance: Shipping Less, Loading Smarter",[15,16,17,18,23,24,28,29,32,33,36,37,41,42,41,45,41,48,41,51,54],"p",{},"This topic is part of ",[19,20,22],"a",{"href":21},"\u002Fframework-performance\u002F","Framework Performance",". Astro and SvelteKit approach performance from different angles, and both start from strong defaults. ",[25,26,27],"strong",{},"Astro"," renders pages to static HTML (at build time or on the server) and ships zero JavaScript by default. Interactive components — written in React, Vue, Svelte, Solid or others — are added as ",[25,30,31],{},"islands",", each hydrated independently according to a ",[25,34,35],{},"client directive"," (",[38,39,40],"code",{},"client:load",", ",[38,43,44],{},"client:idle",[38,46,47],{},"client:visible",[38,49,50],{},"client:media",[38,52,53],{},"client:only","). A content page with one interactive widget ships the JavaScript for that widget only.",[15,56,57,60,61,64,65,68],{},[25,58,59],{},"SvelteKit"," compiles Svelte components into small, efficient JavaScript that updates the DOM directly without a virtual DOM, server-renders by default, and provides ",[38,62,63],{},"load"," functions for data, streaming of promises, and ",[25,66,67],{},"preloading"," of code and data on link hover or tap. Its runtime is small, and its router makes client-side navigations fast.",[15,70,71,72,74,75,77],{},"Both frameworks can still be slowed down: too many islands with ",[38,73,40],{},", heavy UI libraries inside islands, server rendering where prerendering would do, data waterfalls in ",[38,76,63],{}," functions, and images and fonts configured poorly. This topic covers how to use each framework's tools to keep pages fast, and how to choose between them for content-heavy sites.",[15,79,80],{},[81,82,88,89,88,96,88,100,88,103,88,112,88,118,88,124,88,131,88,135,88,139,88,142,88,145,88,149,88,153,88,157,88,160,88,162,88,165,88,168,88,172,88,174,88,177,88,179,88,182,88,185,88,189,88,191,88,194,88,196,88,199,88,202,88,206,88,208,88,211,88,213,88],"svg",{"viewBox":83,"width":84,"role":85,"ariaLabel":86,"style":87},"0 0 760 228","100%","img","Comparison of Astro and SvelteKit on default JavaScript, interactivity model, routing and best fit.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[90,91],"rect",{"className":92,"x":94,"y":94,"width":84,"height":84,"fill":95},[93],"svg-canvas","0","#ffffff",[97,98,99],"title",{},"Astro vs SvelteKit at a glance",[101,102,86],"desc",{},[90,104],{"x":105,"y":105,"width":106,"height":107,"rx":108,"fill":109,"stroke":110,"style":111},"1","758","226","10","none","currentColor","stroke-opacity:0.18",[113,114,99],"text",{"x":115,"y":116,"fill":110,"style":117},"28.0","34.0","font-size:16px;font-weight:700",[90,119],{"x":115,"y":120,"width":121,"height":122,"rx":94,"fill":110,"stroke":110,"style":123},"56.0","128.3","30.0","fill-opacity:0.06;stroke-opacity:0.4",[113,125,130],{"x":126,"y":127,"fill":110,"style":128,"textAnchor":129},"38.0","75.5","font-size:12.5px;font-weight:700","start","Aspect",[90,132],{"x":133,"y":120,"width":134,"height":122,"rx":94,"fill":110,"stroke":110,"style":123},"156.3","287.8",[113,136,27],{"x":137,"y":127,"fill":110,"style":128,"textAnchor":138},"300.2","middle",[90,140],{"x":141,"y":120,"width":134,"height":122,"rx":94,"fill":110,"stroke":110,"style":123},"444.2",[113,143,59],{"x":144,"y":127,"fill":110,"style":128,"textAnchor":138},"588.1",[90,146],{"x":115,"y":147,"width":121,"height":122,"rx":94,"fill":109,"stroke":110,"style":148},"86.0","stroke-opacity:0.35",[113,150,152],{"x":126,"y":151,"fill":110,"style":128,"textAnchor":129},"105.5","Default client JS",[90,154],{"x":133,"y":147,"width":134,"height":122,"rx":94,"fill":155,"stroke":155,"style":156},"#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[113,158,109],{"x":137,"y":151,"fill":110,"style":159,"textAnchor":138},"font-size:12px",[90,161],{"x":141,"y":147,"width":134,"height":122,"rx":94,"fill":110,"stroke":110,"style":123},[113,163,164],{"x":144,"y":151,"fill":110,"style":159,"textAnchor":138},"small runtime + components",[90,166],{"x":115,"y":167,"width":121,"height":122,"rx":94,"fill":109,"stroke":110,"style":148},"116.0",[113,169,171],{"x":126,"y":170,"fill":110,"style":128,"textAnchor":129},"135.5","Interactivity model",[90,173],{"x":133,"y":167,"width":134,"height":122,"rx":94,"fill":109,"stroke":110,"style":148},[113,175,176],{"x":137,"y":170,"fill":110,"style":159,"textAnchor":138},"islands with directives",[90,178],{"x":141,"y":167,"width":134,"height":122,"rx":94,"fill":109,"stroke":110,"style":148},[113,180,181],{"x":144,"y":170,"fill":110,"style":159,"textAnchor":138},"full app hydration (compiled)",[90,183],{"x":115,"y":184,"width":121,"height":122,"rx":94,"fill":109,"stroke":110,"style":148},"146.0",[113,186,188],{"x":126,"y":187,"fill":110,"style":128,"textAnchor":129},"165.5","Navigation",[90,190],{"x":133,"y":184,"width":134,"height":122,"rx":94,"fill":109,"stroke":110,"style":148},[113,192,193],{"x":137,"y":187,"fill":110,"style":159,"textAnchor":138},"MPA (optional view transitions)",[90,195],{"x":141,"y":184,"width":134,"height":122,"rx":94,"fill":109,"stroke":110,"style":148},[113,197,198],{"x":144,"y":187,"fill":110,"style":159,"textAnchor":138},"client-side router with preloading",[90,200],{"x":115,"y":201,"width":121,"height":122,"rx":94,"fill":109,"stroke":110,"style":148},"176.0",[113,203,205],{"x":126,"y":204,"fill":110,"style":128,"textAnchor":129},"195.5","Best fit",[90,207],{"x":133,"y":201,"width":134,"height":122,"rx":94,"fill":109,"stroke":110,"style":148},[113,209,210],{"x":137,"y":204,"fill":110,"style":159,"textAnchor":138},"content sites, docs, marketing",[90,212],{"x":141,"y":201,"width":134,"height":122,"rx":94,"fill":109,"stroke":110,"style":148},[113,214,215],{"x":144,"y":204,"fill":110,"style":159,"textAnchor":138},"apps and interactive sites",[217,218,220],"h2",{"id":219},"the-metric-degradation-this-topic-addresses","The Metric Degradation This Topic Addresses",[15,222,223,224,227,228,231,232,235,236,227,238,241,242,244,245,247],{},"For Astro sites, the main risks are ",[25,225,226],{},"INP"," and ",[25,229,230],{},"TBT"," from islands that hydrate eagerly or include heavy dependencies, and ",[25,233,234],{},"LCP"," from images or fonts that are not optimised. For SvelteKit sites, risks include ",[25,237,234],{},[25,239,240],{},"TTFB"," from slow ",[38,243,63],{}," functions and data waterfalls, ",[25,246,226],{}," from large reactive updates, and slow client navigations when preloading is disabled or data is not cached. Both frameworks generally produce good results when their defaults are kept.",[217,249,251],{"id":250},"prerequisites","Prerequisites",[253,254,255,263,269],"ul",{},[256,257,258,259,262],"li",{},"Build output and bundle analysis (Astro and SvelteKit both use Vite; ",[38,260,261],{},"rollup-plugin-visualizer"," works for both).",[256,264,265,266,268],{},"A list of islands per page (Astro) or route ",[38,267,63],{}," functions and their data sources (SvelteKit).",[256,270,271],{},"Field Core Web Vitals per route.",[217,273,275],{"id":274},"_1-environment-setup-inventory-javascript-per-page","1. Environment Setup: Inventory JavaScript per Page",[15,277,278,279,282,283,41,286,227,289,292],{},"For Astro, search pages for ",[38,280,281],{},"client:"," directives and note each island's framework and dependencies. For SvelteKit, check the per-route client chunks in the build output and the data loaded in ",[38,284,285],{},"+page.ts",[38,287,288],{},"+page.server.ts",[38,290,291],{},"+layout"," load functions.",[217,294,296],{"id":295},"_2-capture-a-baseline","2. Capture a Baseline",[15,298,299],{},"Record JavaScript per route (compressed), TBT and hydration time in throttled lab traces, TTFB for server-rendered routes, and field LCP and INP.",[217,301,303],{"id":302},"_3-isolate-causes","3. Isolate Causes",[15,305,306,307,310],{},"Too much JavaScript in Astro → islands with eager directives or large dependencies, or framework runtimes from multiple UI frameworks. Slow TTFB in SvelteKit → sequential ",[38,308,309],{},"await","s in load functions, uncached API calls, server rendering for static content. Slow navigations → preloading disabled, large route chunks, or data dependencies that waterfall.",[217,312,314],{"id":313},"_4-apply-framework-native-fixes","4. Apply Framework-Native Fixes",[15,316,317,318,41,320,41,322,324,325,328,329,332],{},"In Astro, choose the latest acceptable directive for each island (",[38,319,47],{},[38,321,44],{},[38,323,50],{},"), keep island dependencies small, prefer one UI framework, and use ",[38,326,327],{},"astro:assets"," for images. In SvelteKit, prerender static routes, run independent loads in parallel, stream non-critical data by returning promises, and keep ",[38,330,331],{},"data-sveltekit-preload-data"," on links.",[334,335,340],"pre",{"className":336,"code":337,"language":338,"meta":339,"style":339},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","---\n\u002F\u002F src\u002Fpages\u002Fproduct\u002F[slug].astro\nimport Gallery from '..\u002F..\u002Fcomponents\u002FGallery.svelte';\nimport Reviews from '..\u002F..\u002Fcomponents\u002FReviews.jsx';\nimport { Image } from 'astro:assets';\nconst { product } = Astro.props;\n---\n\u003CImage src={product.hero} alt={product.name} width={1200} height={900} loading=\"eager\" fetchpriority=\"high\" \u002F>\n\u003CGallery client:visible images={product.images} \u002F>\n\u003CReviews client:idle productId={product.id} \u002F>\n\u003C!-- trade-off: client:idle hydrates reviews soon after load even if never scrolled\n     to; client:visible would save that work for users who do not scroll. -->\n","html","",[38,341,342,351,357,363,369,375,381,386,450,471,492,499],{"__ignoreMap":339},[343,344,347],"span",{"class":345,"line":346},"line",1,[343,348,350],{"class":349},"saISM","---\n",[343,352,354],{"class":345,"line":353},2,[343,355,356],{"class":349},"\u002F\u002F src\u002Fpages\u002Fproduct\u002F[slug].astro\n",[343,358,360],{"class":345,"line":359},3,[343,361,362],{"class":349},"import Gallery from '..\u002F..\u002Fcomponents\u002FGallery.svelte';\n",[343,364,366],{"class":345,"line":365},4,[343,367,368],{"class":349},"import Reviews from '..\u002F..\u002Fcomponents\u002FReviews.jsx';\n",[343,370,372],{"class":345,"line":371},5,[343,373,374],{"class":349},"import { Image } from 'astro:assets';\n",[343,376,378],{"class":345,"line":377},6,[343,379,380],{"class":349},"const { product } = Astro.props;\n",[343,382,384],{"class":345,"line":383},7,[343,385,350],{"class":349},[343,387,389,392,396,400,403,407,410,412,415,418,420,423,426,428,431,434,436,439,442,444,447],{"class":345,"line":388},8,[343,390,391],{"class":349},"\u003C",[343,393,395],{"class":394},"si8lv","Image",[343,397,399],{"class":398},"sPXB4"," src",[343,401,402],{"class":349},"=",[343,404,406],{"class":405},"sZ8jY","{product.hero}",[343,408,409],{"class":398}," alt",[343,411,402],{"class":349},[343,413,414],{"class":405},"{product.name}",[343,416,417],{"class":398}," width",[343,419,402],{"class":349},[343,421,422],{"class":405},"{1200}",[343,424,425],{"class":398}," height",[343,427,402],{"class":349},[343,429,430],{"class":405},"{900}",[343,432,433],{"class":398}," loading",[343,435,402],{"class":349},[343,437,438],{"class":405},"\"eager\"",[343,440,441],{"class":398}," fetchpriority",[343,443,402],{"class":349},[343,445,446],{"class":405},"\"high\"",[343,448,449],{"class":349}," \u002F>\n",[343,451,453,455,458,461,464,466,469],{"class":345,"line":452},9,[343,454,391],{"class":349},[343,456,457],{"class":394},"Gallery",[343,459,460],{"class":398}," client:visible",[343,462,463],{"class":398}," images",[343,465,402],{"class":349},[343,467,468],{"class":405},"{product.images}",[343,470,449],{"class":349},[343,472,474,476,479,482,485,487,490],{"class":345,"line":473},10,[343,475,391],{"class":349},[343,477,478],{"class":394},"Reviews",[343,480,481],{"class":398}," client:idle",[343,483,484],{"class":398}," productId",[343,486,402],{"class":349},[343,488,489],{"class":405},"{product.id}",[343,491,449],{"class":349},[343,493,495],{"class":345,"line":494},11,[343,496,498],{"class":497},"sjfSM","\u003C!-- trade-off: client:idle hydrates reviews soon after load even if never scrolled\n",[343,500,502],{"class":345,"line":501},12,[343,503,504],{"class":497},"     to; client:visible would save that work for users who do not scroll. -->\n",[15,506,507],{},[81,508,88,511,88,514,88,517,88,519,88,522,88,524,88,531,88,538,88,543,88,547,88,552,88,556,88,560,88,564,88,568,88,572,88,578,88,580,88],{"viewBox":509,"width":84,"role":85,"ariaLabel":510,"style":87},"0 0 760 220","Bar chart comparing client JavaScript shipped for the same product page built with different approaches.",[90,512],{"className":513,"x":94,"y":94,"width":84,"height":84,"fill":95},[93],[97,515,516],{},"Client JavaScript on a product page by approach",[101,518,510],{},[90,520],{"x":105,"y":105,"width":106,"height":521,"rx":108,"fill":109,"stroke":110,"style":111},"218",[113,523,516],{"x":115,"y":116,"fill":110,"style":117},[113,525,530],{"x":526,"y":527,"fill":110,"style":528,"textAnchor":529},"240.8","70.0","font-size:13px","end","SPA (React, all client)",[90,532],{"x":533,"y":120,"width":534,"height":535,"rx":536,"fill":109,"stroke":110,"style":537},"252.8","415.2","19","3","fill-opacity:0.7;stroke-opacity:0.35",[113,539,542],{"x":540,"y":527,"fill":110,"style":541},"674.0","font-size:12px;font-weight:600","290KB",[113,544,546],{"x":526,"y":545,"fill":110,"style":528,"textAnchor":529},"101.0","SvelteKit SSR (whole page hydrates)",[90,548],{"x":533,"y":549,"width":550,"height":535,"rx":536,"fill":155,"stroke":155,"style":551},"87.0","91.6","fill-opacity:0.55;stroke-opacity:0.9",[113,553,555],{"x":554,"y":545,"fill":110,"style":541},"350.4","64KB",[113,557,559],{"x":526,"y":558,"fill":110,"style":528,"textAnchor":529},"132.0","Astro, 2 islands (load)",[90,561],{"x":533,"y":562,"width":563,"height":535,"rx":536,"fill":155,"stroke":155,"style":551},"118.0","68.7",[113,565,567],{"x":566,"y":558,"fill":110,"style":541},"327.5","48KB",[113,569,571],{"x":526,"y":570,"fill":110,"style":528,"textAnchor":529},"163.0","Astro, 2 islands (visible + idle)",[90,573],{"x":533,"y":574,"width":563,"height":535,"rx":536,"fill":575,"stroke":576,"style":577},"149.0","#ffc300","#b8860b","fill-opacity:0.7;stroke-opacity:0.9",[113,579,567],{"x":566,"y":570,"fill":110,"style":541},[113,581,585],{"x":115,"y":582,"fill":583,"style":584},"198.0","#51617a","font-size:12.5px","Same bytes for both Astro variants, but the second hydrates later and only when needed.",[217,587,589],{"id":588},"deconstructing-islands-and-compiled-hydration","Deconstructing Islands and Compiled Hydration",[15,591,592],{},"In Astro, the page is HTML. Each island is a placeholder element with props serialised into attributes and a small loader script that, when its directive's condition is met, downloads the component's code and its framework's runtime and hydrates just that element. Islands do not share a component tree; they are independent apps, which keeps hydration cost proportional to interactive content. The cost of an island is its component code plus its framework runtime (shared among islands of the same framework).",[15,594,595],{},"In SvelteKit, the whole page is a Svelte component tree that hydrates after server rendering. Svelte's compiler generates code that sets up DOM updates without diffing, and its runtime is small, so hydration is cheap compared with virtual-DOM frameworks of similar complexity. But it is still whole-page hydration: large pages with many components hydrate more. SvelteKit's preloading, code splitting per route and server-side data loading make navigations fast once the app is running.",[217,597,599],{"id":598},"advanced-diagnostics-and-edge-cases","Advanced Diagnostics and Edge Cases",[15,601,602,605],{},[25,603,604],{},"Mixing UI frameworks in Astro."," Islands in React, Vue and Svelte on the same page ship three runtimes; standardise on one where possible.",[15,607,608,611],{},[25,609,610],{},"client:only."," Skips server rendering of the island; the space is empty until JavaScript runs, risking CLS and slower content. Use only for components that cannot render on the server.",[15,613,614,617],{},[25,615,616],{},"Large props."," Island props are serialised into HTML; pass IDs or minimal data rather than large objects.",[15,619,620,88,623,626,627,629],{},[25,621,622],{},"SvelteKit load waterfalls.",[38,624,625],{},"await parent()"," and sequential ",[38,628,309],{},"s in load functions serialise data fetching; parallelise where possible.",[15,631,632,88,635,637,638,640],{},[25,633,634],{},"Universal vs server load.",[38,636,285],{}," load runs on both server and client; heavy server-only work belongs in ",[38,639,288],{},".",[217,642,644],{"id":643},"validation-and-budgeting","Validation and Budgeting",[15,646,647],{},"Budget JavaScript per route, count islands with eager directives (Astro), and track TTFB for server-rendered routes (SvelteKit). Validate with lab traces and field LCP and INP per route.",[649,650,651,667],"table",{},[652,653,654],"thead",{},[655,656,657,661,664],"tr",{},[658,659,660],"th",{},"Budget",[658,662,663],{},"Astro target",[658,665,666],{},"SvelteKit target",[668,669,670,682,693,703],"tbody",{},[655,671,672,676,679],{},[673,674,675],"td",{},"Client JS per content route",[673,677,678],{},"\u003C 50 KB",[673,680,681],{},"\u003C 80 KB",[655,683,684,687,690],{},[673,685,686],{},"Eager islands (client:load)",[673,688,689],{},"0-1",[673,691,692],{},"n\u002Fa",[655,694,695,698,701],{},[673,696,697],{},"Static routes prerendered",[673,699,700],{},"Yes",[673,702,700],{},[655,704,705,708,710],{},[673,706,707],{},"Load function waterfalls",[673,709,692],{},[673,711,712],{},"None on key routes",[217,714,716],{"id":715},"worked-example-a-saas-documentation-and-marketing-site","Worked Example: A SaaS Documentation and Marketing Site",[15,718,719,720,722,723,725,726,728],{},"A SaaS company rebuilt its marketing and documentation site from a React SPA (280KB JavaScript, LCP p75 3.2 seconds) in Astro. Most pages became static HTML. Interactive parts — a pricing calculator, a search box and a code playground — became React islands: the calculator with ",[38,721,47],{},", search with ",[38,724,44],{}," (opened from the header), and the playground with ",[38,727,47],{}," on the pages that included it. Documentation pages shipped 12KB of JavaScript (search only), marketing pages up to 45KB. LCP p75 fell to 1.4 seconds and INP p75 to 90ms. The product's logged-in app remained a separate SvelteKit application, linked from the site.",[15,730,731],{},[81,732,88,735,88,738,88,741,88,743,88,760,88,763,88,765,88,770,88,776,88,780,88,784,88,787,88,791,88,794,88,798,88,802,88,805,88,808,88,812,88,815,88,818,88,821,88,825,88,828,88,836,88,840,88,844,88],{"viewBox":733,"width":84,"role":85,"ariaLabel":734,"style":87},"0 0 760 149","Steps from server rendering an Astro island to hydrating it when its directive's condition is met.",[90,736],{"className":737,"x":94,"y":94,"width":84,"height":84,"fill":95},[93],[97,739,740],{},"Astro island lifecycle",[101,742,734],{},[744,745,746],"defs",{},[747,748,755],"marker",{"id":749,"viewBox":750,"refX":751,"refY":752,"markerWidth":753,"markerHeight":753,"orient":754},"fa6218d565","0 0 10 10","9","5","7","auto-start-reverse",[756,757],"path",{"d":758,"fill":110,"style":759},"M0 0 L10 5 L0 10 z","fill-opacity:0.7",[90,761],{"x":105,"y":105,"width":106,"height":762,"rx":108,"fill":109,"stroke":110,"style":111},"147",[113,764,740],{"x":115,"y":116,"fill":110,"style":117},[90,766],{"x":115,"y":120,"width":767,"height":768,"rx":769,"fill":155,"stroke":155,"style":156},"108.8","71.0","6",[113,771,775],{"x":772,"y":773,"fill":110,"style":774,"textAnchor":138},"82.4","78.0","font-size:13px;font-weight:700","Server render",[113,777,779],{"x":772,"y":778,"fill":110,"style":159,"textAnchor":138},"96.0","static HTML +",[113,781,783],{"x":772,"y":782,"fill":110,"style":159,"textAnchor":138},"112.0","props",[90,785],{"x":786,"y":120,"width":767,"height":768,"rx":769,"fill":155,"stroke":155,"style":156},"176.8",[113,788,790],{"x":789,"y":773,"fill":110,"style":774,"textAnchor":138},"231.2","Page paints",[113,792,793],{"x":789,"y":778,"fill":110,"style":159,"textAnchor":138},"no JS needed",[90,795],{"x":796,"y":120,"width":767,"height":768,"rx":769,"fill":575,"stroke":576,"style":797},"325.6","fill-opacity:0.24;stroke-opacity:0.9",[113,799,801],{"x":800,"y":773,"fill":110,"style":774,"textAnchor":138},"380.0","Directive met",[113,803,804],{"x":800,"y":778,"fill":110,"style":159,"textAnchor":138},"load \u002F idle \u002F visible",[90,806],{"x":807,"y":120,"width":767,"height":768,"rx":769,"fill":155,"stroke":155,"style":156},"474.4",[113,809,811],{"x":810,"y":773,"fill":110,"style":774,"textAnchor":138},"528.8","Load code",[113,813,814],{"x":810,"y":778,"fill":110,"style":159,"textAnchor":138},"component +",[113,816,817],{"x":810,"y":782,"fill":110,"style":159,"textAnchor":138},"runtime",[90,819],{"x":820,"y":120,"width":767,"height":768,"rx":769,"fill":155,"stroke":155,"style":156},"623.2",[113,822,824],{"x":823,"y":773,"fill":110,"style":774,"textAnchor":138},"677.6","Hydrate",[113,826,827],{"x":823,"y":778,"fill":110,"style":159,"textAnchor":138},"island only",[345,829],{"x1":830,"y1":831,"x2":832,"y2":831,"stroke":110,"strokeWidth":833,"style":834,"markerEnd":835},"136.8","91.5","174.8","1.5","stroke-opacity:0.6","url(#fa6218d565)",[345,837],{"x1":838,"y1":831,"x2":839,"y2":831,"stroke":110,"strokeWidth":833,"style":834,"markerEnd":835},"285.6","323.6",[345,841],{"x1":842,"y1":831,"x2":843,"y2":831,"stroke":110,"strokeWidth":833,"style":834,"markerEnd":835},"434.4","472.4",[345,845],{"x1":846,"y1":831,"x2":847,"y2":831,"stroke":110,"strokeWidth":833,"style":834,"markerEnd":835},"583.2","621.2",[217,849,851],{"id":850},"choosing-a-directive-in-astro","Choosing a Directive in Astro",[15,853,854,855,857,858,860,861,863,864,866,867,869],{},"The directive determines when an island's JavaScript loads and runs. ",[38,856,40],{}," hydrates immediately — use it only for above-the-fold controls needed at once. ",[38,859,44],{}," hydrates when the browser is idle after load — good for widgets needed soon. ",[38,862,47],{}," hydrates when the island scrolls into view — the best default for below-the-fold interactivity. ",[38,865,50],{}," hydrates when a media query matches — useful for components only interactive on certain screen sizes. ",[38,868,53],{}," renders only on the client — a last resort. The guide on client directives covers choosing per component.",[217,871,873],{"id":872},"preloading-in-sveltekit","Preloading in SvelteKit",[15,875,876,877,880,881,884],{},"SvelteKit preloads code and data for links on hover or tap by default in new projects (",[38,878,879],{},"data-sveltekit-preload-data=\"hover\""," on the body). Preloading data on hover gives navigations a head start of 100–300ms; preloading code on viewport (",[38,882,883],{},"data-sveltekit-preload-code=\"viewport\"",") makes route chunks ready before users click. Load functions should be fast and cache-friendly so preloading does not create server load for links users do not follow. The SvelteKit preloading guide covers the options and trade-offs.",[217,886,888],{"id":887},"images-and-fonts-in-both-frameworks","Images and Fonts in Both Frameworks",[15,890,891,892,36,894,227,897,900,901,227,904,907,908,911,912,915],{},"Astro's ",[38,893,327],{},[38,895,896],{},"\u003CImage>",[38,898,899],{},"\u003CPicture>",") generates optimised, responsive images at build time or on demand, with dimensions to prevent CLS; set ",[38,902,903],{},"loading=\"eager\"",[38,905,906],{},"fetchpriority=\"high\""," on the LCP image. SvelteKit has an enhanced image plugin (",[38,909,910],{},"@sveltejs\u002Fenhanced-img",") for build-time optimisation, or you can use an image CDN. For fonts, self-host with ",[38,913,914],{},"font-display: swap"," and size-adjusted fallbacks; Astro has built-in font support in recent versions, and both work well with Fontsource packages.",[217,917,919],{"id":918},"third-party-scripts-on-lightweight-sites","Third-Party Scripts on Lightweight Sites",[15,921,922,923,926,927,930],{},"When a page ships almost no first-party JavaScript, third-party scripts become the dominant cost. On many Astro sites, a tag manager or analytics bundle outweighs all islands combined. Load analytics with ",[38,924,925],{},"defer"," or after the load event, put chat and social widgets behind facades that load on interaction, and consider running compatible scripts in a web worker with Partytown, which has an Astro integration. In SvelteKit, load third-party scripts in ",[38,928,929],{},"onMount"," or after navigation completes rather than in the document head. The fastest framework cannot compensate for a blocking third-party script in the head. Audit third-party scripts with the same rigour as islands: list each one, measure its main-thread time on a throttled device, and load it as late as its purpose allows.",[217,932,934],{"id":933},"a-rollout-plan","A Rollout Plan",[936,937,938,941,944,947,950,953],"ol",{},[256,939,940],{},"Inventory JavaScript per route and, in Astro, islands with their directives.",[256,942,943],{},"Astro: switch islands to the latest acceptable directive; consolidate UI frameworks.",[256,945,946],{},"SvelteKit: prerender static routes; parallelise and stream load functions.",[256,948,949],{},"Configure images (LCP priority, sizes) and self-hosted fonts.",[256,951,952],{},"Keep preloading enabled and load functions cacheable.",[256,954,955],{},"Add JavaScript budgets and field monitoring per route, and review both after every release.",[217,957,959],{"id":958},"svelte-5-runes-and-update-performance","Svelte 5 Runes and Update Performance",[15,961,962,963,41,966,41,969,227,972,975,976,978,979,982,983,986,987,990],{},"Svelte 5 introduced runes — ",[38,964,965],{},"$state",[38,967,968],{},"$derived",[38,970,971],{},"$effect",[38,973,974],{},"$props"," — which make reactivity explicit and fine-grained. State declared with ",[38,977,965],{}," is tracked at the property level, derived values recompute only when their inputs change, and updates touch only the DOM nodes that depend on changed values. For large collections, ",[38,980,981],{},"$state.raw"," avoids deep proxying (similar to Vue's ",[38,984,985],{},"shallowRef","), which helps when data is replaced rather than mutated. Keyed ",[38,988,989],{},"{#each}"," blocks let Svelte move existing DOM nodes instead of recreating them when lists reorder. These features keep INP low on interactive SvelteKit pages; problems usually come from very large lists without virtualization or effects that do heavy work on every change.",[217,992,994],{"id":993},"content-collections-and-build-performance","Content Collections and Build Performance",[15,996,997],{},"Large content sites built with Astro rely on content collections for Markdown, MDX and CMS data. Build time grows with page count and image processing; for thousands of pages, enable incremental content caching, process images once and cache the results, and consider on-demand rendering with caching for rarely visited pages. SvelteKit sites face similar choices with prerendering: prerender the pages that receive most traffic and render the rest on demand with CDN caching. Fast builds matter for performance indirectly — teams with slow builds tend to defer optimisations and content fixes.",[217,999,1001],{"id":1000},"measuring-astro-and-sveltekit-sites","Measuring Astro and SvelteKit Sites",[15,1003,1004,1005,1008],{},"Astro sites are multi-page by default, so standard Core Web Vitals measurement with the ",[38,1006,1007],{},"web-vitals"," library covers every navigation. If you enable Astro's client router (view transitions), navigations become soft navigations and need the same care as single-page apps. SvelteKit apps navigate client-side after the first load; measure first loads with Core Web Vitals and client navigations with custom timings (from click to the new page rendering), and segment both by route. In both cases, the Long Animation Frames API helps attribute slow interactions to islands, components or third-party scripts.",[217,1010,1012],{"id":1011},"common-pitfalls","Common Pitfalls",[253,1014,1015,1021,1027,1033,1039],{},[256,1016,1017,1020],{},[25,1018,1019],{},"client:load everywhere."," Islands hydrate eagerly, losing the benefit.",[256,1022,1023,1026],{},[25,1024,1025],{},"Several UI frameworks on one page."," Multiple runtimes downloaded.",[256,1028,1029,1032],{},[25,1030,1031],{},"Large serialised props."," Bloated HTML.",[256,1034,1035,1038],{},[25,1036,1037],{},"Sequential awaits in load functions."," Slow TTFB and navigations.",[256,1040,1041,1044],{},[25,1042,1043],{},"Universal load doing server-only work."," Duplicated work on the client.",[217,1046,1048],{"id":1047},"faq","FAQ",[1050,1051,1054,1058],"details",{"className":1052},[1053],"faq-item",[1055,1056,1057],"summary",{},"Is Astro faster than Next.js?",[15,1059,1060],{},"For content-heavy sites with little interactivity, Astro typically ships far less JavaScript by default. For highly interactive apps, the difference depends on architecture more than framework.",[1050,1062,1064,1067],{"className":1063},[1053],[1055,1065,1066],{},"What is an island in Astro?",[15,1068,1069],{},"An interactive component embedded in static HTML and hydrated independently according to its client directive.",[1050,1071,1073,1076],{"className":1072},[1053],[1055,1074,1075],{},"Does SvelteKit use a virtual DOM?",[15,1077,1078],{},"No. Svelte compiles components into code that updates the DOM directly, which keeps the runtime small and updates efficient.",[1050,1080,1082,1085],{"className":1081},[1053],[1055,1083,1084],{},"Should I prerender SvelteKit pages?",[15,1086,1087,1088,1091],{},"Yes, for pages whose content is known at build time. Set ",[38,1089,1090],{},"export const prerender = true"," on those routes.",[1050,1093,1095,1098],{"className":1094},[1053],[1055,1096,1097],{},"Can I use React components in Astro?",[15,1099,1100],{},"Yes, as islands. Each island hydrates independently; React's runtime is shared among React islands on the page.",[1050,1102,1104,1107],{"className":1103},[1053],[1055,1105,1106],{},"How does SvelteKit preloading work?",[15,1108,1109],{},"Links with preload attributes fetch the next route's code (and optionally data) on hover, tap or visibility, so navigation starts with much of the work done.",[1050,1111,1113,1116],{"className":1112},[1053],[1055,1114,1115],{},"Do Astro view transitions slow pages down?",[15,1117,1118],{},"They add a small client router script when enabled. For most content sites the cost is minor; measure INP and navigation timing after enabling.",[1050,1120,1122,1125],{"className":1121},[1053],[1055,1123,1124],{},"Does Astro work with a headless CMS?",[15,1126,1127],{},"Yes. Content can be fetched at build time for static pages or on demand with caching for server-rendered pages, and webhooks can trigger rebuilds or cache purges.",[1050,1129,1131,1134],{"className":1130},[1053],[1055,1132,1133],{},"Is SvelteKit suitable for content sites?",[15,1135,1136],{},"Yes. With prerendering and minimal client-side interactivity it performs well; for sites that are almost entirely static, Astro ships less JavaScript by default.",[1050,1138,1140,1143],{"className":1139},[1053],[1055,1141,1142],{},"Can Astro pages use speculation rules?",[15,1144,1145],{},"Yes. Because Astro sites navigate with full page loads by default, speculation rules for prefetching or prerendering likely next pages can make navigations nearly instant.",[1050,1147,1149,1152],{"className":1148},[1053],[1055,1150,1151],{},"Do Svelte components hydrate faster than React components?",[15,1153,1154],{},"Generally, because compiled Svelte code and its small runtime do less work per component. The number of components hydrated still matters most.",[1050,1156,1158,1161],{"className":1157},[1053],[1055,1159,1160],{},"What are Astro server islands?",[15,1162,1163,1164,1167],{},"Components marked with ",[38,1165,1166],{},"server:defer"," that render on the server after the main page, so a cached static page can include personalised or slow content without delaying the rest.",[1050,1169,1171,1174],{"className":1170},[1053],[1055,1172,1173],{},"How small can a SvelteKit page's JavaScript be?",[15,1175,1176],{},"Small: the runtime is compact, and with prerendering and few interactive components, routes often ship tens of kilobytes. Check per-route chunks in the build output.",[1050,1178,1180,1183],{"className":1179},[1053],[1055,1181,1182],{},"Should I use Astro's view transitions?",[15,1184,1185],{},"They make navigations feel smoother and allow persistent islands, at the cost of a small client router. Measure INP and navigation timing before and after enabling them.",[217,1187,1189],{"id":1188},"guides-in-this-topic","Guides in This Topic",[253,1191,1192,1199,1206],{},[256,1193,1194,1198],{},[19,1195,1197],{"href":1196},"\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002Fchoosing-astro-client-directives\u002F","Choosing Astro client directives"," — when each island hydrates.",[256,1200,1201,1205],{},[19,1202,1204],{"href":1203},"\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002Fsveltekit-preloading-and-load-functions\u002F","SvelteKit preloading and load functions"," — fast data and navigations.",[256,1207,1208,1212],{},[19,1209,1211],{"href":1210},"\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002Fastro-vs-nextjs-for-content-site-performance\u002F","Astro vs Next.js for content-site performance"," — choosing a framework for content.",[217,1214,1216],{"id":1215},"related","Related",[253,1218,1219,1225,1232],{},[256,1220,1221,1224],{},[19,1222,1223],{"href":21},"Framework performance"," — the section overview.",[256,1226,1227,1231],{},[19,1228,1230],{"href":1229},"\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002Flazy-hydration-in-nuxt\u002F","Lazy hydration in Nuxt"," — the Vue take on partial hydration.",[256,1233,1234,1238],{},[19,1235,1237],{"href":1236},"\u002Fnetwork-protocol-optimization\u002Fspeculative-loading-and-prefetching\u002F","Speculative loading & prefetching"," — instant navigations for multi-page sites.",[1240,1241,1243],"script",{"type":1242},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"Astro & SvelteKit Performance: Shipping Less, Loading Smarter\",\n  \"description\": \"How Astro's islands architecture and SvelteKit's compiled components and load functions deliver fast pages, and how to configure them for the best Core Web Vitals.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Environment Setup: Inventory JavaScript per Page\",\n      \"text\": \"For Astro, search pages for client: directives and note each island's framework and dependencies.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Capture a Baseline\",\n      \"text\": \"Record JavaScript per route (compressed), TBT and hydration time in throttled lab traces, TTFB for server-rendered routes, and field LCP and INP.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Isolate Causes\",\n      \"text\": \"Too much JavaScript in Astro → islands with eager directives or large dependencies, or framework runtimes from multiple UI frameworks.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Apply Framework-Native Fixes\",\n      \"text\": \"In Astro, choose the latest acceptable directive for each island (client:visible, client:idle, client:media), keep island dependencies small, prefer one UI framework, and use astro:assets for images.\"\n    }\n  ]\n}\n",[1240,1245,1246],{"type":1242},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"Astro & SvelteKit Performance: Shipping Less, Loading Smarter\",\n  \"description\": \"How Astro's islands architecture and SvelteKit's compiled components and load functions deliver fast pages, and how to configure them for the best Core Web Vitals.\",\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\u002Fastro-and-sveltekit-performance\u002F\"\n  }\n}\n",[1240,1248,1249],{"type":1242},"\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\": \"Astro & SvelteKit Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002F\"\n    }\n  ]\n}\n",[1251,1252,1253],"style",{},"html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .si8lv, html code.shiki .si8lv{--shiki-default:#6E011A;--shiki-default-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic;--shiki-light:#6E011A;--shiki-light-font-style:italic}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}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);}",{"title":339,"searchDepth":353,"depth":353,"links":1255},[1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277],{"id":219,"depth":353,"text":220},{"id":250,"depth":353,"text":251},{"id":274,"depth":353,"text":275},{"id":295,"depth":353,"text":296},{"id":302,"depth":353,"text":303},{"id":313,"depth":353,"text":314},{"id":588,"depth":353,"text":589},{"id":598,"depth":353,"text":599},{"id":643,"depth":353,"text":644},{"id":715,"depth":353,"text":716},{"id":850,"depth":353,"text":851},{"id":872,"depth":353,"text":873},{"id":887,"depth":353,"text":888},{"id":918,"depth":353,"text":919},{"id":933,"depth":353,"text":934},{"id":958,"depth":353,"text":959},{"id":993,"depth":353,"text":994},{"id":1000,"depth":353,"text":1001},{"id":1011,"depth":353,"text":1012},{"id":1047,"depth":353,"text":1048},{"id":1188,"depth":353,"text":1189},{"id":1215,"depth":353,"text":1216},"How Astro's islands architecture and SvelteKit's compiled components and load functions deliver fast pages, and how to configure them for the best Core Web Vitals.","md",{"slug":1281,"type":1282,"breadcrumb":1283,"datePublished":1290,"dateModified":1290},"astro-and-sveltekit-performance","topic",[1284,1287,1288],{"name":1285,"url":1286},"Home","\u002F",{"name":22,"url":21},{"name":5,"url":1289},"\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002F","2026-10-06",true,"\u002Fframework-performance\u002Fastro-and-sveltekit-performance",{"title":1294,"description":1295},"Astro and SvelteKit Performance: Islands and Preloading","Get the most from Astro islands and SvelteKit: choose client directives, keep JavaScript minimal, preload on intent, and pick the right framework.","framework-performance\u002Fastro-and-sveltekit-performance\u002Findex","kVbaJQI9chbYPBrntVvtIgA972vdNbQ42HcgUG7JZlM",[1299,1303],{"title":1300,"path":1301,"stem":1302,"children":-1},"Going Zoneless in Angular","\u002Fframework-performance\u002Fangular-performance\u002Fgoing-zoneless-in-angular","framework-performance\u002Fangular-performance\u002Fgoing-zoneless-in-angular\u002Findex",{"title":1304,"path":1305,"stem":1306,"children":-1},"Astro vs Next.js for Content-Site Performance","\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002Fastro-vs-nextjs-for-content-site-performance","framework-performance\u002Fastro-and-sveltekit-performance\u002Fastro-vs-nextjs-for-content-site-performance\u002Findex",1791308070283]