1"use strict";(self.webpackChunkgatsby_starter_default=self.webpackChunkgatsby_starter_default||[]).push([[1714],{21993:function(e,n,a){a.r(n),a.d(n,{Head:function(){return g},default:function(){return h}});var t=a(28453),s=a(96540);function l(e){const n=Object.assign({h1:"h1",a:"a",span:"span",p:"p",blockquote:"blockquote",strong:"strong",h2:"h2",h3:"h3",ol:"ol",li:"li",table:"table",thead:"thead",tr:"tr",th:"th",tbody:"tbody",td:"td",ul:"ul"},(0,t.R)(),e.components);return s.createElement(s.Fragment,null,s.createElement(n.h1,{id:"rsc-migration-flight-payload-optimization",style:{position:"relative"}},s.createElement(n.a,{href:"#rsc-migration-flight-payload-optimization","aria-label":"rsc migration flight payload optimization permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"RSC Migration: Flight Payload Optimization"),"\n",s.createElement(n.p,null,"This guide covers a critical and counterintuitive RSC performance nuance: not all non-interactive, stateless components should be Server Components. When presentational components produce element trees much larger than their data props, moving them to Client Components can dramatically reduce page weight."),"\n",s.createElement(n.blockquote,null,"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"Part 8 of the ",s.createElement(n.a,{href:"/linked-assets/e8d09fae987585e61153eab1eac11f7c/migrating-to-rsc.md"},"RSC Migration Series"))," | Previous:\n",s.createElement(n.a,{href:"/linked-assets/95b3d10509bb106251ff4d4866187802/rsc-troubleshooting.md"},"Troubleshooting and Common Pitfalls")," | Next:\n",s.createElement(n.a,{href:"/linked-assets/622a61aa1ad6998352e5086c6bf2834f/rsc-performance-validation.md"},"RSC Performance Validation Playbook")),"\n"),"\n",s.createElement(n.h2,{id:"whats-in-the-flight-payload",style:{position:"relative"}},s.createElement(n.a,{href:"#whats-in-the-flight-payload","aria-label":"whats in the flight payload permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"What's in the Flight Payload"),"\n",s.createElement(n.p,null,"When a Server Component renders, React serializes its output into the ",s.createElement(n.strong,null,"RSC Flight payload")," -- a JSON-like stream embedded in ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text"><script></code>'}})," tags alongside the server-rendered HTML. This payload tells React on the client how to reconcile the component tree without re-rendering from scratch."),"\n",s.createElement(n.p,null,"Every server-rendered element becomes a JSON array in the payload:"),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="json"><pre class="language-json"><code class="language-json"><span class="token punctuation">[</span><span class="token string">"$"</span><span class="token punctuation">,</span><span class="token string">"div"</span><span class="token punctuation">,</span><span class="token null keyword">null</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">"flex items-center justify-between px-4 py-2 bg-white shadow-sm rounded-lg"</span><span class="token punctuation">,</span><span class="token property">"children"</span><span class="token operator">:</span><span class="token punctuation">[</span>...<span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre></div>'}}),"\n",s.createElement(n.p,null,"In contrast, when a Client Component is referenced from a Server Component, the payload contains only a lightweight ",s.createElement(n.strong,null,"client reference")," (module ID + chunk metadata) plus the serialized props. The browser renders the element tree locally from the JavaScript bundle it already has."),"\n",s.createElement(n.h2,{id:"why-all-display-only--server-is-an-oversimplification",style:{position:"relative"}}
1,s.createElement(n.a,{href:"#why-all-display-only--server-is-an-oversimplification","aria-label":"why all display only server is an oversimplification permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),'Why "All Display-Only = Server" Is an Oversimplification'),"\n",s.createElement(n.p,null,'The standard RSC guidance says: "If a component doesn\'t use hooks, event handlers, or browser APIs, make it a Server Component." This is a good default, but it ignores the ',s.createElement(n.strong,null,"expansion ratio")," between data props and rendered element trees."),"\n",s.createElement(n.p,null,"Consider a ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">StarRating</code>'}})," component:"),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="jsx"><pre class="language-jsx"><code class="language-jsx"><span class="token comment">// StarRating as a Server Component</span>\n<span class="token comment">// Data: { rating: 4.5, count: 128 } â ~30 bytes</span>\n<span class="token comment">// Flight payload per instance: ~498 bytes of nested divs, â
characters, and className strings</span>\n<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">StarRating</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> rating<span class="token punctuation">,</span> count <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>\n <span class="token keyword">const</span> fullStars <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>rating<span class="token punctuation">)</span><span class="token punctuation">;</span>\n <span class="token keyword">const</span> hasHalf <span class="token operator">=</span> rating <span class="token operator">%</span> <span class="token number">1</span> <span class="token operator">>=</span> <span class="token number">0.5</span><span class="token punctuation">;</span>\n <span class="token keyword">return</span> <span class="token punctuation">(</span>\n <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>flex items-center gap-1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text">\n </span><span class="token punctuation">{</span>Array<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">length</span><span class="token operator">:</span> <span class="token number">5</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">_<span class="token punctuation">,</span> i</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span>\n <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span>\n <span class="token attr-name">key</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>i<span class="token punctuation">}</span></span>
1\n <span class="token attr-name">className</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">text-lg </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>i <span class="token operator"><</span> fullStars <span class="token operator">?</span> <span class="token string">\'text-yellow-400\'</span> <span class="token operator">:</span> i <span class="token operator">===</span> fullStars <span class="token operator">&&</span> hasHalf <span class="token operator">?</span> <span class="token string">\'text-yellow-300\'</span> <span class="token operator">:</span> <span class="token string">\'text-gray-300\'</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">}</span></span>\n <span class="token punctuation">></span></span><span class="token plain-text">\n â
\n </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span>\n <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text">\n </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>ml-2 text-sm text-gray-600<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text">(</span><span class="token punctuation">{</span>count<span class="token punctuation">}</span><span class="token plain-text">)</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><span class="token plain-text">\n </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>\n <span class="token punctuation">)</span><span class="token punctuation">;</span>\n<span class="token punctuation">}</span></code></pre></div>'}}),"\n",s.createElement(n.p,null,"As a Server Component, the Flight payload contains the ",s.createElement(n.strong,null,"entire expanded element tree")," -- every ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text"><span></code>'}}),", every className string, every ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">â
</code>'}})," character. The 30 bytes of data (",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">rating</code>'}})," + ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">count</code>'}}),") expands to ~498 bytes in the payload. That's a 16:1 expansion ratio."),"\n",s.createElement(n.p,null,"As a Client Component, the payload contains only the client reference plus serialized props -- a fraction of the expanded element tree. The browser renders the element tree from the JS bundle."),"\n",s.createElement(n.h2,{id:"the-counterintuitive-pattern-presentational-client-components",style:{position:"relative"}},s.createElement(n.a,{href:"#the-counterintuitive-pattern-presentational-client-components","aria-label":"the counterintuitive pattern presentational client components permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"The Counterintuitive Pattern: Presentational Client Components"),"\n",s.createElement(n.p,null,"Sometimes the right move is to make a purely presentational component a Client Component. This is counterintuitive because the component doesn't use hooks, state, or event handlers -- the usual reasons for ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:"<code class=\"language-text\">'use client'</code>"}}),"."),"\n",s.createElement(n.h3,{id:"when-to-apply-this-pattern",style:{position:"relative"}}
1,s.createElement(n.a,{href:"#when-to-apply-this-pattern","aria-label":"when to apply this pattern permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"When to Apply This Pattern"),"\n",s.createElement(n.p,null,"A component is a candidate for this optimization when these signals line up:"),"\n",s.createElement(n.ol,null,"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"High per-instance expansion")," -- the rendered element tree is several times larger than the data props"),"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"Repeated many times on the page")," -- the component renders per-item in a list (e.g., product cards, review snippets, tag lists)"),"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"Heavy className density")," -- the component has many utility CSS classes (especially Tailwind) that inflate the element tree"),"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"Bundle scope is narrow")," -- the component is not part of a shared client bundle loaded on many pages where it never renders"),"\n"),"\n",s.createElement(n.p,null,"Treat ratio and repetition count together. A 3:1 component rendered 60 times can be a better target than a 10:1 component rendered once."),"\n",s.createElement(n.h3,{id:"real-world-example",style:{position:"relative"}},s.createElement(n.a,{href:"#real-world-example","aria-label":"real world example permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Real-World Example"),"\n",s.createElement(n.p,null,"This was demonstrated on a product search page rendering 36 products, each with reviews, features, tags, and star ratings. Four purely presentational subtrees were moved from server to client components:"),"\n",s.createElement(n.table,null,s.createElement(n.thead,null,s.createElement(n.tr,null,s.createElement(n.th,null,"Component"),s.createElement(n.th,null,"Server element tree per card"),s.createElement(n.th,null,"Client props per card"),s.createElement(n.th,null,"Savings ratio"))),s.createElement(n.tbody,null,s.createElement(n.tr,null,s.createElement(n.td,null,s.createElement(n.strong,null,"StarRating")),s.createElement(n.td,null,"~498 B (nested divs, â
chars, classNames)"),s.createElement(n.td,null,"~30 B (2 numbers: rating, count)"),s.createElement(n.td,null,"16:1")),s.createElement(n.tr,null,s.createElement(n.td,null,s.createElement(n.strong,null,"ReviewSnippets")),s.createElement(n.td,null,"~934 B per snippet"),s.createElement(n.td,null,"~100 B (ReviewSnippet data)"),s.createElement(n.td,null,"9:1")),s.createElement(n.tr,null,s.createElement(n.td,null,s.createElement(n.strong,null,"FeaturesList")),s.createElement(n.td,null,"~190 B per feature item"),s.createElement(n.td,null,"~30 B (string)"),s.createElement(n.td,null,"6:1")),s.createElement(n.tr,null,s.createElement(n.td,null,s.createElement(n.strong,null,"ProductTags")),s.createElement(n.td,null,"~155 B per tag"),s.createElement(n.td,null,"~10 B (string)"),s.createElement(n.td,null,"15:1")))),"\n",s.createElement(n.p,null,"These before/after numbers came from the same page in one benchmark environment. The large TTFB gain here is most representative of buffered or non-streaming SSR, where the server finishes more work before sending bytes. Streaming deployments may
1see smaller or different TTFB changes, and results will also vary under different server load, caching, or multi-region production setups."),"\n",s.createElement(n.p,null,"Results:"),"\n",s.createElement(n.table,null,s.createElement(n.thead,null,s.createElement(n.tr,null,s.createElement(n.th,null,"Metric"),s.createElement(n.th,null,"Before"),s.createElement(n.th,null,"After"),s.createElement(n.th,null,"Change"))),s.createElement(n.tbody,null,s.createElement(n.tr,null,s.createElement(n.td,null,s.createElement(n.strong,null,"Raw Flight payload")),s.createElement(n.td,null,"158,267 B"),s.createElement(n.td,null,"91,244 B"),s.createElement(n.td,null,s.createElement(n.strong,null,"-42.3%"))),s.createElement(n.tr,null,s.createElement(n.td,null,s.createElement(n.strong,null,"Total HTML")),s.createElement(n.td,null,"370,461 B"),s.createElement(n.td,null,"273,901 B"),s.createElement(n.td,null,s.createElement(n.strong,null,"-26.1%"))),s.createElement(n.tr,null,s.createElement(n.td,null,s.createElement(n.strong,null,"Client JS increase")),s.createElement(n.td,null,"--"),s.createElement(n.td,null,"+2,152 B (+471 B gzipped)"),s.createElement(n.td,null,"minimal")),s.createElement(n.tr,null,s.createElement(n.td,null,s.createElement(n.strong,null,"TTFB")),s.createElement(n.td,null,"808 ms"),s.createElement(n.td,null,"245 ms"),s.createElement(n.td,null,"-70%")),s.createElement(n.tr,null,s.createElement(n.td,null,s.createElement(n.strong,null,"FCP")),s.createElement(n.td,null,"982 ms"),s.createElement(n.td,null,"350 ms"),s.createElement(n.td,null,"-64%")),s.createElement(n.tr,null,s.createElement(n.td,null,s.createElement(n.strong,null,"LCP")),s.createElement(n.td,null,"982 ms"),s.createElement(n.td,null,"1,058 ms"),s.createElement(n.td,null,"+8% (tradeoff: more hydration)")))),"\n",s.createElement(n.p,null,"The ",s.createElement(n.strong,null,"2.2 KB client JS increase")," produced a ",s.createElement(n.strong,null,"67 KB Flight payload reduction")," -- a 31:1 ratio.\nIn this benchmark, the TTFB improvement came primarily from the server serializing far less Flight data before it could emit the first byte. The wire-size reduction alone would not normally explain the full change."),"\n",s.createElement(n.p,null,"The savings were dominated by className strings. In the Tailwind-heavy benchmark, the Flight payload broke down as:"),"\n",s.createElement(n.table,null,s.createElement(n.thead,null,s.createElement(n.tr,null,s.createElement(n.th,null,"Category"),s.createElement(n.th,null,"Approximate share"),s.createElement(n.th,null,"Description"))),s.createElement(n.tbody,null,s.createElement(n.tr,null,s.createElement(n.td,null,s.createElement(n.strong,null,"className strings")),s.createElement(n.td,null,"~48%"),s.createElement(n.td,null,"CSS class lists, especially verbose with utility-first CSS (Tailwind)")),s.createElement(n.tr,null,s.createElement(n.td,null,s.createElement(n.strong,null,"Structural JSON")),s.createElement(n.td,null,"~25%"),s.createElement(n.td,null,"The ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">["$","div",null,{...}]</code>'}})," wrappers around every element")),s.createElement(n.tr,null,s.createElement(n.td,null,s.createElement(n.strong,null,"Content data")),s.createElement(n.td,null,"~27%"),s.createElement(n.td,null,"Actual text, numbers, and data values")))),"\n",s.createElement("p",{align:"center"},s.createElement("img",{src:"images/flight-payload-breakdown.svg",alt:"Diagram showing what makes up the RSC Flight payload: className strings (~48%), structural JSON (~25%), and content data (~27%). Includes expansion ratio benchmarks for real components like StarRating (16:1) and ReviewSnippets (9.3:1).",width:"840"})),"\n",s.createElement(n.h3,{id:"how-to-apply-it",style:{position:"relative"}},s.createElement(n.a,{href:"#how-to-apply-it","aria-label":"how to apply it permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"How to Apply It"),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"Step 1:")," Identify presentational subtrees with high expansion ratios."),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"Step 2:")," Add ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:"<code class=\"language-text\">'use client'</code>"}})," to those components. The directive must appear at the top of the file, before any ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">import</code>'}})," statements. It tells React to send a client reference instead of the expanded element tree."),"\n",s.createElement(n.p,null,"Before adding ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:"<code class=\"language-text\">'use client'</code>"}}),", confirm the component and its import tree are free of server-only depen
1dencies (",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">server-only</code>'}}),", direct DB queries, API-key-bearing helpers, async props, etc.). If any exist, move that work into a parent Server Component and pass the results down as props first.\nAfter the change, inspect the resulting client bundle or import tree as well. Any direct or transitive import under that file now becomes client code, so server-only helpers must be pulled out before you keep the directive."),"\n",s.createElement(n.p,null,"Note: Client Components cannot be ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">async</code>'}})," functions. If the component you want to convert is currently loading its own data with ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">async</code>'}}),"/",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">await</code>'}}),", move that fetch into a parent Server Component first and pass the data down as props before adding ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:"<code class=\"language-text\">'use client'</code>"}}),"."),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="jsx"><pre class="language-jsx"><code class="language-jsx"><span class="token comment">// Before: Server Component â entire element tree in Flight payload</span>\n<span class="token comment">// (No \'use client\' directive â React renders this on the server.)</span>\n<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">ProductTags</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> tags <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>\n <span class="token keyword">return</span> <span class="token punctuation">(</span>\n <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>flex flex-wrap gap-2 mt-3<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text">\n </span><span class="token punctuation">{</span>tags<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">tag</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span>\n <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span>\n <span class="token attr-name">key</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>tag<span class="token punctuation">}</span></span>\n <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800<span class="token punctuation">"</span></span>\n <span class="token punctuation">></span></span><span class="token plain-text">\n </span><span class="token punctuation">{</span>tag<span class="token punctuation">}</span><span class="token plain-text">\n </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span>\n <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text">\n </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>\n <span class="token punctuation">)</span><span class="token punctuation">;</span>\n<span class="token punctuation">}</span></code></pre></div>'}}),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="jsx"><pre class="language-jsx"><code class="language-jsx"><span class="token comment">// After: Client Component â only tags array in Flight payload</span>\n<span class="token string">\'use client\'</span><span class="token punctuation">;</span>\n\n<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">ProductTags</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> tags <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>\n <span class="token keyword">return</span> <span class="token punctuation">(</span>\n <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>flex flex-wrap gap-2 mt-3<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text">\n </span><span class="token punctuation">{</span>tags<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">tag</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span>
1\n <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span>\n <span class="token attr-name">key</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>tag<span class="token punctuation">}</span></span>\n <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800<span class="token punctuation">"</span></span>\n <span class="token punctuation">></span></span><span class="token plain-text">\n </span><span class="token punctuation">{</span>tag<span class="token punctuation">}</span><span class="token plain-text">\n </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span>\n <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text">\n </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>\n <span class="token punctuation">)</span><span class="token punctuation">;</span>\n<span class="token punctuation">}</span></code></pre></div>'}}),"\n",s.createElement(n.p,null,"The code is identical except for the ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:"<code class=\"language-text\">'use client'</code>"}})," directive. The component still receives the same props and renders the same output. The difference is where the rendering happens and what the Flight payload contains."),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"Step 3:")," Verify the savings by measuring the payload (see next section)."),"\n",s.createElement(n.h2,{id:"how-to-measure-your-flight-payload",style:{position:"relative"}},s.createElement(n.a,{href:"#how-to-measure-your-flight-payload","aria-label":"how to measure your flight payload permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"How to Measure Your Flight Payload"),"\n",s.createElement(n.p,null,"The Flight payload is embedded in ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text"><script></code>'}})," tags in the HTML response. To extract and measure it:"),"\n",s.createElement(n.h3,{id:"browser-devtools",style:{position:"relative"}},s.createElement(n.a,{href:"#browser-devtools","aria-label":"browser devtools permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Browser DevTools"),"\n",s.createElement(n.ol,null,"\n",s.createElement(n.li,null,"Open ",s.createElement(n.strong,null,"Network")," tab, load the page, find the document request"),"\n",s.createElement(n.li,null,"View the response and search for ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text"><script></code>'}})," tags containing RSC data"),"\n",s.createElement(n.li,null,"The payload is the JSON-like content between the script tags"),"\n"),"\n",s.createElement(n.h3,{id:"programmatic-extraction",style:{position:"relative"}}
1,s.createElement(n.a,{href:"#programmatic-extraction","aria-label":"programmatic extraction permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Programmatic Extraction"),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="js"><pre class="language-js"><code class="language-js"><span class="token comment">// In browser console: extract RSC payload size</span>\n<span class="token comment">// Heuristic only: inspect your rendered RSC script tags first and adjust the filter if needed.</span>\n<span class="token comment">// If your framework exposes explicit RSC markers/attributes, prefer those over content matching.</span>\n<span class="token keyword">const</span> scripts <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">\'script\'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>\n<span class="token keyword">let</span> rscPayloadSize <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>\nscripts<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">script</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>\n <span class="token comment">// Heuristic: Flight records usually contain element tuples like ["$","div",...]</span>\n <span class="token keyword">if</span> <span class="token punctuation">(</span>script<span class="token punctuation">.</span>textContent <span class="token operator">&&</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\\["\\$","[a-zA-Z]</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>script<span class="token punctuation">.</span>textContent<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>\n rscPayloadSize <span class="token operator">+=</span> <span class="token keyword">new</span> <span class="token class-name">Blob</span><span class="token punctuation">(</span><span class="token punctuation">[</span>script<span class="token punctuation">.</span>textContent<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">.</span>size<span class="token punctuation">;</span>\n <span class="token punctuation">}</span>\n<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>\nconsole<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">RSC payload: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token punctuation">(</span>rscPayloadSize <span class="token operator">/</span> <span class="token number">1024</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toFixed</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> KB</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>'}}),"\n",s.createElement(n.p,null,"This is still an approximation. Validate the marker pattern against how your app emits Flight chunks. For React on Rails specifically, inspect the actual ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text"><script></code>'}})," payload format in your rendered HTML before relying on this heuristic, and adapt the filter condition if your app uses a different wrapper format (a ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">0</code>'}})," result may mean the regex missed your format, not that RSC is disabled)."),"\n",s.createElement(n.h3,{id:"analyzing-payload-composition",style:{position:"relative"}}
1,s.createElement(n.a,{href:"#analyzing-payload-composition","aria-label":"analyzing payload composition permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Analyzing Payload Composition"),"\n",s.createElement(n.p,null,"To understand what's taking up space in your payload, parse the Flight data and categorize the content:"),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="js"><pre class="language-js"><code class="language-js"><span class="token comment">// Rough breakdown of payload composition</span>\n<span class="token keyword">const</span> payload <span class="token operator">=</span> Array<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">\'script\'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>\n <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">script</span><span class="token punctuation">)</span> <span class="token operator">=></span> script<span class="token punctuation">.</span>textContent <span class="token operator">||</span> <span class="token string">\'\'</span><span class="token punctuation">)</span>\n <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">text</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\\["\\$","[a-zA-Z]</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>text<span class="token punctuation">)</span><span class="token punctuation">)</span>\n <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">\'\'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>\n<span class="token keyword">const</span> classNameMatches <span class="token operator">=</span> payload<span class="token punctuation">.</span><span class="token function">match</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">"className":"[^"]*"</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>\n<span class="token keyword">const</span> classNameBytes <span class="token operator">=</span> classNameMatches<span class="token punctuation">.</span><span class="token function">reduce</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">sum<span class="token punctuation">,</span> m</span><span class="token punctuation">)</span> <span class="token operator">=></span> sum <span class="token operator">+</span> <span class="token keyword">new</span> <span class="token class-name">Blob</span><span class="token punctuation">(</span><span class="token punctuation">[</span>m<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">.</span>
1size<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>\n<span class="token keyword">const</span> totalBytes <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Blob</span><span class="token punctuation">(</span><span class="token punctuation">[</span>payload<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">.</span>size<span class="token punctuation">;</span>\nconsole<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">className share: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token punctuation">(</span><span class="token punctuation">(</span>classNameBytes <span class="token operator">/</span> totalBytes<span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toFixed</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">%</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>'}}),"\n",s.createElement(n.p,null,"If className strings account for a large share of your payload, that is a strong signal to investigate this optimization. Even 30%+ can be worth examining on larger pages."),"\n",s.createElement(n.h2,{id:"compression-effectiveness",style:{position:"relative"}},s.createElement(n.a,{href:"#compression-effectiveness","aria-label":"compression effectiveness permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Compression Effectiveness"),"\n",s.createElement(n.p,null,"Modern HTTP compression (gzip, Brotli) partially offsets the bloated payload because repetitive className strings compress well. However, raw payload size still matters for:"),"\n",s.createElement(n.ul,null,"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"Parse time")," -- the browser must parse the full decompressed payload before React can reconcile the tree"),"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"Memory usage")," -- the decompressed payload is held in memory during reconciliation"),"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"Server generation time")," -- serializing larger element trees takes more CPU time on the server"),"\n"),"\n",s.createElement(n.p,null,"In the benchmark above, the payload reduction was significant even after compression because the savings came from eliminating entire subtrees, not just deduplicating strings."),"\n",s.createElement(n.h2,{id:"the-lcp-tradeoff",style:{position:"relative"}},s.createElement(n.a,{href:"#the-lcp-tradeoff","aria-label":"the lcp tradeoff permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"The LCP Tradeoff"),"\n",s.createElement(n.p,null,"Moving presentational components to the client increases the amount of JavaScript the browser must download and execute before those components fully hydrate. This can slightly increase Largest Contentful Paint (LCP):"),"\n",s.createElement(n.ul,null,"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"TTFB and FCP improve")," because the server generates and streams a smaller payload faster"),"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"LCP may increase")," because the converted components now require their JavaScript bundle to be parsed and executed before hydration completes, which can slightly delay when React considers those subtrees ready. This is most noticeable when the LCP element itself sits inside a converted component."),"\n"),"\n",s.createElement(n.p,null,"In the benchmark, LCP increased by 8% (982 ms to 1,058 ms) -- a minor regression offset by the 64% FCP improvement and 42% payload reduction."),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"Recommendation:")," Always benchmark before and after. The tradeoff is favorable when:"),"\n",s.createElement(n.ul,null,"\n",s.createElement(n.li,null,"The payload reduction is large (> 20%)"),"\n",s.createElement(n.li,null,"The client JS increase is small (< 5 KB gzipped)"),"\n",s.createElement(n.li,null,"The page has many repeated components (lists, grids, cards)"),"\n"),"\n",s.createElement(n.p,null,"If LCP is your critical metric (e.g., for a landing page with a hero image), be more conservative about mov
1ing components to the client."),"\n",s.createElement(n.h2,{id:"react-on-rails-double-jsonstringify-resolved",style:{position:"relative"}},s.createElement(n.a,{href:"#react-on-rails-double-jsonstringify-resolved","aria-label":"react on rails double jsonstringify resolved permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"React on Rails: Double JSON.stringify (Resolved)"),"\n",s.createElement(n.p,null,"React on Rails previously double-encoded the RSC payload when embedding it in inline ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text"><script></code>'}})," tags â the Flight payload (already a serialized wire format) was JSON-encoded again, adding ~24% overhead. This was fixed in ",s.createElement(n.a,{href:"https://github.com/shakacode/react_on_rails/issues/2522"},"issue #2522")," with the length-prefixed streaming protocol, which sends HTML content as raw bytes with a length prefix instead of re-encoding it as JSON."),"\n",s.createElement(n.p,null,"The Flight payload optimization patterns in this guide (expansion ratios, presentational client components) remain important regardless â they address the inherent size of the serialized element tree, not the encoding overhead."),"\n",s.createElement(n.h2,{id:"decision-flowchart",style:{position:"relative"}},s.createElement(n.a,{href:"#decision-flowchart","aria-label":"decision flowchart permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Decision Flowchart"),"\n",s.createElement(n.p,null,"Use this flowchart when deciding whether a presentational component should be a Server or Client Component:"),"\n",s.createElement("p",{align:"center"},s.createElement("img",{src:"images/server-client-decision-flowchart.svg",alt:"Static flowchart guiding developers through the decision of whether a component should be a Server Component or Client Component, based on interactivity, server-only resources, repetition ratio, expansion ratio, and bundle cost.",width:"840"})),"\n",s.createElement(n.h2,{id:"summary",style:{position:"relative"}},s.createElement(n.a,{href:"#summary","aria-label":"summary permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Summary"),"\n",s.createElement(n.p,null,'The standard RSC advice -- "make everything a Server Component unless it needs interactivity" -- is a good starting point but not the full picture. For presentational components with high expansion ratios that render many times on a page, moving them to Client Components can dramatically reduce the Flight payload with minimal JS cost. Always measure to confirm the tradeoff is favorable for your specific page.'),"\n",s.createElement(n.h2,{id:"related-articles",style:{position:"relative"}}
1,s.createElement(n.a,{href:"#related-articles","aria-label":"related articles permalink",className:"anchor before"},s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Related Articles"),"\n",s.createElement(n.ul,null,"\n",s.createElement(n.li,null,s.createElement(n.a,{href:"/linked-assets/8658e14f4fb3fcb41ed0c45060e00899/rsc-component-patterns.md"},"Component Tree Restructuring Patterns")," -- the foundational patterns for splitting server and client components"),"\n",s.createElement(n.li,null,s.createElement(n.a,{href:"/linked-assets/95b3d10509bb106251ff4d4866187802/rsc-troubleshooting.md"},"Troubleshooting and Common Pitfalls")," -- debugging payload duplication and other RSC issues"),"\n",s.createElement(n.li,null,s.createElement(n.a,{href:"/linked-assets/ac508aaab32d6164befba4ceae1e5634/rsc-data-fetching.md"},"Data Fetching Migration")," -- migrating data-fetching patterns to Server Components"),"\n"))}var o=function(e){void 0===e&&(e={});const{wrapper:n}=Object.assign({},(0,t.R)(),e.components);return n?s.createElement(n,e,s.createElement(l,e)):l(e)},p=a(63679),c=a(95197),r=a(47388),i=a(23690),u=a(14487);const m=p.default.p.withConfig({displayName:"doc-article__RedirectFallback",componentId:"sc-tic2w5-0"})(["padding:2rem;"]),d=e=>{let{data:n,location:a,children:t}=e;const{headings:l}=n.article.childMdx,o=(0,c.X9)(a.pathname),[p,i]=s.useState(null),d=a.pathname.split("/"),h=d.indexOf("docs"),g=-1===h?a.pathname.length:d.slice(0,h+1).join("/").length,k=a.pathname.slice(0,g),f=a.pathname.slice(g+1).replace(/\/$/,"").split("/").filter((e=>""!==e)),y=f.length>1?f.slice(0,-1).join("/"):"";s.useEffect((()=>{if(!o)return;const{hash:e}=window.location;i(e);const n=""+o+e;window.location.href!==n&&window.location.replace(n)}),[o]);const v=null===o||null===p?null:""+o+p;return s.createElement(s.Fragment,null,null!==v?s.createElement(m,{role:"status","aria-live":"polite"},"Redirecting..."," ",s.createElement("a",{href:v,target:"_blank",rel:"noopener noreferrer"},"Click here if not redirected.")):s.createElement(r.A,{main:s.createElement(u.A,{body:t,headings:l,transformUrl:e=>{if(e.startsWith("http")||e.startsWith("#"))return e;const n=e.replace(/\.md$/,"/");if(n.startsWith("./"))return k+(""===y?"":"/"+y)+n.slice(1);if(n.startsWith("../")){if(""===y)return""+k+n.slice(2);const e=y.split("/").slice(0,-1).join("/");return k+(""===e?"":"/"+e)+n.slice(2)}return k+"/"+(""===y?"":y+"/")+n}})}))};function h(e){return s.createElement(d,e,s.createElement(o,e))}const g=e=>{let{data:n,location:a,pageContext:t}=e;const{headings:l}=n.article.childMdx,{siteUrl:o}=n.site.siteMetadata,{repoDisplayName:p}=t,r=l.find((e=>1===e.depth)),u=(0,c.X9)(a.pathname)||""+o.replace(/\/+$/,"")+a.pathname;return s.createElement(i.A,{title:r?r.value:p,description:r?r.value:p+" documentation",isArticle:!0,canonical:u,pathname:a.pathname})}}}]); 2//# sourceMappingURL=component---src-template-doc-article-tsx-content-file-path-cache-gatsby-source-git-react-on-rails-docs-oss-migrating-rsc-flight-payload-md-79a70a347b6368af086f.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.