[{"data":1,"prerenderedAt":1140},["ShallowReactive",2],{"\u002Fblog\u002Fnuxt-4-6-whats-new":3,"\u002Fblog\u002Fnuxt-4-6-whats-new-surround":1134},{"id":4,"title":5,"authors":6,"body":13,"category":1124,"date":1125,"description":1126,"extension":1127,"image":1128,"meta":1129,"minRead":400,"navigation":282,"path":1130,"seo":1131,"stem":1132,"__hash__":1133},"blog_fr\u002Fblog\u002F5.nuxt-4-6-whats-new.md","Nuxt 4.6 : j'ai migré mon portfolio et activé (presque) tous les flags",[7],{"name":8,"avatar":9,"to":11,"twitter":12},"Désiré KOUASSI",{"src":10,"alt":8},"https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F57430025?v=4&s=64","https:\u002F\u002Fx.com\u002Fkdesire09","KouamDesire07",{"type":14,"value":15,"toc":1109},"minimark",[16,20,23,28,31,61,72,101,104,148,151,155,177,184,191,194,210,217,224,248,251,417,420,552,565,593,619,623,630,781,790,796,817,875,890,896,911,915,928,936,946,951,958,962,969,1050,1053,1057,1089,1105],[17,18,19],"p",{},"Nuxt 4.6 est sorti le 5 octobre 2026. C'est l'une des plus grosses versions mineures du framework : plus de 420 commits depuis la 4.5.2, une nouvelle CLI majeure, et surtout une bonne partie de Nuxt 5 déjà disponible derrière des flags. Nuxt 3 étant en fin de vie depuis le 31 juillet, c'est aussi le moment de se mettre à jour.",[17,21,22],{},"Plutôt que de résumer les notes de version, j'ai migré ce portfolio (Nuxt Content, i18n, Nuxt UI, Nuxt SEO, Workflow, evlog) et testé chaque nouveauté une par une. Voici ce qui a marché, ce qui a cassé, et les chiffres.",[24,25,27],"h2",{"id":26},"la-migration-elle-même","La migration elle-même",[17,29,30],{},"La commande recommandée est :",[32,33,38],"pre",{"className":34,"code":35,"language":36,"meta":37,"style":37},"language-bash shiki shiki-themes github-light github-dark github-dark","npx nuxt upgrade --dedupe\n","bash","",[39,40,41],"code",{"__ignoreMap":37},[42,43,46,50,54,57],"span",{"class":44,"line":45},"line",1,[42,47,49],{"class":48},"shcOC","npx",[42,51,53],{"class":52},"sfrk1"," nuxt",[42,55,56],{"class":52}," upgrade",[42,58,60],{"class":59},"suiK_"," --dedupe\n",[17,62,63,64,67,68,71],{},"Chez moi, elle a annoncé « already using the latest version (4.5.2) » sans rien mettre à jour, et a même déplacé ",[39,65,66],{},"@nuxt\u002Fkit"," dans les ",[39,69,70],{},"devDependencies"," au passage. J'ai donc fait la mise à jour à la main :",[32,73,75],{"className":34,"code":74,"language":36,"meta":37,"style":37},"pnpm add -D nuxt@^4.6.0\npnpm add @nuxt\u002Fkit@^4.6.0\n",[39,76,77,91],{"__ignoreMap":37},[42,78,79,82,85,88],{"class":44,"line":45},[42,80,81],{"class":48},"pnpm",[42,83,84],{"class":52}," add",[42,86,87],{"class":59}," -D",[42,89,90],{"class":52}," nuxt@^4.6.0\n",[42,92,94,96,98],{"class":44,"line":93},2,[42,95,81],{"class":48},[42,97,84],{"class":52},[42,99,100],{"class":52}," @nuxt\u002Fkit@^4.6.0\n",[17,102,103],{},"Deux détails à surveiller :",[105,106,107,127],"ul",{},[108,109,110,114,115,118,119,122,123,126],"li",{},[111,112,113],"strong",{},"Node.js"," : la 4.6 exige ",[39,116,117],{},"^22.22.3 || ^24.15.0 || >=26.0.0",". J'ai aligné le champ ",[39,120,121],{},"engines"," du ",[39,124,125],{},"package.json",".",[108,128,129,135,136,139,140,143,144,147],{},[111,130,131,132],{},"pnpm ",[39,133,134],{},"minimumReleaseAge"," : si vous l'utilisez (et vous devriez), une version publiée la veille est bloquée. pnpm a ajouté lui-même les paquets ",[39,137,138],{},"nuxt@4.6.0",", ",[39,141,142],{},"@nuxt\u002Fcli@4.0.0",", etc. dans ",[39,145,146],{},"minimumReleaseAgeExclude",". Pensez à le commiter.",[17,149,150],{},"Sans activer aucune option, le site a fonctionné du premier coup : toutes les pages, les deux langues, le contenu.",[24,152,154],{"id":153},"nuxt-cli-v4-le-changement-quon-voit-tout-de-suite","Nuxt CLI v4 : le changement qu'on voit tout de suite",[17,156,157,158,161,162,165,166,169,170,173,174,176],{},"En lançant ",[39,159,160],{},"nuxt dev",", on découvre la nouvelle CLI, livrée avec Nuxt. Le terminal devient une petite interface : progression du démarrage, raccourcis (",[39,163,164],{},"o"," ouvrir, ",[39,167,168],{},"l"," logs, ",[39,171,172],{},"n"," réseau, ",[39,175,17],{}," routes), et un résumé des requêtes en échec qu'on peut tracer.",[17,178,179],{},[180,181],"img",{"alt":182,"src":183},"La nouvelle interface de nuxt dev (Nuxt CLI v4) sur ce projet : serveur prêt, nombre de requêtes, temps médian, avertissements et raccourcis clavier","\u002Fimages\u002Fblog\u002Fnuxt-4-6-cli.webp",[17,185,186,187,190],{},"L'écran de chargement du navigateur a lui aussi été redessiné : une chaîne de montagnes en particules WebGL2 (l'image en haut de cet article est une capture de cet écran). Il désactive l'animation avec ",[39,188,189],{},"prefers-reduced-motion"," et retombe sur le logo seul sans WebGL2.",[17,192,193],{},"Petit bonus pratique, la recherche dans la doc depuis le terminal :",[32,195,197],{"className":34,"code":196,"language":36,"meta":37,"style":37},"nuxt docs \"server imports\"\n",[39,198,199],{"__ignoreMap":37},[42,200,201,204,207],{"class":44,"line":45},[42,202,203],{"class":48},"nuxt",[42,205,206],{"class":52}," docs",[42,208,209],{"class":52}," \"server imports\"\n",[17,211,212,213,216],{},"Elle télécharge et indexe la documentation de ",[111,214,215],{},"votre"," version de Nuxt, puis ouvre la bonne page.",[24,218,220,223],{"id":219},"nuxtserver-du-code-serveur-qui-survivra-à-nuxt-5",[39,221,222],{},"nuxt\u002Fserver"," : du code serveur qui survivra à Nuxt 5",[17,225,226,227,230,231,234,235,237,238,139,241,139,244,247],{},"Jusqu'ici, le code serveur importait (ou auto-importait) les helpers de ",[39,228,229],{},"h3"," et ",[39,232,233],{},"nitropack",". Chaque version majeure de h3 ou de Nitro cassait donc tout l'écosystème. La 4.6 introduit ",[39,236,222],{},", une surface d'import maintenue par Nuxt et basée sur les standards du web (",[39,239,240],{},"Request",[39,242,243],{},"Headers",[39,245,246],{},"URL",").",[17,249,250],{},"J'ai migré le handler du formulaire de contact. Avant :",[32,252,257],{"className":253,"code":254,"filename":255,"language":256,"meta":37,"style":37},"language-ts shiki shiki-themes github-light github-dark github-dark","import type { H3Event } from 'h3'\n\nexport default defineEventHandler(async (event: H3Event) => {\n  const result = await readValidatedBody(event, body => contactSchema.safeParse(body))\n  if (!result.success) {\n    throw createError({ statusCode: 400, statusMessage: result.error.errors[0].message })\n  }\n  \u002F\u002F ...\n})\n","server\u002Fapi\u002Fcontact.post.ts","ts",[39,258,259,278,284,324,360,374,398,404,411],{"__ignoreMap":37},[42,260,261,265,268,272,275],{"class":44,"line":45},[42,262,264],{"class":263},"so5gQ","import",[42,266,267],{"class":263}," type",[42,269,271],{"class":270},"slsVL"," { H3Event } ",[42,273,274],{"class":263},"from",[42,276,277],{"class":52}," 'h3'\n",[42,279,280],{"class":44,"line":93},[42,281,283],{"emptyLinePlaceholder":282},true,"\n",[42,285,287,290,293,296,299,302,305,309,312,315,318,321],{"class":44,"line":286},3,[42,288,289],{"class":263},"export",[42,291,292],{"class":263}," default",[42,294,295],{"class":48}," defineEventHandler",[42,297,298],{"class":270},"(",[42,300,301],{"class":263},"async",[42,303,304],{"class":270}," (",[42,306,308],{"class":307},"sQHwn","event",[42,310,311],{"class":263},":",[42,313,314],{"class":48}," H3Event",[42,316,317],{"class":270},") ",[42,319,320],{"class":263},"=>",[42,322,323],{"class":270}," {\n",[42,325,327,330,333,336,339,342,345,348,351,354,357],{"class":44,"line":326},4,[42,328,329],{"class":263},"  const",[42,331,332],{"class":59}," result",[42,334,335],{"class":263}," =",[42,337,338],{"class":263}," await",[42,340,341],{"class":48}," readValidatedBody",[42,343,344],{"class":270},"(event, ",[42,346,347],{"class":307},"body",[42,349,350],{"class":263}," =>",[42,352,353],{"class":270}," contactSchema.",[42,355,356],{"class":48},"safeParse",[42,358,359],{"class":270},"(body))\n",[42,361,363,366,368,371],{"class":44,"line":362},5,[42,364,365],{"class":263},"  if",[42,367,304],{"class":270},[42,369,370],{"class":263},"!",[42,372,373],{"class":270},"result.success) {\n",[42,375,377,380,383,386,389,392,395],{"class":44,"line":376},6,[42,378,379],{"class":263},"    throw",[42,381,382],{"class":48}," createError",[42,384,385],{"class":270},"({ statusCode: ",[42,387,388],{"class":59},"400",[42,390,391],{"class":270},", statusMessage: result.error.errors[",[42,393,394],{"class":59},"0",[42,396,397],{"class":270},"].message })\n",[42,399,401],{"class":44,"line":400},7,[42,402,403],{"class":270},"  }\n",[42,405,407],{"class":44,"line":406},8,[42,408,410],{"class":409},"sCsY4","  \u002F\u002F ...\n",[42,412,414],{"class":44,"line":413},9,[42,415,416],{"class":270},"})\n",[17,418,419],{},"Après :",[32,421,423],{"className":253,"code":422,"filename":255,"language":256,"meta":37,"style":37},"import { defineEventHandler, readValidatedBody } from 'nuxt\u002Fserver'\n\nexport default defineEventHandler(async (event) => {\n  const data = await readValidatedBody(event, contactSchema, {\n    onError: ({ issues }) => ({\n      status: 400,\n      statusText: issues?.[0]?.message ?? 'Validation failed',\n      issues,\n    }),\n  })\n  \u002F\u002F ...\n})\n",[39,424,425,437,441,463,479,498,508,526,531,536,542,547],{"__ignoreMap":37},[42,426,427,429,432,434],{"class":44,"line":45},[42,428,264],{"class":263},[42,430,431],{"class":270}," { defineEventHandler, readValidatedBody } ",[42,433,274],{"class":263},[42,435,436],{"class":52}," 'nuxt\u002Fserver'\n",[42,438,439],{"class":44,"line":93},[42,440,283],{"emptyLinePlaceholder":282},[42,442,443,445,447,449,451,453,455,457,459,461],{"class":44,"line":286},[42,444,289],{"class":263},[42,446,292],{"class":263},[42,448,295],{"class":48},[42,450,298],{"class":270},[42,452,301],{"class":263},[42,454,304],{"class":270},[42,456,308],{"class":307},[42,458,317],{"class":270},[42,460,320],{"class":263},[42,462,323],{"class":270},[42,464,465,467,470,472,474,476],{"class":44,"line":326},[42,466,329],{"class":263},[42,468,469],{"class":59}," data",[42,471,335],{"class":263},[42,473,338],{"class":263},[42,475,341],{"class":48},[42,477,478],{"class":270},"(event, contactSchema, {\n",[42,480,481,484,487,490,493,495],{"class":44,"line":362},[42,482,483],{"class":48},"    onError",[42,485,486],{"class":270},": ({ ",[42,488,489],{"class":307},"issues",[42,491,492],{"class":270}," }) ",[42,494,320],{"class":263},[42,496,497],{"class":270}," ({\n",[42,499,500,503,505],{"class":44,"line":376},[42,501,502],{"class":270},"      status: ",[42,504,388],{"class":59},[42,506,507],{"class":270},",\n",[42,509,510,513,515,518,521,524],{"class":44,"line":400},[42,511,512],{"class":270},"      statusText: issues?.[",[42,514,394],{"class":59},[42,516,517],{"class":270},"]?.message ",[42,519,520],{"class":263},"??",[42,522,523],{"class":52}," 'Validation failed'",[42,525,507],{"class":270},[42,527,528],{"class":44,"line":406},[42,529,530],{"class":270},"      issues,\n",[42,532,533],{"class":44,"line":413},[42,534,535],{"class":270},"    }),\n",[42,537,539],{"class":44,"line":538},10,[42,540,541],{"class":270},"  })\n",[42,543,545],{"class":44,"line":544},11,[42,546,410],{"class":409},[42,548,550],{"class":44,"line":549},12,[42,551,416],{"class":270},[17,553,554,555,562,563,126],{},"Zod v4 implémente ",[556,557,561],"a",{"href":558,"rel":559},"https:\u002F\u002Fstandardschema.dev",[560],"nofollow","Standard Schema",", donc on passe directement le schéma, sans ",[39,564,356],{},[566,567,570],"callout",{"color":568,"icon":569},"warning","i-lucide-triangle-alert",[17,571,572,573,139,576,579,580,583,584,586,587,589,590,126],{},"En Nuxt 4, les ",[39,574,575],{},"defineEventHandler",[39,577,578],{},"readBody","… ",[111,581,582],{},"auto-importés"," restent ceux de h3. Pour utiliser le nouveau runtime, il faut importer explicitement depuis ",[39,585,222],{},", y compris ",[39,588,575],{},". Mélanger les deux déclenche une erreur ",[39,591,592],{},"NUXT_E8012",[17,594,595,596,599,600,603,604,607,608,603,611,614,615,618],{},"Attention aussi aux différences de forme : ",[39,597,598],{},"createError"," prend ",[39,601,602],{},"status","\u002F",[39,605,606],{},"statusText"," (et non plus ",[39,609,610],{},"statusCode",[39,612,613],{},"statusMessage","), et ",[39,616,617],{},"sendRedirect"," renvoie la réponse au lieu de l'envoyer.",[24,620,622],{"id":621},"les-options-expérimentales-une-par-une","Les options expérimentales, une par une",[17,624,625,626,629],{},"J'ai activé chaque option, puis vérifié le build de production, les types (",[39,627,628],{},"vue-tsc -b",") et les pages en FR et en EN.",[631,632,633,649],"table",{},[634,635,636],"thead",{},[637,638,639,643,646],"tr",{},[640,641,642],"th",{},"Option",[640,644,645],{},"Résultat",[640,647,648],{},"Gardée",[650,651,652,670,682,697,709,724,739,752,769],"tbody",{},[637,653,654,660,667],{},[655,656,657],"td",{},[39,658,659],{},"routeTypedFetch",[655,661,662,663,666],{},"Types générés via ",[39,664,665],{},"fetchdts",", aucune erreur sur ce projet",[655,668,669],{},"✅",[637,671,672,677,680],{},[655,673,674],{},[39,675,676],{},"typedPages",[655,678,679],{},"A trouvé un typage trop lâche (voir ci-dessous)",[655,681,669],{},[637,683,684,689,695],{},[655,685,686],{},[39,687,688],{},"prerenderErrorPages",[655,690,691,694],{},[39,692,693],{},"404.html"," passe d'une coquille SPA vide (9,8 Ko) à la vraie page 404 en HTML (27 Ko)",[655,696,669],{},[637,698,699,704,707],{},[655,700,701],{},[39,702,703],{},"early404",[655,705,706],{},"URL inconnue → 404 immédiate, i18n intact",[655,708,669],{},[637,710,711,716,722],{},[655,712,713],{},[39,714,715],{},"inlineErrorRendering",[655,717,718,721],{},[39,719,720],{},"error.vue"," rendu dans la même requête, avec la page personnalisée",[655,723,669],{},[637,725,726,734,737],{},[655,727,728,139,731],{},[39,729,730],{},"extractSerializablePageMeta",[39,732,733],{},"stripNeverHydratedData",[655,735,736],{},"Rien de cassé, rien de mesurable sur ce site",[655,738,669],{},[637,740,741,746,749],{},[655,742,743],{},[39,744,745],{},"future.compatibilityVersion: 5",[655,747,748],{},"Build et pages OK, mais le routage devient sensible à la casse",[655,750,751],{},"⏸️",[637,753,754,760,766],{},[655,755,756,759],{},[39,757,758],{},"vue.vapor"," (Vue 3.6 RC)",[655,761,762,763],{},"Build cassé par ",[39,764,765],{},"@nuxtjs\u002Fmdc",[655,767,768],{},"❌",[637,770,771,776,779],{},[655,772,773],{},[39,774,775],{},"server.builder: 'vite'",[655,777,778],{},"Incompatible avec ce site",[655,780,768],{},[17,782,783,784,786,787,789],{},"Le gain le plus concret est ",[39,785,688],{},". Sur Vercel, le ",[39,788,693],{}," statique servait jusqu'ici une page vide hydratée côté client. C'est désormais la vraie page « Oups ! », lisible sans JavaScript et par les robots.",[229,791,793,795],{"id":792},"typedpages-i18n",[39,794,676],{}," + i18n",[17,797,798,799,139,801,804,805,808,809,812,813,816],{},"Avec ",[39,800,676],{},[39,802,803],{},"useRoute()"," sans argument a renvoyé ",[39,806,807],{},"unknown"," dans ",[39,810,811],{},"pages\u002Fblog\u002F[...slug].vue",". Avec ",[39,814,815],{},"@nuxtjs\u002Fi18n",", les routes portent un suffixe de langue. Il faut donc donner les noms au générique :",[32,818,820],{"className":253,"code":819,"language":256,"meta":37,"style":37},"const route = useRoute\u003C'blog-slug___fr' | 'blog-slug___en'>()\nconst slug = computed(() => route.params.slug ?? [])\n",[39,821,822,850],{"__ignoreMap":37},[42,823,824,827,830,832,835,838,841,844,847],{"class":44,"line":45},[42,825,826],{"class":263},"const",[42,828,829],{"class":59}," route",[42,831,335],{"class":263},[42,833,834],{"class":48}," useRoute",[42,836,837],{"class":270},"\u003C",[42,839,840],{"class":52},"'blog-slug___fr'",[42,842,843],{"class":263}," |",[42,845,846],{"class":52}," 'blog-slug___en'",[42,848,849],{"class":270},">()\n",[42,851,852,854,857,859,862,865,867,870,872],{"class":44,"line":93},[42,853,826],{"class":263},[42,855,856],{"class":59}," slug",[42,858,335],{"class":263},[42,860,861],{"class":48}," computed",[42,863,864],{"class":270},"(() ",[42,866,320],{"class":263},[42,868,869],{"class":270}," route.params.slug ",[42,871,520],{"class":263},[42,873,874],{"class":270}," [])\n",[17,876,877,878,881,882,885,886,889],{},"Bonus : TypeScript sait maintenant que ",[39,879,880],{},"slug"," est un ",[39,883,884],{},"string[]",", et l'ancien cast défensif ",[39,887,888],{},"Array.isArray(...) ? ... as string[] : [... as string]"," a pu disparaître.",[229,891,893],{"id":892},"compatibilityversion-5",[39,894,895],{},"compatibilityVersion: 5",[17,897,898,899,902,903,906,907,910],{},"Le build passe, toutes les pages et l'API répondent. Le changement visible est le ",[111,900,901],{},"routage sensible à la casse"," : ",[39,904,905],{},"\u002FContact"," ou ",[39,908,909],{},"\u002FBLOG"," renvoient maintenant 404. C'est cohérent avec Nitro, mais je préfère activer ce flag au moment de passer à Nuxt 5 plutôt que de risquer de casser d'anciens liens.",[229,912,914],{"id":913},"vapor-bloqué-par-un-module","Vapor : bloqué par un module",[17,916,917,918,923,924,927],{},"La 4.6 permet de passer un composant en ",[556,919,922],{"href":920,"rel":921},"https:\u002F\u002Fgithub.com\u002Fvuejs\u002Fcore\u002Freleases\u002Ftag\u002Fv3.6.0-rc.1#about-vapor-mode",[560],"Vapor Mode"," avec ",[39,925,926],{},"\u003Cscript setup vapor>"," (avec Vue 3.6, encore en RC). J'ai essayé sur le footer du site, présent sur toutes les pages. Le build a échoué dans le compilateur Vapor :",[32,929,934],{"className":930,"code":932,"language":933},[931],"language-text","TypeError: Cannot read properties of undefined (reading '0')\n    at viteMDCSlot (@nuxtjs\u002Fmdc\u002Fdist\u002Fmodule.mjs)\n","text",[39,935,932],{"__ignoreMap":37},[17,937,938,939,941,942,945],{},"La transformation de template de ",[39,940,765],{}," lit ",[39,943,944],{},"context.nodeTransforms",", qui n'existe pas dans le contexte du compilateur Vapor. C'est le même code dans la dernière version (0.23.2). Tant que mdc n'est pas compatible, un seul composant Vapor suffit à casser le build. Je n'aurais de toute façon pas mis une RC de Vue en production.",[229,947,949],{"id":948},"serverbuilder-vite",[39,950,775],{},[17,952,953,954,957],{},"Le nouveau builder serveur expérimental fabrique l'app avec Vite seul, sans Nitro. Il prévient lui-même : pas de prérendu, pas de routes serveur, pas de plugins Nitro. Le build s'arrête sur un module qui appelle ",[39,955,956],{},"useNitro()",". Ce site repose sur le prérendu, une route API, Workflow, evlog et les images OG : Nitro reste le bon choix, comme le dit d'ailleurs l'équipe Nuxt.",[24,959,961],{"id":960},"les-chiffres","Les chiffres",[17,963,964,965,968],{},"Mesurés sur ma machine (Apple Silicon, Node 24.18), build de production complet après suppression de ",[39,966,967],{},".nuxt",", une seule mesure à chaque fois (à prendre comme une tendance) :",[631,970,971,985],{},[634,972,973],{},[637,974,975,977,980,983],{},[640,976],{},[640,978,979],{},"Nuxt 4.5.2",[640,981,982],{},"Nuxt 4.6.0",[640,984],{},[650,986,987,1006,1022,1038],{},[637,988,989,995,998,1001],{},[655,990,991,994],{},[39,992,993],{},"nuxt build"," (total)",[655,996,997],{},"142,5 s",[655,999,1000],{},"131,8 s",[655,1002,1003],{},[111,1004,1005],{},"−7,5 %",[637,1007,1008,1011,1014,1017],{},[655,1009,1010],{},"Prérendu des 130 routes",[655,1012,1013],{},"34,1 s",[655,1015,1016],{},"26,3 s",[655,1018,1019],{},[111,1020,1021],{},"−23 %",[637,1023,1024,1030,1033,1035],{},[655,1025,1026,1027],{},"Taille de ",[39,1028,1029],{},".output\u002Fpublic",[655,1031,1032],{},"61 Mo",[655,1034,1032],{},[655,1036,1037],{},"=",[637,1039,1040,1043,1046,1048],{},[655,1041,1042],{},"Payload de la page d'accueil",[655,1044,1045],{},"68,8 Ko",[655,1047,1045],{},[655,1049,1037],{},[17,1051,1052],{},"Sur un site déjà entièrement prérendu, la sortie ne change pas. Le gain vient du temps de build, surtout du prérendu.",[24,1054,1056],{"id":1055},"ce-que-je-retiens","Ce que je retiens",[105,1058,1059,1065,1073,1083],{},[108,1060,1061,1064],{},[111,1062,1063],{},"La migration est sans douleur"," : aucune modification de code n'a été nécessaire pour que le site tourne en 4.6.",[108,1066,1067,1072],{},[111,1068,1069,1071],{},[39,1070,222],{}," vaut le détour dès maintenant"," : c'est ce qui rendra le passage à Nuxt 5 et Nitro v3 transparent.",[108,1074,1075,1082],{},[111,1076,1077,230,1079,1081],{},[39,1078,688],{},[39,1080,676],{}," sont des gains concrets",", à activer sans attendre.",[108,1084,1085,1088],{},[111,1086,1087],{},"Vapor et le builder Vite sont des expérimentations",", à suivre de près, mais à ne pas mettre en production sur un vrai projet.",[17,1090,1091,1092,1097,1098,139,1101,1104],{},"Toutes les nouveautés sont dans les ",[556,1093,1096],{"href":1094,"rel":1095},"https:\u002F\u002Fgithub.com\u002Fnuxt\u002Fnuxt\u002Freleases\u002Ftag\u002Fv4.6.0",[560],"notes de version officielles de Nuxt 4.6",", y compris celles que je n'ai pas couvertes ici (addons pour ",[39,1099,1100],{},"useFetch",[39,1102,1103],{},"appSecret"," et sessions, payloads allégés…).",[1106,1107,1108],"style",{},"html pre.shiki code .shcOC, html code.shiki .shcOC{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#B392F0}html pre.shiki code .sfrk1, html code.shiki .sfrk1{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}html pre.shiki code .suiK_, html code.shiki .suiK_{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .so5gQ, html code.shiki .so5gQ{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#F97583}html pre.shiki code .slsVL, html code.shiki .slsVL{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8}html pre.shiki code .sQHwn, html code.shiki .sQHwn{--shiki-light:#E36209;--shiki-default:#FFAB70;--shiki-dark:#FFAB70}html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":37,"searchDepth":93,"depth":93,"links":1110},[1111,1112,1113,1115,1122,1123],{"id":26,"depth":93,"text":27},{"id":153,"depth":93,"text":154},{"id":219,"depth":93,"text":1114},"nuxt\u002Fserver : du code serveur qui survivra à Nuxt 5",{"id":621,"depth":93,"text":622,"children":1116},[1117,1119,1120,1121],{"id":792,"depth":286,"text":1118},"typedPages + i18n",{"id":892,"depth":286,"text":895},{"id":913,"depth":286,"text":914},{"id":948,"depth":286,"text":775},{"id":960,"depth":93,"text":961},{"id":1055,"depth":93,"text":1056},null,"2026-10-06","Nuxt 4.6 apporte nuxt\u002Fserver, la CLI v4, un $fetch typé réécrit et un avant-goût de Nuxt 5. Retour d'expérience sur la migration de ce site, option par option, avec ce qui marche, ce qui casse et les chiffres.","md","\u002Fimages\u002Fblog\u002Fnuxt-4-6-loading-screen.webp",{},"\u002Fblog\u002Fnuxt-4-6-whats-new",{"title":5,"description":1126},"blog\u002F5.nuxt-4-6-whats-new","3GqqoQxMs1OO_LPyVSnEwV1_zk-lU_eF_4SI_f7a2AE",[1135,1124],{"title":1136,"path":1137,"stem":1138,"description":1139,"children":-1},"Automatiser la création d'images Docker avec GitHub Actions","\u002Fblog\u002Fautomating-deployment-with-github-actions-and-docker","blog\u002F4.automating-deployment-with-github-actions-and-docker","Découvrez comment mettre en place un pipeline CI\u002FCD complet avec GitHub Actions pour builder et publier automatiquement vos images Docker sur le GitHub Container Registry.",1791713061529]