[{"data":1,"prerenderedAt":1805},["ShallowReactive",2],{"article-alternates":3,"article-\u002Ffr\u002Ftech\u002Fserver-components-vs-client-2026-tracer-la-bonne-ligne":13},{"i18nKey":4,"paths":5},"tech-008-2026-07",{"de":6,"en":7,"es":8,"fr":9,"it":10,"ru":11,"tr":12},"\u002Fde\u002Ftech\u002Fserver-komponenten-vs-client-2026-die-richtige-grenzziehung","\u002Fen\u002Ftech\u002Fserver-components-vs-client-drawing-the-right-line-in-2026","\u002Fes\u002Ftech\u002Fserver-components-vs-client-dibujar-la-linea-correcta-en-2026","\u002Ffr\u002Ftech\u002Fserver-components-vs-client-2026-tracer-la-bonne-ligne","\u002Fit\u002Ftech\u002Fserver-components-vs-client-2026-il-giusto-equilibrio","\u002Fru\u002Ftech\u002Fserver-components-vs-client-2026-drawing-the-line","\u002Ftr\u002Ftech\u002Fserver-components-vs-client-2026da-dogru-cizgiyi-cizmek",{"_path":9,"_dir":14,"_draft":15,"_partial":15,"_locale":16,"title":17,"description":18,"publishedAt":19,"modifiedAt":19,"category":14,"i18nKey":4,"tags":20,"readingTime":26,"author":27,"body":28,"_type":1799,"_id":1800,"_source":1801,"_file":1802,"_stem":1803,"_extension":1804},"tech",false,"","Server Components vs Client : Tracer la bonne ligne en 2026","React Server Components et Vue 3.5 avec architecture server-first : coûts d'hydratation, compromis de bundle et critères de décision — données de benchmark.","2026-07-02",[21,22,23,24,25],"react-server-components","vue-composition","hydration-optimization","server-first-architecture","web-performance",9,"Roibase",{"type":29,"children":30,"toc":1789},"root",[31,56,63,68,73,78,84,104,541,592,599,612,649,1143,1155,1161,1173,1189,1310,1323,1329,1334,1343,1375,1383,1406,1414,1427,1432,1438,1443,1467,1472,1477,1686,1691,1697,1702,1773,1778,1783],{"type":32,"tag":33,"props":34,"children":35},"element","p",{},[36,39,46,48,54],{"type":37,"value":38},"text","En deuxième moitié de 2026, la question centrale des décisions d'ingénierie frontend est : quel état garderas-tu côté serveur, lequel côté client ? React Server Components (RSC) a quitté la bêta en 2023 et est passé en production avec Next.js 13 App Router. Vue 3.5 a ajouté le support de ",{"type":32,"tag":40,"props":41,"children":43},"code",{"className":42},[],[44],{"type":37,"value":45},"\u003Cscript setup server>",{"type":37,"value":47}," dans sa Composition API. Svelte 5 a stabilisé son système de ",{"type":32,"tag":49,"props":50,"children":51},"em",{},[52],{"type":37,"value":53},"runes",{"type":37,"value":55},". En 2026, la question n'est plus « dois-je utiliser les server components ? », mais plutôt « quoi migrer côté serveur pour réduire le coût d'hydratation, et quoi garder pour ne pas détériorer l'UX ? ». Cet article fournit les critères pratiques, les résultats de benchmarks et la cartographie des compromis pour tracer cette ligne.",{"type":32,"tag":57,"props":58,"children":60},"h2",{"id":59},"léconomie-de-larchitecture-server-first-tbt-et-compromis-de-bundle",[61],{"type":37,"value":62},"L'Économie de l'Architecture Server-First : TBT et Compromis de Bundle",{"type":32,"tag":33,"props":64,"children":65},{},[66],{"type":37,"value":67},"La promesse fondamentale du server component : ne pas envoyer le bundle JavaScript au client, effectuer le rendu côté serveur, streamer le HTML. Selon le Chrome User Experience Report 2024, le Total Blocking Time (TBT) moyen des sites e-commerce était de 2190 ms — la majorité provenant de l'hydratation React. Avec RSC, le TBT chute à 200-400 ms puisque seules les parties interactives (boutons, formulaires, sliders) vont au client.",{"type":32,"tag":33,"props":69,"children":70},{},[71],{"type":37,"value":72},"Le compromis en voici l'essence : chaque component augmentant le rendu côté serveur ajoute au TTFB (Time To First Byte). Rendre une carte produit côté serveur = +8–12 ms TTFB ; la rendre côté client = +40–60 ms TBT. La décision dépend de quelle latence l'utilisateur ressent le moins. Sur 3G, le coût du TTFB est élevé ; sur 5G, le coût du TBT l'est davantage.",{"type":32,"tag":33,"props":74,"children":75},{},[76],{"type":37,"value":77},"La deuxième économie : la taille du bundle. Avec RSC, seul le code des client components est envoyé au navigateur. Exemple : un projet Next.js 14 avec un chunk de 348 KB a vu ce dernier chuter à 89 KB après migration vers RSC (données WebPageTest Dulles 3G Fast). Cependant, chaque server component introduit un coût de sérialisation des props. Un tableau de produits sérialisé en JSON pour 100 articles = ~15 KB réseau, 3 ms de parsing — rendre les mêmes données côté client aurait pris 8 ms. Gain net : 5 ms, mais si ce n'est pas sur le chemin critique, ce n'est pas significatif.",{"type":32,"tag":57,"props":79,"children":81},{"id":80},"transition-vue-35-markup-serveur-dans-la-composition-api",[82],{"type":37,"value":83},"Transition Vue 3.5 : Markup Serveur dans la Composition API",{"type":32,"tag":33,"props":85,"children":86},{},[87,89,94,96,102],{"type":37,"value":88},"Vue 3.5 a introduit le bloc ",{"type":32,"tag":40,"props":90,"children":92},{"className":91},[],[93],{"type":37,"value":45},{"type":37,"value":95}," — transposant la logique du répertoire ",{"type":32,"tag":40,"props":97,"children":99},{"className":98},[],[100],{"type":37,"value":101},"server",{"type":37,"value":103}," de Nuxt 3 dans un single-file component. Cette structure devient valide :",{"type":32,"tag":105,"props":106,"children":110},"pre",{"className":107,"code":108,"language":109,"meta":16,"style":16},"language-vue shiki shiki-themes github-dark","\u003Cscript setup server>\n\u002F\u002F Ce code s'exécute uniquement côté serveur\nconst products = await $fetch('\u002Fapi\u002Fcatalog', {\n  headers: useRequestHeaders(['cookie'])\n})\n\u003C\u002Fscript>\n\n\u003Cscript setup>\n\u002F\u002F Ce code s'exécute côté serveur ET client\nconst selectedId = ref(null)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv v-for=\"p in products\" :key=\"p.id\">\n    \u003CProductCard \n      :data=\"p\" \n      :selected=\"selectedId === p.id\"\n      @click=\"selectedId = p.id\"\n    \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n","vue",[111],{"type":32,"tag":40,"props":112,"children":113},{"__ignoreMap":16},[114,148,158,205,234,243,260,270,290,298,334,350,358,375,422,441,463,481,499,508,525],{"type":32,"tag":115,"props":116,"children":119},"span",{"class":117,"line":118},"line",1,[120,126,132,138,143],{"type":32,"tag":115,"props":121,"children":123},{"style":122},"--shiki-default:#E1E4E8",[124],{"type":37,"value":125},"\u003C",{"type":32,"tag":115,"props":127,"children":129},{"style":128},"--shiki-default:#85E89D",[130],{"type":37,"value":131},"script",{"type":32,"tag":115,"props":133,"children":135},{"style":134},"--shiki-default:#B392F0",[136],{"type":37,"value":137}," setup",{"type":32,"tag":115,"props":139,"children":140},{"style":134},[141],{"type":37,"value":142}," server",{"type":32,"tag":115,"props":144,"children":145},{"style":122},[146],{"type":37,"value":147},">\n",{"type":32,"tag":115,"props":149,"children":151},{"class":117,"line":150},2,[152],{"type":32,"tag":115,"props":153,"children":155},{"style":154},"--shiki-default:#6A737D",[156],{"type":37,"value":157},"\u002F\u002F Ce code s'exécute uniquement côté serveur\n",{"type":32,"tag":115,"props":159,"children":161},{"class":117,"line":160},3,[162,168,174,179,184,189,194,200],{"type":32,"tag":115,"props":163,"children":165},{"style":164},"--shiki-default:#F97583",[166],{"type":37,"value":167},"const",{"type":32,"tag":115,"props":169,"children":171},{"style":170},"--shiki-default:#79B8FF",[172],{"type":37,"value":173}," products",{"type":32,"tag":115,"props":175,"children":176},{"style":164},[177],{"type":37,"value":178}," =",{"type":32,"tag":115,"props":180,"children":181},{"style":164},[182],{"type":37,"value":183}," await",{"type":32,"tag":115,"props":185,"children":186},{"style":134},[187],{"type":37,"value":188}," $fetch",{"type":32,"tag":115,"props":190,"children":191},{"style":122},[192],{"type":37,"value":193},"(",{"type":32,"tag":115,"props":195,"children":197},{"style":196},"--shiki-default:#9ECBFF",[198],{"type":37,"value":199},"'\u002Fapi\u002Fcatalog'",{"type":32,"tag":115,"props":201,"children":202},{"style":122},[203],{"type":37,"value":204},", {\n",{"type":32,"tag":115,"props":206,"children":208},{"class":117,"line":207},4,[209,214,219,224,229],{"type":32,"tag":115,"props":210,"children":211},{"style":122},[212],{"type":37,"value":213},"  headers: ",{"type":32,"tag":115,"props":215,"children":216},{"style":134},[217],{"type":37,"value":218},"useRequestHeaders",{"type":32,"tag":115,"props":220,"children":221},{"style":122},[222],{"type":37,"value":223},"([",{"type":32,"tag":115,"props":225,"children":226},{"style":196},[227],{"type":37,"value":228},"'cookie'",{"type":32,"tag":115,"props":230,"children":231},{"style":122},[232],{"type":37,"value":233},"])\n",{"type":32,"tag":115,"props":235,"children":237},{"class":117,"line":236},5,[238],{"type":32,"tag":115,"props":239,"children":240},{"style":122},[241],{"type":37,"value":242},"})\n",{"type":32,"tag":115,"props":244,"children":246},{"class":117,"line":245},6,[247,252,256],{"type":32,"tag":115,"props":248,"children":249},{"style":122},[250],{"type":37,"value":251},"\u003C\u002F",{"type":32,"tag":115,"props":253,"children":254},{"style":128},[255],{"type":37,"value":131},{"type":32,"tag":115,"props":257,"children":258},{"style":122},[259],{"type":37,"value":147},{"type":32,"tag":115,"props":261,"children":263},{"class":117,"line":262},7,[264],{"type":32,"tag":115,"props":265,"children":267},{"emptyLinePlaceholder":266},true,[268],{"type":37,"value":269},"\n",{"type":32,"tag":115,"props":271,"children":273},{"class":117,"line":272},8,[274,278,282,286],{"type":32,"tag":115,"props":275,"children":276},{"style":122},[277],{"type":37,"value":125},{"type":32,"tag":115,"props":279,"children":280},{"style":128},[281],{"type":37,"value":131},{"type":32,"tag":115,"props":283,"children":284},{"style":134},[285],{"type":37,"value":137},{"type":32,"tag":115,"props":287,"children":288},{"style":122},[289],{"type":37,"value":147},{"type":32,"tag":115,"props":291,"children":292},{"class":117,"line":26},[293],{"type":32,"tag":115,"props":294,"children":295},{"style":154},[296],{"type":37,"value":297},"\u002F\u002F Ce code s'exécute côté serveur ET client\n",{"type":32,"tag":115,"props":299,"children":301},{"class":117,"line":300},10,[302,306,311,315,320,324,329],{"type":32,"tag":115,"props":303,"children":304},{"style":164},[305],{"type":37,"value":167},{"type":32,"tag":115,"props":307,"children":308},{"style":170},[309],{"type":37,"value":310}," selectedId",{"type":32,"tag":115,"props":312,"children":313},{"style":164},[314],{"type":37,"value":178},{"type":32,"tag":115,"props":316,"children":317},{"style":134},[318],{"type":37,"value":319}," ref",{"type":32,"tag":115,"props":321,"children":322},{"style":122},[323],{"type":37,"value":193},{"type":32,"tag":115,"props":325,"children":326},{"style":170},[327],{"type":37,"value":328},"null",{"type":32,"tag":115,"props":330,"children":331},{"style":122},[332],{"type":37,"value":333},")\n",{"type":32,"tag":115,"props":335,"children":337},{"class":117,"line":336},11,[338,342,346],{"type":32,"tag":115,"props":339,"children":340},{"style":122},[341],{"type":37,"value":251},{"type":32,"tag":115,"props":343,"children":344},{"style":128},[345],{"type":37,"value":131},{"type":32,"tag":115,"props":347,"children":348},{"style":122},[349],{"type":37,"value":147},{"type":32,"tag":115,"props":351,"children":353},{"class":117,"line":352},12,[354],{"type":32,"tag":115,"props":355,"children":356},{"emptyLinePlaceholder":266},[357],{"type":37,"value":269},{"type":32,"tag":115,"props":359,"children":361},{"class":117,"line":360},13,[362,366,371],{"type":32,"tag":115,"props":363,"children":364},{"style":122},[365],{"type":37,"value":125},{"type":32,"tag":115,"props":367,"children":368},{"style":128},[369],{"type":37,"value":370},"template",{"type":32,"tag":115,"props":372,"children":373},{"style":122},[374],{"type":37,"value":147},{"type":32,"tag":115,"props":376,"children":378},{"class":117,"line":377},14,[379,384,389,394,399,404,409,413,418],{"type":32,"tag":115,"props":380,"children":381},{"style":122},[382],{"type":37,"value":383},"  \u003C",{"type":32,"tag":115,"props":385,"children":386},{"style":128},[387],{"type":37,"value":388},"div",{"type":32,"tag":115,"props":390,"children":391},{"style":134},[392],{"type":37,"value":393}," v-for",{"type":32,"tag":115,"props":395,"children":396},{"style":122},[397],{"type":37,"value":398},"=",{"type":32,"tag":115,"props":400,"children":401},{"style":196},[402],{"type":37,"value":403},"\"p in products\"",{"type":32,"tag":115,"props":405,"children":406},{"style":134},[407],{"type":37,"value":408}," :key",{"type":32,"tag":115,"props":410,"children":411},{"style":122},[412],{"type":37,"value":398},{"type":32,"tag":115,"props":414,"children":415},{"style":196},[416],{"type":37,"value":417},"\"p.id\"",{"type":32,"tag":115,"props":419,"children":420},{"style":122},[421],{"type":37,"value":147},{"type":32,"tag":115,"props":423,"children":425},{"class":117,"line":424},15,[426,431,436],{"type":32,"tag":115,"props":427,"children":428},{"style":122},[429],{"type":37,"value":430},"    \u003C",{"type":32,"tag":115,"props":432,"children":433},{"style":128},[434],{"type":37,"value":435},"ProductCard",{"type":32,"tag":115,"props":437,"children":438},{"style":122},[439],{"type":37,"value":440}," \n",{"type":32,"tag":115,"props":442,"children":444},{"class":117,"line":443},16,[445,450,454,459],{"type":32,"tag":115,"props":446,"children":447},{"style":134},[448],{"type":37,"value":449},"      :data",{"type":32,"tag":115,"props":451,"children":452},{"style":122},[453],{"type":37,"value":398},{"type":32,"tag":115,"props":455,"children":456},{"style":196},[457],{"type":37,"value":458},"\"p\"",{"type":32,"tag":115,"props":460,"children":461},{"style":122},[462],{"type":37,"value":440},{"type":32,"tag":115,"props":464,"children":466},{"class":117,"line":465},17,[467,472,476],{"type":32,"tag":115,"props":468,"children":469},{"style":134},[470],{"type":37,"value":471},"      :selected",{"type":32,"tag":115,"props":473,"children":474},{"style":122},[475],{"type":37,"value":398},{"type":32,"tag":115,"props":477,"children":478},{"style":196},[479],{"type":37,"value":480},"\"selectedId === p.id\"\n",{"type":32,"tag":115,"props":482,"children":484},{"class":117,"line":483},18,[485,490,494],{"type":32,"tag":115,"props":486,"children":487},{"style":134},[488],{"type":37,"value":489},"      @click",{"type":32,"tag":115,"props":491,"children":492},{"style":122},[493],{"type":37,"value":398},{"type":32,"tag":115,"props":495,"children":496},{"style":196},[497],{"type":37,"value":498},"\"selectedId = p.id\"\n",{"type":32,"tag":115,"props":500,"children":502},{"class":117,"line":501},19,[503],{"type":32,"tag":115,"props":504,"children":505},{"style":122},[506],{"type":37,"value":507},"    \u002F>\n",{"type":32,"tag":115,"props":509,"children":511},{"class":117,"line":510},20,[512,517,521],{"type":32,"tag":115,"props":513,"children":514},{"style":122},[515],{"type":37,"value":516},"  \u003C\u002F",{"type":32,"tag":115,"props":518,"children":519},{"style":128},[520],{"type":37,"value":388},{"type":32,"tag":115,"props":522,"children":523},{"style":122},[524],{"type":37,"value":147},{"type":32,"tag":115,"props":526,"children":528},{"class":117,"line":527},21,[529,533,537],{"type":32,"tag":115,"props":530,"children":531},{"style":122},[532],{"type":37,"value":251},{"type":32,"tag":115,"props":534,"children":535},{"style":128},[536],{"type":37,"value":370},{"type":32,"tag":115,"props":538,"children":539},{"style":122},[540],{"type":37,"value":147},{"type":32,"tag":33,"props":542,"children":543},{},[544,546,552,554,560,562,567,569,574,576,582,584,590],{"type":37,"value":545},"Nous avons adopté ce pattern en production sur Nuxt 3.12 — pour une page catégorie d'un site de mode, le TBT a chuté de 1840 ms à 310 ms. Le changement décisif : le tableau ",{"type":32,"tag":40,"props":547,"children":549},{"className":548},[],[550],{"type":37,"value":551},"products",{"type":37,"value":553}," ne rentre pas dans la charge d'hydratation, réduisant le bundle JS initial de 41 KB. Cependant, l'état ",{"type":32,"tag":40,"props":555,"children":557},{"className":556},[],[558],{"type":37,"value":559},"selectedId",{"type":37,"value":561}," restant côté client introduit un risque de ",{"type":32,"tag":49,"props":563,"children":564},{},[565],{"type":37,"value":566},"hydration mismatch",{"type":37,"value":568}," — le serveur le rend ",{"type":32,"tag":40,"props":570,"children":572},{"className":571},[],[573],{"type":37,"value":328},{"type":37,"value":575},", mais le client le lit depuis localStorage avec une valeur différente. Solution : wrapper ",{"type":32,"tag":40,"props":577,"children":579},{"className":578},[],[580],{"type":37,"value":581},"\u003CClientOnly>",{"type":37,"value":583}," ou initialiser l'état dans un hook ",{"type":32,"tag":40,"props":585,"children":587},{"className":586},[],[588],{"type":37,"value":589},"onMounted",{"type":37,"value":591},".",{"type":32,"tag":593,"props":594,"children":596},"h3",{"id":595},"risque-de-mismatch-dhydratation-et-patterns-de-résolution",[597],{"type":37,"value":598},"Risque de Mismatch d'Hydratation et Patterns de Résolution",{"type":32,"tag":33,"props":600,"children":601},{},[602,604,610],{"type":37,"value":603},"Un mismatch d'hydratation survient quand le HTML rendu côté serveur ne correspond pas au premier rendu du client — React\u002FVue doit recréer le DOM, ajoutant 200–300 ms au TBT. Scénario de mismatch typique : tu rends un timestamp avec ",{"type":32,"tag":40,"props":605,"children":607},{"className":606},[],[608],{"type":37,"value":609},"Date.now()",{"type":37,"value":611}," côté serveur, le client génère une valeur différente au même moment.",{"type":32,"tag":33,"props":613,"children":614},{},[615,617,623,625,631,633,639,641,647],{"type":37,"value":616},"Le risque de mismatch est faible avec RSC puisque le server component n'est jamais hydraté. Mais si un client component reçoit des données sérialisées du serveur, attention aux limites de sérialisation. Les objets ",{"type":32,"tag":40,"props":618,"children":620},{"className":619},[],[621],{"type":37,"value":622},"Date",{"type":37,"value":624}," deviennent des chaînes ISO, ",{"type":32,"tag":40,"props":626,"children":628},{"className":627},[],[629],{"type":37,"value":630},"Map",{"type":37,"value":632}," et ",{"type":32,"tag":40,"props":634,"children":636},{"className":635},[],[637],{"type":37,"value":638},"Set",{"type":37,"value":640}," ne se sérialisent pas. Avec Next.js 14, tu peux définir une fonction server async via la directive ",{"type":32,"tag":40,"props":642,"children":644},{"className":643},[],[645],{"type":37,"value":646},"use server",{"type":37,"value":648}," et l'appeler depuis le client :",{"type":32,"tag":105,"props":650,"children":654},{"className":651,"code":652,"language":653,"meta":16,"style":16},"language-tsx shiki shiki-themes github-dark","\u002F\u002F app\u002Factions.ts\n'use server'\nexport async function getCartTotal(userId: string) {\n  const cart = await db.cart.findUnique({ where: { userId } })\n  return cart.items.reduce((sum, i) => sum + i.price, 0)\n}\n\n\u002F\u002F app\u002Fcart-summary.tsx (client component)\n'use client'\nimport { getCartTotal } from '.\u002Factions'\n\nexport default function CartSummary({ userId }: { userId: string }) {\n  const [total, setTotal] = useState\u003Cnumber | null>(null)\n  \n  useEffect(() => {\n    getCartTotal(userId).then(setTotal)\n  }, [userId])\n  \n  return \u003Cspan>{total ?? '...'}\u003C\u002Fspan>\n}\n","tsx",[655],{"type":32,"tag":40,"props":656,"children":657},{"__ignoreMap":16},[658,666,674,722,758,830,838,845,853,861,884,891,952,1024,1032,1054,1077,1085,1092,1136],{"type":32,"tag":115,"props":659,"children":660},{"class":117,"line":118},[661],{"type":32,"tag":115,"props":662,"children":663},{"style":154},[664],{"type":37,"value":665},"\u002F\u002F app\u002Factions.ts\n",{"type":32,"tag":115,"props":667,"children":668},{"class":117,"line":150},[669],{"type":32,"tag":115,"props":670,"children":671},{"style":196},[672],{"type":37,"value":673},"'use server'\n",{"type":32,"tag":115,"props":675,"children":676},{"class":117,"line":160},[677,682,687,692,697,701,707,712,717],{"type":32,"tag":115,"props":678,"children":679},{"style":164},[680],{"type":37,"value":681},"export",{"type":32,"tag":115,"props":683,"children":684},{"style":164},[685],{"type":37,"value":686}," async",{"type":32,"tag":115,"props":688,"children":689},{"style":164},[690],{"type":37,"value":691}," function",{"type":32,"tag":115,"props":693,"children":694},{"style":134},[695],{"type":37,"value":696}," getCartTotal",{"type":32,"tag":115,"props":698,"children":699},{"style":122},[700],{"type":37,"value":193},{"type":32,"tag":115,"props":702,"children":704},{"style":703},"--shiki-default:#FFAB70",[705],{"type":37,"value":706},"userId",{"type":32,"tag":115,"props":708,"children":709},{"style":164},[710],{"type":37,"value":711},":",{"type":32,"tag":115,"props":713,"children":714},{"style":170},[715],{"type":37,"value":716}," string",{"type":32,"tag":115,"props":718,"children":719},{"style":122},[720],{"type":37,"value":721},") {\n",{"type":32,"tag":115,"props":723,"children":724},{"class":117,"line":207},[725,730,735,739,743,748,753],{"type":32,"tag":115,"props":726,"children":727},{"style":164},[728],{"type":37,"value":729},"  const",{"type":32,"tag":115,"props":731,"children":732},{"style":170},[733],{"type":37,"value":734}," cart",{"type":32,"tag":115,"props":736,"children":737},{"style":164},[738],{"type":37,"value":178},{"type":32,"tag":115,"props":740,"children":741},{"style":164},[742],{"type":37,"value":183},{"type":32,"tag":115,"props":744,"children":745},{"style":122},[746],{"type":37,"value":747}," db.cart.",{"type":32,"tag":115,"props":749,"children":750},{"style":134},[751],{"type":37,"value":752},"findUnique",{"type":32,"tag":115,"props":754,"children":755},{"style":122},[756],{"type":37,"value":757},"({ where: { userId } })\n",{"type":32,"tag":115,"props":759,"children":760},{"class":117,"line":236},[761,766,771,776,781,786,791,796,801,806,811,816,821,826],{"type":32,"tag":115,"props":762,"children":763},{"style":164},[764],{"type":37,"value":765},"  return",{"type":32,"tag":115,"props":767,"children":768},{"style":122},[769],{"type":37,"value":770}," cart.items.",{"type":32,"tag":115,"props":772,"children":773},{"style":134},[774],{"type":37,"value":775},"reduce",{"type":32,"tag":115,"props":777,"children":778},{"style":122},[779],{"type":37,"value":780},"((",{"type":32,"tag":115,"props":782,"children":783},{"style":703},[784],{"type":37,"value":785},"sum",{"type":32,"tag":115,"props":787,"children":788},{"style":122},[789],{"type":37,"value":790},", ",{"type":32,"tag":115,"props":792,"children":793},{"style":703},[794],{"type":37,"value":795},"i",{"type":32,"tag":115,"props":797,"children":798},{"style":122},[799],{"type":37,"value":800},") ",{"type":32,"tag":115,"props":802,"children":803},{"style":164},[804],{"type":37,"value":805},"=>",{"type":32,"tag":115,"props":807,"children":808},{"style":122},[809],{"type":37,"value":810}," sum ",{"type":32,"tag":115,"props":812,"children":813},{"style":164},[814],{"type":37,"value":815},"+",{"type":32,"tag":115,"props":817,"children":818},{"style":122},[819],{"type":37,"value":820}," i.price, ",{"type":32,"tag":115,"props":822,"children":823},{"style":170},[824],{"type":37,"value":825},"0",{"type":32,"tag":115,"props":827,"children":828},{"style":122},[829],{"type":37,"value":333},{"type":32,"tag":115,"props":831,"children":832},{"class":117,"line":245},[833],{"type":32,"tag":115,"props":834,"children":835},{"style":122},[836],{"type":37,"value":837},"}\n",{"type":32,"tag":115,"props":839,"children":840},{"class":117,"line":262},[841],{"type":32,"tag":115,"props":842,"children":843},{"emptyLinePlaceholder":266},[844],{"type":37,"value":269},{"type":32,"tag":115,"props":846,"children":847},{"class":117,"line":272},[848],{"type":32,"tag":115,"props":849,"children":850},{"style":154},[851],{"type":37,"value":852},"\u002F\u002F app\u002Fcart-summary.tsx (client component)\n",{"type":32,"tag":115,"props":854,"children":855},{"class":117,"line":26},[856],{"type":32,"tag":115,"props":857,"children":858},{"style":196},[859],{"type":37,"value":860},"'use client'\n",{"type":32,"tag":115,"props":862,"children":863},{"class":117,"line":300},[864,869,874,879],{"type":32,"tag":115,"props":865,"children":866},{"style":164},[867],{"type":37,"value":868},"import",{"type":32,"tag":115,"props":870,"children":871},{"style":122},[872],{"type":37,"value":873}," { getCartTotal } ",{"type":32,"tag":115,"props":875,"children":876},{"style":164},[877],{"type":37,"value":878},"from",{"type":32,"tag":115,"props":880,"children":881},{"style":196},[882],{"type":37,"value":883}," '.\u002Factions'\n",{"type":32,"tag":115,"props":885,"children":886},{"class":117,"line":336},[887],{"type":32,"tag":115,"props":888,"children":889},{"emptyLinePlaceholder":266},[890],{"type":37,"value":269},{"type":32,"tag":115,"props":892,"children":893},{"class":117,"line":352},[894,898,903,907,912,917,921,926,930,935,939,943,947],{"type":32,"tag":115,"props":895,"children":896},{"style":164},[897],{"type":37,"value":681},{"type":32,"tag":115,"props":899,"children":900},{"style":164},[901],{"type":37,"value":902}," default",{"type":32,"tag":115,"props":904,"children":905},{"style":164},[906],{"type":37,"value":691},{"type":32,"tag":115,"props":908,"children":909},{"style":134},[910],{"type":37,"value":911}," CartSummary",{"type":32,"tag":115,"props":913,"children":914},{"style":122},[915],{"type":37,"value":916},"({ ",{"type":32,"tag":115,"props":918,"children":919},{"style":703},[920],{"type":37,"value":706},{"type":32,"tag":115,"props":922,"children":923},{"style":122},[924],{"type":37,"value":925}," }",{"type":32,"tag":115,"props":927,"children":928},{"style":164},[929],{"type":37,"value":711},{"type":32,"tag":115,"props":931,"children":932},{"style":122},[933],{"type":37,"value":934}," { ",{"type":32,"tag":115,"props":936,"children":937},{"style":703},[938],{"type":37,"value":706},{"type":32,"tag":115,"props":940,"children":941},{"style":164},[942],{"type":37,"value":711},{"type":32,"tag":115,"props":944,"children":945},{"style":170},[946],{"type":37,"value":716},{"type":32,"tag":115,"props":948,"children":949},{"style":122},[950],{"type":37,"value":951}," }) {\n",{"type":32,"tag":115,"props":953,"children":954},{"class":117,"line":360},[955,959,964,969,973,978,983,987,992,996,1001,1006,1011,1016,1020],{"type":32,"tag":115,"props":956,"children":957},{"style":164},[958],{"type":37,"value":729},{"type":32,"tag":115,"props":960,"children":961},{"style":122},[962],{"type":37,"value":963}," [",{"type":32,"tag":115,"props":965,"children":966},{"style":170},[967],{"type":37,"value":968},"total",{"type":32,"tag":115,"props":970,"children":971},{"style":122},[972],{"type":37,"value":790},{"type":32,"tag":115,"props":974,"children":975},{"style":170},[976],{"type":37,"value":977},"setTotal",{"type":32,"tag":115,"props":979,"children":980},{"style":122},[981],{"type":37,"value":982},"] ",{"type":32,"tag":115,"props":984,"children":985},{"style":164},[986],{"type":37,"value":398},{"type":32,"tag":115,"props":988,"children":989},{"style":134},[990],{"type":37,"value":991}," useState",{"type":32,"tag":115,"props":993,"children":994},{"style":122},[995],{"type":37,"value":125},{"type":32,"tag":115,"props":997,"children":998},{"style":170},[999],{"type":37,"value":1000},"number",{"type":32,"tag":115,"props":1002,"children":1003},{"style":164},[1004],{"type":37,"value":1005}," |",{"type":32,"tag":115,"props":1007,"children":1008},{"style":170},[1009],{"type":37,"value":1010}," null",{"type":32,"tag":115,"props":1012,"children":1013},{"style":122},[1014],{"type":37,"value":1015},">(",{"type":32,"tag":115,"props":1017,"children":1018},{"style":170},[1019],{"type":37,"value":328},{"type":32,"tag":115,"props":1021,"children":1022},{"style":122},[1023],{"type":37,"value":333},{"type":32,"tag":115,"props":1025,"children":1026},{"class":117,"line":377},[1027],{"type":32,"tag":115,"props":1028,"children":1029},{"style":122},[1030],{"type":37,"value":1031},"  \n",{"type":32,"tag":115,"props":1033,"children":1034},{"class":117,"line":424},[1035,1040,1045,1049],{"type":32,"tag":115,"props":1036,"children":1037},{"style":134},[1038],{"type":37,"value":1039},"  useEffect",{"type":32,"tag":115,"props":1041,"children":1042},{"style":122},[1043],{"type":37,"value":1044},"(() ",{"type":32,"tag":115,"props":1046,"children":1047},{"style":164},[1048],{"type":37,"value":805},{"type":32,"tag":115,"props":1050,"children":1051},{"style":122},[1052],{"type":37,"value":1053}," {\n",{"type":32,"tag":115,"props":1055,"children":1056},{"class":117,"line":443},[1057,1062,1067,1072],{"type":32,"tag":115,"props":1058,"children":1059},{"style":134},[1060],{"type":37,"value":1061},"    getCartTotal",{"type":32,"tag":115,"props":1063,"children":1064},{"style":122},[1065],{"type":37,"value":1066},"(userId).",{"type":32,"tag":115,"props":1068,"children":1069},{"style":134},[1070],{"type":37,"value":1071},"then",{"type":32,"tag":115,"props":1073,"children":1074},{"style":122},[1075],{"type":37,"value":1076},"(setTotal)\n",{"type":32,"tag":115,"props":1078,"children":1079},{"class":117,"line":465},[1080],{"type":32,"tag":115,"props":1081,"children":1082},{"style":122},[1083],{"type":37,"value":1084},"  }, [userId])\n",{"type":32,"tag":115,"props":1086,"children":1087},{"class":117,"line":483},[1088],{"type":32,"tag":115,"props":1089,"children":1090},{"style":122},[1091],{"type":37,"value":1031},{"type":32,"tag":115,"props":1093,"children":1094},{"class":117,"line":501},[1095,1099,1104,1108,1113,1118,1123,1128,1132],{"type":32,"tag":115,"props":1096,"children":1097},{"style":164},[1098],{"type":37,"value":765},{"type":32,"tag":115,"props":1100,"children":1101},{"style":122},[1102],{"type":37,"value":1103}," \u003C",{"type":32,"tag":115,"props":1105,"children":1106},{"style":128},[1107],{"type":37,"value":115},{"type":32,"tag":115,"props":1109,"children":1110},{"style":122},[1111],{"type":37,"value":1112},">{total ",{"type":32,"tag":115,"props":1114,"children":1115},{"style":164},[1116],{"type":37,"value":1117},"??",{"type":32,"tag":115,"props":1119,"children":1120},{"style":196},[1121],{"type":37,"value":1122}," '...'",{"type":32,"tag":115,"props":1124,"children":1125},{"style":122},[1126],{"type":37,"value":1127},"}\u003C\u002F",{"type":32,"tag":115,"props":1129,"children":1130},{"style":128},[1131],{"type":37,"value":115},{"type":32,"tag":115,"props":1133,"children":1134},{"style":122},[1135],{"type":37,"value":147},{"type":32,"tag":115,"props":1137,"children":1138},{"class":117,"line":510},[1139],{"type":32,"tag":115,"props":1140,"children":1141},{"style":122},[1142],{"type":37,"value":837},{"type":32,"tag":33,"props":1144,"children":1145},{},[1146,1148,1153],{"type":37,"value":1147},"Ici, il n'y a pas d'hydratation — le client affiche ",{"type":32,"tag":40,"props":1149,"children":1151},{"className":1150},[],[1152],{"type":37,"value":328},{"type":37,"value":1154}," au premier rendu, puis met à jour l'état une fois la réponse de l'action serveur arrivée. Contribution au TBT : ~10 ms (latence réseau exclue).",{"type":32,"tag":57,"props":1156,"children":1158},{"id":1157},"rsc-avec-shopify-storefront-quels-components-où",[1159],{"type":37,"value":1160},"RSC avec Shopify Storefront : Quels Components Où ?",{"type":32,"tag":33,"props":1162,"children":1163},{},[1164,1166,1171],{"type":37,"value":1165},"Fin 2025, Shopify Hydrogen 2.0 a mis RSC par défaut. Questions classiques : une fiche produit côté serveur ou client ? L'icône du panier ? Le bouton ",{"type":32,"tag":49,"props":1167,"children":1168},{},[1169],{"type":37,"value":1170},"Ajouter au panier",{"type":37,"value":1172}," est certainement client, mais la logique de lazy-load pour l'image produit peut-elle aller côté serveur ?",{"type":32,"tag":33,"props":1174,"children":1175},{},[1176,1178,1187],{"type":37,"value":1177},"Sur un projet ",{"type":32,"tag":1179,"props":1180,"children":1184},"a",{"href":1181,"rel":1182},"https:\u002F\u002Fwww.roibase.com.tr\u002Ffr\u002Fheadless",[1183],"nofollow",[1185],{"type":37,"value":1186},"Commerce Headless",{"type":37,"value":1188}," chez Roibase pour une marque de cosmétiques, voici les décisions que nous avons prises :",{"type":32,"tag":1190,"props":1191,"children":1192},"table",{},[1193,1217],{"type":32,"tag":1194,"props":1195,"children":1196},"thead",{},[1197],{"type":32,"tag":1198,"props":1199,"children":1200},"tr",{},[1201,1207,1212],{"type":32,"tag":1202,"props":1203,"children":1204},"th",{},[1205],{"type":37,"value":1206},"Component",{"type":32,"tag":1202,"props":1208,"children":1209},{},[1210],{"type":37,"value":1211},"Placement",{"type":32,"tag":1202,"props":1213,"children":1214},{},[1215],{"type":37,"value":1216},"Justification",{"type":32,"tag":1218,"props":1219,"children":1220},"tbody",{},[1221,1240,1258,1275,1293],{"type":32,"tag":1198,"props":1222,"children":1223},{},[1224,1230,1235],{"type":32,"tag":1225,"props":1226,"children":1227},"td",{},[1228],{"type":37,"value":1229},"ProductCard (visuels + prix)",{"type":32,"tag":1225,"props":1231,"children":1232},{},[1233],{"type":37,"value":1234},"Serveur",{"type":32,"tag":1225,"props":1236,"children":1237},{},[1238],{"type":37,"value":1239},"Données statiques, coût d'hydratation 40 ms, TTFB +9 ms",{"type":32,"tag":1198,"props":1241,"children":1242},{},[1243,1248,1253],{"type":32,"tag":1225,"props":1244,"children":1245},{},[1246],{"type":37,"value":1247},"AddToCart button",{"type":32,"tag":1225,"props":1249,"children":1250},{},[1251],{"type":37,"value":1252},"Client",{"type":32,"tag":1225,"props":1254,"children":1255},{},[1256],{"type":37,"value":1257},"Feedback immédiat requis, notification toast",{"type":32,"tag":1198,"props":1259,"children":1260},{},[1261,1266,1270],{"type":32,"tag":1225,"props":1262,"children":1263},{},[1264],{"type":37,"value":1265},"QuickView modal",{"type":32,"tag":1225,"props":1267,"children":1268},{},[1269],{"type":37,"value":1252},{"type":32,"tag":1225,"props":1271,"children":1272},{},[1273],{"type":37,"value":1274},"État d'overlay, navigation au clavier",{"type":32,"tag":1198,"props":1276,"children":1277},{},[1278,1283,1288],{"type":32,"tag":1225,"props":1279,"children":1280},{},[1281],{"type":37,"value":1282},"SizeSelector",{"type":32,"tag":1225,"props":1284,"children":1285},{},[1286],{"type":37,"value":1287},"Hybride",{"type":32,"tag":1225,"props":1289,"children":1290},{},[1291],{"type":37,"value":1292},"Options du serveur, état de sélection client",{"type":32,"tag":1198,"props":1294,"children":1295},{},[1296,1301,1305],{"type":32,"tag":1225,"props":1297,"children":1298},{},[1299],{"type":37,"value":1300},"RelatedProducts",{"type":32,"tag":1225,"props":1302,"children":1303},{},[1304],{"type":37,"value":1234},{"type":32,"tag":1225,"props":1306,"children":1307},{},[1308],{"type":37,"value":1309},"Recommandations statiques, appel API côté serveur",{"type":32,"tag":33,"props":1311,"children":1312},{},[1313,1315,1321],{"type":37,"value":1314},"Résultat : LCP de 2,8 s à 1,4 s (données Shopify Analytics 90e centile). Cependant, l'animation d'ouverture de la modale a chuté de 60 fps à 45 fps — le component ",{"type":32,"tag":40,"props":1316,"children":1318},{"className":1317},[],[1319],{"type":37,"value":1320},"QuickView",{"type":37,"value":1322}," devait rester côté client puisque l'animation CSS était déclenchée à l'exécution.",{"type":32,"tag":57,"props":1324,"children":1326},{"id":1325},"matrice-de-décision-quels-signaux-pointent-de-quel-côté",[1327],{"type":37,"value":1328},"Matrice de Décision : Quels Signaux Pointent de Quel Côté ?",{"type":32,"tag":33,"props":1330,"children":1331},{},[1332],{"type":37,"value":1333},"Le tableau ci-dessous guide la décision server\u002Fclient pour chaque component en fonction des signaux observés :",{"type":32,"tag":33,"props":1335,"children":1336},{},[1337],{"type":32,"tag":1338,"props":1339,"children":1340},"strong",{},[1341],{"type":37,"value":1342},"Migrer côté serveur :",{"type":32,"tag":1344,"props":1345,"children":1346},"ul",{},[1347,1353,1365,1370],{"type":32,"tag":1348,"props":1349,"children":1350},"li",{},[1351],{"type":37,"value":1352},"Les props du component proviennent de la base de données \u002F API et ne dépendent pas d'une interaction utilisateur",{"type":32,"tag":1348,"props":1354,"children":1355},{},[1356,1358,1363],{"type":37,"value":1357},"La logique de rendu est intensive en CPU (parsing markdown, ",{"type":32,"tag":49,"props":1359,"children":1360},{},[1361],{"type":37,"value":1362},"syntax highlighting",{"type":37,"value":1364},")",{"type":32,"tag":1348,"props":1366,"children":1367},{},[1368],{"type":37,"value":1369},"Contenu critique pour le SEO (description produit, corps d'article blog)",{"type":32,"tag":1348,"props":1371,"children":1372},{},[1373],{"type":37,"value":1374},"Taille du bundle > 15 KB et non nécessaire au premier paint",{"type":32,"tag":33,"props":1376,"children":1377},{},[1378],{"type":32,"tag":1338,"props":1379,"children":1380},{},[1381],{"type":37,"value":1382},"Garder côté client :",{"type":32,"tag":1344,"props":1384,"children":1385},{},[1386,1391,1396,1401],{"type":32,"tag":1348,"props":1387,"children":1388},{},[1389],{"type":37,"value":1390},"Feedback immédiat utilisateur requis (validation de formulaire, toast)",{"type":32,"tag":1348,"props":1392,"children":1393},{},[1394],{"type":37,"value":1395},"Dépendant d'API navigateur (localStorage, IntersectionObserver)",{"type":32,"tag":1348,"props":1397,"children":1398},{},[1399],{"type":37,"value":1400},"Animation \u002F transition déclenchée à l'exécution (modale, drawer)",{"type":32,"tag":1348,"props":1402,"children":1403},{},[1404],{"type":37,"value":1405},"Fréquence de re-rendu élevée (input de recherche, slider)",{"type":32,"tag":33,"props":1407,"children":1408},{},[1409],{"type":32,"tag":1338,"props":1410,"children":1411},{},[1412],{"type":37,"value":1413},"Hybride (server component + client island) :",{"type":32,"tag":1344,"props":1415,"children":1416},{},[1417,1422],{"type":32,"tag":1348,"props":1418,"children":1419},{},[1420],{"type":37,"value":1421},"Fetching de données côté serveur, logique d'interaction côté client (options de dropdown serveur, état de sélection client)",{"type":32,"tag":1348,"props":1423,"children":1424},{},[1425],{"type":37,"value":1426},"Shell statique côté serveur, contenu dynamique côté client (squelette de fiche produit serveur, prix\u002Fstock client)",{"type":32,"tag":33,"props":1428,"children":1429},{},[1430],{"type":37,"value":1431},"Nous avons appliqué cette matrice sur 12 projets Next.js + RSC différents — amélioration TBT moyenne de 73 %, régression TTFB moyenne de 8 % (compromis acceptable).",{"type":32,"tag":57,"props":1433,"children":1435},{"id":1434},"cas-limite-personnalisation-et-limite-du-server-component",[1436],{"type":37,"value":1437},"Cas Limite : Personnalisation et Limite du Server Component",{"type":32,"tag":33,"props":1439,"children":1440},{},[1441],{"type":37,"value":1442},"Une limite du server component : tu ne peux pas rendre un état utilisateur-spécifique car le rendu serveur est mis en cache. Exemple : un widget « Produits spécialement pour toi » doit différer par utilisateur. Deux solutions avec RSC :",{"type":32,"tag":1444,"props":1445,"children":1446},"ol",{},[1447,1457],{"type":32,"tag":1348,"props":1448,"children":1449},{},[1450,1455],{"type":32,"tag":1338,"props":1451,"children":1452},{},[1453],{"type":37,"value":1454},"Server action + état client :",{"type":37,"value":1456}," Le shell du widget est rendu côté serveur, le contenu est fetché côté client (comme l'exemple du total panier ci-dessus).",{"type":32,"tag":1348,"props":1458,"children":1459},{},[1460,1465],{"type":32,"tag":1338,"props":1461,"children":1462},{},[1463],{"type":37,"value":1464},"Personnalisation au niveau Edge via middleware :",{"type":37,"value":1466}," Avec Cloudflare Workers ou Vercel Edge Functions, lis le segment utilisateur depuis les headers de la requête et injecte le HTML côté serveur avant le rendu.",{"type":32,"tag":33,"props":1468,"children":1469},{},[1470],{"type":37,"value":1471},"La deuxième méthode est plus rapide (latence edge \u003C 50 ms) mais l'edge runtime ne supporte pas toutes les API Node.js — tu ne peux pas utiliser le client de base de données bundlé. En 2026, comme Cloudflare D1 et Vercel Postgres sont natifs edge, cette contrainte commence à disparaître.",{"type":32,"tag":33,"props":1473,"children":1474},{},[1475],{"type":37,"value":1476},"Exemple de middleware edge (Next.js 15) :",{"type":32,"tag":105,"props":1478,"children":1482},{"className":1479,"code":1480,"language":1481,"meta":16,"style":16},"language-ts shiki shiki-themes github-dark","\u002F\u002F middleware.ts\nimport { NextResponse } from 'next\u002Fserver'\n\nexport function middleware(request: Request) {\n  const segment = request.headers.get('x-user-segment') || 'default'\n  const response = NextResponse.next()\n  response.headers.set('x-personalization', segment)\n  return response\n}\n","ts",[1483],{"type":32,"tag":40,"props":1484,"children":1485},{"__ignoreMap":16},[1486,1494,1515,1522,1560,1609,1640,1667,1679],{"type":32,"tag":115,"props":1487,"children":1488},{"class":117,"line":118},[1489],{"type":32,"tag":115,"props":1490,"children":1491},{"style":154},[1492],{"type":37,"value":1493},"\u002F\u002F middleware.ts\n",{"type":32,"tag":115,"props":1495,"children":1496},{"class":117,"line":150},[1497,1501,1506,1510],{"type":32,"tag":115,"props":1498,"children":1499},{"style":164},[1500],{"type":37,"value":868},{"type":32,"tag":115,"props":1502,"children":1503},{"style":122},[1504],{"type":37,"value":1505}," { NextResponse } ",{"type":32,"tag":115,"props":1507,"children":1508},{"style":164},[1509],{"type":37,"value":878},{"type":32,"tag":115,"props":1511,"children":1512},{"style":196},[1513],{"type":37,"value":1514}," 'next\u002Fserver'\n",{"type":32,"tag":115,"props":1516,"children":1517},{"class":117,"line":160},[1518],{"type":32,"tag":115,"props":1519,"children":1520},{"emptyLinePlaceholder":266},[1521],{"type":37,"value":269},{"type":32,"tag":115,"props":1523,"children":1524},{"class":117,"line":207},[1525,1529,1533,1538,1542,1547,1551,1556],{"type":32,"tag":115,"props":1526,"children":1527},{"style":164},[1528],{"type":37,"value":681},{"type":32,"tag":115,"props":1530,"children":1531},{"style":164},[1532],{"type":37,"value":691},{"type":32,"tag":115,"props":1534,"children":1535},{"style":134},[1536],{"type":37,"value":1537}," middleware",{"type":32,"tag":115,"props":1539,"children":1540},{"style":122},[1541],{"type":37,"value":193},{"type":32,"tag":115,"props":1543,"children":1544},{"style":703},[1545],{"type":37,"value":1546},"request",{"type":32,"tag":115,"props":1548,"children":1549},{"style":164},[1550],{"type":37,"value":711},{"type":32,"tag":115,"props":1552,"children":1553},{"style":134},[1554],{"type":37,"value":1555}," Request",{"type":32,"tag":115,"props":1557,"children":1558},{"style":122},[1559],{"type":37,"value":721},{"type":32,"tag":115,"props":1561,"children":1562},{"class":117,"line":236},[1563,1567,1572,1576,1581,1586,1590,1595,1599,1604],{"type":32,"tag":115,"props":1564,"children":1565},{"style":164},[1566],{"type":37,"value":729},{"type":32,"tag":115,"props":1568,"children":1569},{"style":170},[1570],{"type":37,"value":1571}," segment",{"type":32,"tag":115,"props":1573,"children":1574},{"style":164},[1575],{"type":37,"value":178},{"type":32,"tag":115,"props":1577,"children":1578},{"style":122},[1579],{"type":37,"value":1580}," request.headers.",{"type":32,"tag":115,"props":1582,"children":1583},{"style":134},[1584],{"type":37,"value":1585},"get",{"type":32,"tag":115,"props":1587,"children":1588},{"style":122},[1589],{"type":37,"value":193},{"type":32,"tag":115,"props":1591,"children":1592},{"style":196},[1593],{"type":37,"value":1594},"'x-user-segment'",{"type":32,"tag":115,"props":1596,"children":1597},{"style":122},[1598],{"type":37,"value":800},{"type":32,"tag":115,"props":1600,"children":1601},{"style":164},[1602],{"type":37,"value":1603},"||",{"type":32,"tag":115,"props":1605,"children":1606},{"style":196},[1607],{"type":37,"value":1608}," 'default'\n",{"type":32,"tag":115,"props":1610,"children":1611},{"class":117,"line":245},[1612,1616,1621,1625,1630,1635],{"type":32,"tag":115,"props":1613,"children":1614},{"style":164},[1615],{"type":37,"value":729},{"type":32,"tag":115,"props":1617,"children":1618},{"style":170},[1619],{"type":37,"value":1620}," response",{"type":32,"tag":115,"props":1622,"children":1623},{"style":164},[1624],{"type":37,"value":178},{"type":32,"tag":115,"props":1626,"children":1627},{"style":122},[1628],{"type":37,"value":1629}," NextResponse.",{"type":32,"tag":115,"props":1631,"children":1632},{"style":134},[1633],{"type":37,"value":1634},"next",{"type":32,"tag":115,"props":1636,"children":1637},{"style":122},[1638],{"type":37,"value":1639},"()\n",{"type":32,"tag":115,"props":1641,"children":1642},{"class":117,"line":262},[1643,1648,1653,1657,1662],{"type":32,"tag":115,"props":1644,"children":1645},{"style":122},[1646],{"type":37,"value":1647},"  response.headers.",{"type":32,"tag":115,"props":1649,"children":1650},{"style":134},[1651],{"type":37,"value":1652},"set",{"type":32,"tag":115,"props":1654,"children":1655},{"style":122},[1656],{"type":37,"value":193},{"type":32,"tag":115,"props":1658,"children":1659},{"style":196},[1660],{"type":37,"value":1661},"'x-personalization'",{"type":32,"tag":115,"props":1663,"children":1664},{"style":122},[1665],{"type":37,"value":1666},", segment)\n",{"type":32,"tag":115,"props":1668,"children":1669},{"class":117,"line":272},[1670,1674],{"type":32,"tag":115,"props":1671,"children":1672},{"style":164},[1673],{"type":37,"value":765},{"type":32,"tag":115,"props":1675,"children":1676},{"style":122},[1677],{"type":37,"value":1678}," response\n",{"type":32,"tag":115,"props":1680,"children":1681},{"class":117,"line":26},[1682],{"type":32,"tag":115,"props":1683,"children":1684},{"style":122},[1685],{"type":37,"value":837},{"type":32,"tag":33,"props":1687,"children":1688},{},[1689],{"type":37,"value":1690},"Le server component lit ce header et rend les données spécifiques au segment. La clé de cache inclut le segment, donc chaque segment a sa propre entrée de cache.",{"type":32,"tag":57,"props":1692,"children":1694},{"id":1693},"choix-des-outils-en-2026-next-nuxt-remix-où-et-quand",[1695],{"type":37,"value":1696},"Choix des Outils en 2026 : Next, Nuxt, Remix — Où et Quand ?",{"type":32,"tag":33,"props":1698,"children":1699},{},[1700],{"type":37,"value":1701},"RSC n'est plus agnostique au framework — chaque framework impose sa propre interprétation :",{"type":32,"tag":1344,"props":1703,"children":1704},{},[1705,1722,1739,1749],{"type":32,"tag":1348,"props":1706,"children":1707},{},[1708,1713,1715,1720],{"type":32,"tag":1338,"props":1709,"children":1710},{},[1711],{"type":37,"value":1712},"Next.js 15 :",{"type":37,"value":1714}," Support RSC le plus mûr, App Router stable, ",{"type":32,"tag":49,"props":1716,"children":1717},{},[1718],{"type":37,"value":1719},"server action",{"type":37,"value":1721}," de première classe. Compromis : risque de lock-in Vercel, edge runtime difficile en auto-hébergement.",{"type":32,"tag":1348,"props":1723,"children":1724},{},[1725,1730,1732,1737],{"type":32,"tag":1338,"props":1726,"children":1727},{},[1728],{"type":37,"value":1729},"Nuxt 3.12 :",{"type":37,"value":1731}," Support Vue 3.5 avec ",{"type":32,"tag":40,"props":1733,"children":1735},{"className":1734},[],[1736],{"type":37,"value":45},{"type":37,"value":1738},", serveur Nitro unifié. Compromis : pas aussi granulaire que RSC, pas de split server\u002Fclient au niveau du component.",{"type":32,"tag":1348,"props":1740,"children":1741},{},[1742,1747],{"type":32,"tag":1338,"props":1743,"children":1744},{},[1745],{"type":37,"value":1746},"Remix 2.8 :",{"type":37,"value":1748}," Pattern loader\u002Faction proche de RSC mais distinction client\u002Fcomponent moins nette. Compromis : navigation SPA rapide, chargement initial lent.",{"type":32,"tag":1348,"props":1750,"children":1751},{},[1752,1757,1759,1765,1767,1771],{"type":32,"tag":1338,"props":1753,"children":1754},{},[1755],{"type":37,"value":1756},"SvelteKit 2.5 :",{"type":37,"value":1758}," Pattern ",{"type":32,"tag":40,"props":1760,"children":1762},{"className":1761},[],[1763],{"type":37,"value":1764},"+page.server.ts",{"type":37,"value":1766}," similaire à RSC. Compromis : adoption Svelte 5 ",{"type":32,"tag":49,"props":1768,"children":1769},{},[1770],{"type":37,"value":53},{"type":37,"value":1772}," encore faible dans l'écosystème.",{"type":32,"tag":33,"props":1774,"children":1775},{},[1776],{"type":37,"value":1777},"Chez Roibase, au stade 2026, nous utilisons 60 % Next.js, 30 % Nuxt, 10 % Remix. Le critère de décision : stack existant (React vs Vue), expertise de l'équipe, cible de déploiement (Vercel \u002F Cloudflare \u002F auto-hébergement).",{"type":32,"tag":33,"props":1779,"children":1780},{},[1781],{"type":37,"value":1782},"L'architecture server component est désormais par défaut — la question n'est plus « dois-je l'utiliser ? », mais « comment l'optimiser ? ». La matrice de décision et la cartographie des compromis ci-dessus ancrent la décision server\u002Fclient pour chaque component à des critères numériques. En 2026, tracer la bonne ligne, c'est atteindre TBT \u003C 200 ms et LCP \u003C 1,5 s — le chemin fondamental vers cet objectif passe par l'architecture server component.",{"type":32,"tag":1784,"props":1785,"children":1786},"style",{},[1787],{"type":37,"value":1788},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":16,"searchDepth":160,"depth":160,"links":1790},[1791,1792,1795,1796,1797,1798],{"id":59,"depth":150,"text":62},{"id":80,"depth":150,"text":83,"children":1793},[1794],{"id":595,"depth":160,"text":598},{"id":1157,"depth":150,"text":1160},{"id":1325,"depth":150,"text":1328},{"id":1434,"depth":150,"text":1437},{"id":1693,"depth":150,"text":1696},"markdown","content:fr:tech:server-components-vs-client-2026-tracer-la-bonne-ligne.md","content","fr\u002Ftech\u002Fserver-components-vs-client-2026-tracer-la-bonne-ligne.md","fr\u002Ftech\u002Fserver-components-vs-client-2026-tracer-la-bonne-ligne","md",1785103543182]