[{"data":1,"prerenderedAt":25738},["ShallowReactive",2],{"navigation":3,"blog-landing":1107,"posts":1119},[4,1018],{"title":5,"titleTemplate":6,"icon":7,"path":8,"stem":9,"children":10,"page":108},"Docs",null,"i-lucide-bookmark","/docs","docs",[11,109,345,805,897,934,976],{"title":12,"titleTemplate":13,"icon":14,"path":15,"stem":16,"children":17,"page":108},"Get Started","%s · Get Started with Nuxt","i-lucide-rocket","/docs/getting-started","docs/1.getting-started",[18,23,28,33,38,43,48,53,58,63,68,73,78,83,88,93,98,103],{"title":19,"path":20,"stem":21,"titleTemplate":6,"icon":22},"Introduction","/docs/getting-started/introduction","docs/1.getting-started/01.introduction","i-lucide-info",{"title":24,"path":25,"stem":26,"titleTemplate":6,"icon":27},"Installation","/docs/getting-started/installation","docs/1.getting-started/02.installation","i-lucide-play",{"title":29,"path":30,"stem":31,"titleTemplate":6,"icon":32},"Configuration","/docs/getting-started/configuration","docs/1.getting-started/03.configuration","i-lucide-cog",{"title":34,"path":35,"stem":36,"titleTemplate":6,"icon":37},"Views","/docs/getting-started/views","docs/1.getting-started/04.views","i-lucide-panels-top-left",{"title":39,"path":40,"stem":41,"titleTemplate":6,"icon":42},"Assets","/docs/getting-started/assets","docs/1.getting-started/05.assets","i-lucide-image",{"title":44,"path":45,"stem":46,"titleTemplate":6,"icon":47},"Styling","/docs/getting-started/styling","docs/1.getting-started/06.styling","i-lucide-palette",{"title":49,"path":50,"stem":51,"titleTemplate":6,"icon":52},"Routing","/docs/getting-started/routing","docs/1.getting-started/07.routing","i-lucide-milestone",{"title":54,"path":55,"stem":56,"titleTemplate":6,"icon":57},"SEO and Meta","/docs/getting-started/seo-meta","docs/1.getting-started/08.seo-meta","i-lucide-file-search",{"title":59,"path":60,"stem":61,"titleTemplate":6,"icon":62},"Transitions","/docs/getting-started/transitions","docs/1.getting-started/09.transitions","i-lucide-toggle-right",{"title":64,"path":65,"stem":66,"titleTemplate":6,"icon":67},"Data Fetching","/docs/getting-started/data-fetching","docs/1.getting-started/10.data-fetching","i-lucide-cable",{"title":69,"path":70,"stem":71,"titleTemplate":6,"icon":72},"State Management","/docs/getting-started/state-management","docs/1.getting-started/11.state-management","i-lucide-database",{"title":74,"path":75,"stem":76,"titleTemplate":6,"icon":77},"Error Handling","/docs/getting-started/error-handling","docs/1.getting-started/12.error-handling","i-lucide-bug-off",{"title":79,"path":80,"stem":81,"titleTemplate":6,"icon":82},"Server","/docs/getting-started/server","docs/1.getting-started/13.server","i-lucide-pc-case",{"title":84,"path":85,"stem":86,"titleTemplate":6,"icon":87},"Layers","/docs/getting-started/layers","docs/1.getting-started/14.layers","i-lucide-layers",{"title":89,"path":90,"stem":91,"titleTemplate":6,"icon":92},"Prerendering","/docs/getting-started/prerendering","docs/1.getting-started/15.prerendering","i-lucide-file-code-2",{"title":94,"path":95,"stem":96,"titleTemplate":6,"icon":97},"Deployment","/docs/getting-started/deployment","docs/1.getting-started/16.deployment","i-lucide-cloud",{"title":99,"path":100,"stem":101,"titleTemplate":6,"icon":102},"Testing","/docs/getting-started/testing","docs/1.getting-started/17.testing","i-lucide-circle-check",{"title":104,"path":105,"stem":106,"titleTemplate":6,"icon":107},"Upgrade Guide","/docs/getting-started/upgrade","docs/1.getting-started/18.upgrade","i-lucide-circle-arrow-up",false,{"title":110,"titleTemplate":6,"icon":111,"path":112,"stem":113,"children":114,"page":108},"Guide","i-lucide-book-open","/docs/guide","docs/2.guide",[115,158,271,322],{"title":116,"titleTemplate":117,"icon":118,"path":119,"stem":120,"children":121,"page":108},"Key Concepts","%s · Nuxt Concepts","i-lucide-medal","/docs/guide/concepts","docs/2.guide/1.concepts",[122,126,130,134,138,142,146,150,154],{"title":123,"path":124,"stem":125,"titleTemplate":6},"Auto-imports","/docs/guide/concepts/auto-imports","docs/2.guide/1.concepts/1.auto-imports",{"title":127,"path":128,"stem":129,"titleTemplate":6},"Nuxt Lifecycle","/docs/guide/concepts/nuxt-lifecycle","docs/2.guide/1.concepts/10.nuxt-lifecycle",{"title":131,"path":132,"stem":133,"titleTemplate":6},"Vue.js Development","/docs/guide/concepts/vuejs-development","docs/2.guide/1.concepts/2.vuejs-development",{"title":135,"path":136,"stem":137,"titleTemplate":6},"Rendering Modes","/docs/guide/concepts/rendering","docs/2.guide/1.concepts/3.rendering",{"title":139,"path":140,"stem":141,"titleTemplate":6},"Server Engine","/docs/guide/concepts/server-engine","docs/2.guide/1.concepts/4.server-engine",{"title":143,"path":144,"stem":145,"titleTemplate":6},"Modules","/docs/guide/concepts/modules","docs/2.guide/1.concepts/5.modules",{"title":147,"path":148,"stem":149,"titleTemplate":6},"ES Modules","/docs/guide/concepts/esm","docs/2.guide/1.concepts/7.esm",{"title":151,"path":152,"stem":153,"titleTemplate":6},"TypeScript","/docs/guide/concepts/typescript","docs/2.guide/1.concepts/8.typescript",{"title":155,"path":156,"stem":157,"titleTemplate":6},"Code Style","/docs/guide/concepts/code-style","docs/2.guide/1.concepts/9.code-style",{"title":159,"titleTemplate":160,"icon":161,"path":162,"stem":163,"children":164,"page":108},"Directory Structure","%s · Nuxt Directory Structure","i-lucide-folders","/docs/guide/directory-structure","docs/2.guide/2.directory-structure",[165,170,174,178,182,186,190,194,198,202,206,210,214,218,222,226,230,235,239,243,247,251,255,259,263,267],{"title":166,"path":167,"stem":168,"titleTemplate":6,"icon":169},".nuxt","/docs/guide/directory-structure/nuxt","docs/2.guide/2.directory-structure/0.nuxt","i-lucide-folder",{"title":171,"path":172,"stem":173,"titleTemplate":6,"icon":169},".output","/docs/guide/directory-structure/output","docs/2.guide/2.directory-structure/0.output",{"title":175,"path":176,"stem":177,"titleTemplate":6,"icon":169},"assets","/docs/guide/directory-structure/assets","docs/2.guide/2.directory-structure/1.assets",{"title":179,"path":180,"stem":181,"titleTemplate":6,"icon":169},"components","/docs/guide/directory-structure/components","docs/2.guide/2.directory-structure/1.components",{"title":183,"path":184,"stem":185,"titleTemplate":6,"icon":169},"composables","/docs/guide/directory-structure/composables","docs/2.guide/2.directory-structure/1.composables",{"title":187,"path":188,"stem":189,"titleTemplate":6,"icon":169},"content","/docs/guide/directory-structure/content","docs/2.guide/2.directory-structure/1.content",{"title":191,"path":192,"stem":193,"titleTemplate":6,"icon":169},"layouts","/docs/guide/directory-structure/layouts","docs/2.guide/2.directory-structure/1.layouts",{"title":195,"path":196,"stem":197,"titleTemplate":6,"icon":169},"middleware","/docs/guide/directory-structure/middleware","docs/2.guide/2.directory-structure/1.middleware",{"title":199,"path":200,"stem":201,"titleTemplate":6,"icon":169},"modules","/docs/guide/directory-structure/modules","docs/2.guide/2.directory-structure/1.modules",{"title":203,"path":204,"stem":205,"titleTemplate":6,"icon":169},"node_modules","/docs/guide/directory-structure/node_modules","docs/2.guide/2.directory-structure/1.node_modules",{"title":207,"path":208,"stem":209,"titleTemplate":6,"icon":169},"pages","/docs/guide/directory-structure/pages","docs/2.guide/2.directory-structure/1.pages",{"title":211,"path":212,"stem":213,"titleTemplate":6,"icon":169},"plugins","/docs/guide/directory-structure/plugins","docs/2.guide/2.directory-structure/1.plugins",{"title":215,"path":216,"stem":217,"titleTemplate":6,"icon":169},"public","/docs/guide/directory-structure/public","docs/2.guide/2.directory-structure/1.public",{"title":219,"path":220,"stem":221,"titleTemplate":6,"icon":169},"server","/docs/guide/directory-structure/server","docs/2.guide/2.directory-structure/1.server",{"title":223,"path":224,"stem":225,"titleTemplate":6,"icon":169},"shared","/docs/guide/directory-structure/shared","docs/2.guide/2.directory-structure/1.shared",{"title":227,"path":228,"stem":229,"titleTemplate":6,"icon":169},"utils","/docs/guide/directory-structure/utils","docs/2.guide/2.directory-structure/1.utils",{"title":231,"path":232,"stem":233,"titleTemplate":6,"icon":234},".env","/docs/guide/directory-structure/env","docs/2.guide/2.directory-structure/2.env","i-lucide-file",{"title":236,"path":237,"stem":238,"titleTemplate":6,"icon":234},".gitignore","/docs/guide/directory-structure/gitignore","docs/2.guide/2.directory-structure/2.gitignore",{"title":240,"path":241,"stem":242,"titleTemplate":6,"icon":234},".nuxtignore","/docs/guide/directory-structure/nuxtignore","docs/2.guide/2.directory-structure/2.nuxtignore",{"title":244,"path":245,"stem":246,"titleTemplate":6,"icon":234},".nuxtrc","/docs/guide/directory-structure/nuxtrc","docs/2.guide/2.directory-structure/2.nuxtrc",{"title":248,"path":249,"stem":250,"titleTemplate":6,"icon":234},"app.vue","/docs/guide/directory-structure/app","docs/2.guide/2.directory-structure/3.app",{"title":252,"path":253,"stem":254,"titleTemplate":6,"icon":234},"app.config.ts","/docs/guide/directory-structure/app-config","docs/2.guide/2.directory-structure/3.app-config",{"title":256,"path":257,"stem":258,"titleTemplate":6,"icon":234},"error.vue","/docs/guide/directory-structure/error","docs/2.guide/2.directory-structure/3.error",{"title":260,"path":261,"stem":262,"titleTemplate":6,"icon":234},"nuxt.config.ts","/docs/guide/directory-structure/nuxt-config","docs/2.guide/2.directory-structure/3.nuxt-config",{"title":264,"path":265,"stem":266,"titleTemplate":6,"icon":234},"package.json","/docs/guide/directory-structure/package","docs/2.guide/2.directory-structure/3.package",{"title":268,"path":269,"stem":270,"titleTemplate":6,"icon":234},"tsconfig.json","/docs/guide/directory-structure/tsconfig","docs/2.guide/2.directory-structure/3.tsconfig",{"title":272,"titleTemplate":273,"icon":274,"path":275,"stem":276,"children":277,"page":108},"Going Further","%s · Nuxt Advanced","i-lucide-star","/docs/guide/going-further","docs/2.guide/3.going-further",[278,282,286,290,294,298,302,306,310,314,318],{"title":279,"path":280,"stem":281,"titleTemplate":6},"Experimental Features","/docs/guide/going-further/experimental-features","docs/2.guide/3.going-further/1.experimental-features",{"title":283,"path":284,"stem":285,"titleTemplate":6},"Features","/docs/guide/going-further/features","docs/2.guide/3.going-further/1.features",{"title":287,"path":288,"stem":289,"titleTemplate":6},"How Nuxt Works?","/docs/guide/going-further/internals","docs/2.guide/3.going-further/1.internals",{"title":291,"path":292,"stem":293,"titleTemplate":6},"Runtime Config","/docs/guide/going-further/runtime-config","docs/2.guide/3.going-further/10.runtime-config",{"title":295,"path":296,"stem":297,"titleTemplate":6},"Nightly Release Channel","/docs/guide/going-further/nightly-release-channel","docs/2.guide/3.going-further/11.nightly-release-channel",{"title":299,"path":300,"stem":301,"titleTemplate":6},"Lifecycle Hooks","/docs/guide/going-further/hooks","docs/2.guide/3.going-further/2.hooks",{"title":303,"path":304,"stem":305,"titleTemplate":6},"Module Author Guide","/docs/guide/going-further/modules","docs/2.guide/3.going-further/3.modules",{"title":307,"path":308,"stem":309,"titleTemplate":6},"Nuxt Kit","/docs/guide/going-further/kit","docs/2.guide/3.going-further/4.kit",{"title":311,"path":312,"stem":313,"titleTemplate":6},"NuxtApp","/docs/guide/going-further/nuxt-app","docs/2.guide/3.going-further/6.nuxt-app",{"title":315,"path":316,"stem":317,"titleTemplate":6},"Authoring Nuxt Layers","/docs/guide/going-further/layers","docs/2.guide/3.going-further/7.layers",{"title":319,"path":320,"stem":321,"titleTemplate":6},"Debugging","/docs/guide/going-further/debugging","docs/2.guide/3.going-further/9.debugging",{"title":323,"titleTemplate":324,"icon":325,"path":326,"stem":327,"children":328,"page":108},"Recipes","%s · Recipes","i-lucide-cooking-pot","/docs/guide/recipes","docs/2.guide/4.recipes",[329,333,337,341],{"title":330,"path":331,"stem":332,"titleTemplate":6},"Custom Routing","/docs/guide/recipes/custom-routing","docs/2.guide/4.recipes/1.custom-routing",{"title":334,"path":335,"stem":336,"titleTemplate":6},"Vite Plugins","/docs/guide/recipes/vite-plugin","docs/2.guide/4.recipes/2.vite-plugin",{"title":338,"path":339,"stem":340,"titleTemplate":6},"Custom useFetch","/docs/guide/recipes/custom-usefetch","docs/2.guide/4.recipes/3.custom-usefetch",{"title":342,"path":343,"stem":344,"titleTemplate":6},"Sessions and Authentication","/docs/guide/recipes/sessions-and-authentication","docs/2.guide/4.recipes/4.sessions-and-authentication",{"title":346,"titleTemplate":347,"icon":348,"path":349,"stem":350,"children":351,"page":108},"API","%s · Nuxt API","i-lucide-code-xml","/docs/api","docs/3.api",[352,416,539,654,721,787,800],{"title":353,"titleTemplate":354,"icon":355,"path":356,"stem":357,"children":358,"page":108},"Components","%s · Nuxt Components","i-lucide-box","/docs/api/components","docs/3.api/1.components",[359,363,367,371,375,379,384,388,392,396,400,404,408,412],{"title":360,"path":361,"stem":362,"titleTemplate":6},"\u003CClientOnly>","/docs/api/components/client-only","docs/3.api/1.components/1.client-only",{"title":364,"path":365,"stem":366,"titleTemplate":6},"\u003CDevOnly>","/docs/api/components/dev-only","docs/3.api/1.components/1.dev-only",{"title":368,"path":369,"stem":370,"titleTemplate":6},"\u003CNuxtClientFallback>","/docs/api/components/nuxt-client-fallback","docs/3.api/1.components/1.nuxt-client-fallback",{"title":372,"path":373,"stem":374,"titleTemplate":6},"\u003CNuxtPicture>","/docs/api/components/nuxt-picture","docs/3.api/1.components/10.nuxt-picture",{"title":376,"path":377,"stem":378,"titleTemplate":6},"\u003CTeleport>","/docs/api/components/teleports","docs/3.api/1.components/11.teleports",{"title":380,"path":381,"stem":382,"titleTemplate":6,"badge":383},"\u003CNuxtRouteAnnouncer>","/docs/api/components/nuxt-route-announcer","docs/3.api/1.components/12.nuxt-route-announcer","New",{"title":385,"path":386,"stem":387,"titleTemplate":6},"\u003CNuxtPage>","/docs/api/components/nuxt-page","docs/3.api/1.components/2.nuxt-page",{"title":389,"path":390,"stem":391,"titleTemplate":6},"\u003CNuxtLayout>","/docs/api/components/nuxt-layout","docs/3.api/1.components/3.nuxt-layout",{"title":393,"path":394,"stem":395,"titleTemplate":6},"\u003CNuxtLink>","/docs/api/components/nuxt-link","docs/3.api/1.components/4.nuxt-link",{"title":397,"path":398,"stem":399,"titleTemplate":6},"\u003CNuxtLoadingIndicator>","/docs/api/components/nuxt-loading-indicator","docs/3.api/1.components/5.nuxt-loading-indicator",{"title":401,"path":402,"stem":403,"titleTemplate":6},"\u003CNuxtErrorBoundary>","/docs/api/components/nuxt-error-boundary","docs/3.api/1.components/6.nuxt-error-boundary",{"title":405,"path":406,"stem":407,"titleTemplate":6},"\u003CNuxtWelcome>","/docs/api/components/nuxt-welcome","docs/3.api/1.components/7.nuxt-welcome",{"title":409,"path":410,"stem":411,"titleTemplate":6},"\u003CNuxtIsland>","/docs/api/components/nuxt-island","docs/3.api/1.components/8.nuxt-island",{"title":413,"path":414,"stem":415,"titleTemplate":6},"\u003CNuxtImg>","/docs/api/components/nuxt-img","docs/3.api/1.components/9.nuxt-img",{"title":417,"titleTemplate":418,"icon":419,"path":420,"stem":421,"children":422,"page":108},"Composables","%s · Nuxt Composables","i-lucide-arrow-left-right","/docs/api/composables","docs/3.api/2.composables",[423,427,431,435,439,443,447,451,455,459,463,467,471,475,479,483,487,491,495,499,503,507,511,515,519,523,527,531,535],{"title":424,"path":425,"stem":426,"titleTemplate":6},"onPrehydrate","/docs/api/composables/on-prehydrate","docs/3.api/2.composables/on-prehydrate",{"title":428,"path":429,"stem":430,"titleTemplate":6},"useAppConfig","/docs/api/composables/use-app-config","docs/3.api/2.composables/use-app-config",{"title":432,"path":433,"stem":434,"titleTemplate":6},"useAsyncData","/docs/api/composables/use-async-data","docs/3.api/2.composables/use-async-data",{"title":436,"path":437,"stem":438,"titleTemplate":6},"useCookie","/docs/api/composables/use-cookie","docs/3.api/2.composables/use-cookie",{"title":440,"path":441,"stem":442,"titleTemplate":6},"useError","/docs/api/composables/use-error","docs/3.api/2.composables/use-error",{"title":444,"path":445,"stem":446,"titleTemplate":6},"useFetch","/docs/api/composables/use-fetch","docs/3.api/2.composables/use-fetch",{"title":448,"path":449,"stem":450,"titleTemplate":6},"useHead","/docs/api/composables/use-head","docs/3.api/2.composables/use-head",{"title":452,"path":453,"stem":454,"titleTemplate":6},"useHeadSafe","/docs/api/composables/use-head-safe","docs/3.api/2.composables/use-head-safe",{"title":456,"path":457,"stem":458,"titleTemplate":6},"useHydration","/docs/api/composables/use-hydration","docs/3.api/2.composables/use-hydration",{"title":460,"path":461,"stem":462,"titleTemplate":6},"useLazyAsyncData","/docs/api/composables/use-lazy-async-data","docs/3.api/2.composables/use-lazy-async-data",{"title":464,"path":465,"stem":466,"titleTemplate":6},"useLazyFetch","/docs/api/composables/use-lazy-fetch","docs/3.api/2.composables/use-lazy-fetch",{"title":468,"path":469,"stem":470,"titleTemplate":6},"useLoadingIndicator","/docs/api/composables/use-loading-indicator","docs/3.api/2.composables/use-loading-indicator",{"title":472,"path":473,"stem":474,"titleTemplate":6},"useNuxtApp","/docs/api/composables/use-nuxt-app","docs/3.api/2.composables/use-nuxt-app",{"title":476,"path":477,"stem":478,"titleTemplate":6},"useNuxtData","/docs/api/composables/use-nuxt-data","docs/3.api/2.composables/use-nuxt-data",{"title":480,"path":481,"stem":482,"titleTemplate":6},"usePreviewMode","/docs/api/composables/use-preview-mode","docs/3.api/2.composables/use-preview-mode",{"title":484,"path":485,"stem":486,"titleTemplate":6},"useRequestEvent","/docs/api/composables/use-request-event","docs/3.api/2.composables/use-request-event",{"title":488,"path":489,"stem":490,"titleTemplate":6},"useRequestFetch","/docs/api/composables/use-request-fetch","docs/3.api/2.composables/use-request-fetch",{"title":492,"path":493,"stem":494,"titleTemplate":6},"useRequestHeader","/docs/api/composables/use-request-header","docs/3.api/2.composables/use-request-header",{"title":496,"path":497,"stem":498,"titleTemplate":6},"useRequestHeaders","/docs/api/composables/use-request-headers","docs/3.api/2.composables/use-request-headers",{"title":500,"path":501,"stem":502,"titleTemplate":6},"useRequestURL","/docs/api/composables/use-request-url","docs/3.api/2.composables/use-request-url",{"title":504,"path":505,"stem":506,"titleTemplate":6},"useResponseHeader","/docs/api/composables/use-response-header","docs/3.api/2.composables/use-response-header",{"title":508,"path":509,"stem":510,"titleTemplate":6},"useRoute","/docs/api/composables/use-route","docs/3.api/2.composables/use-route",{"title":512,"path":513,"stem":514,"titleTemplate":6,"badge":383},"useRouteAnnouncer","/docs/api/composables/use-route-announcer","docs/3.api/2.composables/use-route-announcer",{"title":516,"path":517,"stem":518,"titleTemplate":6},"useRouter","/docs/api/composables/use-router","docs/3.api/2.composables/use-router",{"title":520,"path":521,"stem":522,"titleTemplate":6},"useRuntimeConfig","/docs/api/composables/use-runtime-config","docs/3.api/2.composables/use-runtime-config",{"title":524,"path":525,"stem":526,"titleTemplate":6},"useRuntimeHook","/docs/api/composables/use-runtime-hook","docs/3.api/2.composables/use-runtime-hook",{"title":528,"path":529,"stem":530,"titleTemplate":6},"useSeoMeta","/docs/api/composables/use-seo-meta","docs/3.api/2.composables/use-seo-meta",{"title":532,"path":533,"stem":534,"titleTemplate":6},"useServerSeoMeta","/docs/api/composables/use-server-seo-meta","docs/3.api/2.composables/use-server-seo-meta",{"title":536,"path":537,"stem":538,"titleTemplate":6},"useState","/docs/api/composables/use-state","docs/3.api/2.composables/use-state",{"title":540,"titleTemplate":541,"icon":542,"path":543,"stem":544,"children":545,"page":108},"Utils","%s · Nuxt Utils","i-lucide-square-function","/docs/api/utils","docs/3.api/3.utils",[546,550,554,558,562,566,570,574,578,582,586,590,594,598,602,606,610,614,618,622,626,630,634,638,642,646,650],{"title":547,"path":548,"stem":549,"titleTemplate":6},"$fetch","/docs/api/utils/dollarfetch","docs/3.api/3.utils/$fetch",{"title":551,"path":552,"stem":553,"titleTemplate":6},"abortNavigation","/docs/api/utils/abort-navigation","docs/3.api/3.utils/abort-navigation",{"title":555,"path":556,"stem":557,"titleTemplate":6},"addRouteMiddleware","/docs/api/utils/add-route-middleware","docs/3.api/3.utils/add-route-middleware",{"title":559,"path":560,"stem":561,"titleTemplate":6,"badge":383},"callOnce","/docs/api/utils/call-once","docs/3.api/3.utils/call-once",{"title":563,"path":564,"stem":565,"titleTemplate":6},"clearError","/docs/api/utils/clear-error","docs/3.api/3.utils/clear-error",{"title":567,"path":568,"stem":569,"titleTemplate":6},"clearNuxtData","/docs/api/utils/clear-nuxt-data","docs/3.api/3.utils/clear-nuxt-data",{"title":571,"path":572,"stem":573,"titleTemplate":6},"clearNuxtState","/docs/api/utils/clear-nuxt-state","docs/3.api/3.utils/clear-nuxt-state",{"title":575,"path":576,"stem":577,"titleTemplate":6},"createError","/docs/api/utils/create-error","docs/3.api/3.utils/create-error",{"title":579,"path":580,"stem":581,"titleTemplate":6},"defineNuxtComponent","/docs/api/utils/define-nuxt-component","docs/3.api/3.utils/define-nuxt-component",{"title":583,"path":584,"stem":585,"titleTemplate":6},"defineNuxtRouteMiddleware","/docs/api/utils/define-nuxt-route-middleware","docs/3.api/3.utils/define-nuxt-route-middleware",{"title":587,"path":588,"stem":589,"titleTemplate":6},"definePageMeta","/docs/api/utils/define-page-meta","docs/3.api/3.utils/define-page-meta",{"title":591,"path":592,"stem":593,"titleTemplate":6},"defineRouteRules","/docs/api/utils/define-route-rules","docs/3.api/3.utils/define-route-rules",{"title":595,"path":596,"stem":597,"titleTemplate":6},"navigateTo","/docs/api/utils/navigate-to","docs/3.api/3.utils/navigate-to",{"title":599,"path":600,"stem":601,"titleTemplate":6},"onBeforeRouteLeave","/docs/api/utils/on-before-route-leave","docs/3.api/3.utils/on-before-route-leave",{"title":603,"path":604,"stem":605,"titleTemplate":6},"onBeforeRouteUpdate","/docs/api/utils/on-before-route-update","docs/3.api/3.utils/on-before-route-update",{"title":607,"path":608,"stem":609,"titleTemplate":6},"onNuxtReady","/docs/api/utils/on-nuxt-ready","docs/3.api/3.utils/on-nuxt-ready",{"title":611,"path":612,"stem":613,"titleTemplate":6},"prefetchComponents","/docs/api/utils/prefetch-components","docs/3.api/3.utils/prefetch-components",{"title":615,"path":616,"stem":617,"titleTemplate":6},"preloadComponents","/docs/api/utils/preload-components","docs/3.api/3.utils/preload-components",{"title":619,"path":620,"stem":621,"titleTemplate":6},"preloadRouteComponents","/docs/api/utils/preload-route-components","docs/3.api/3.utils/preload-route-components",{"title":623,"path":624,"stem":625,"titleTemplate":6},"prerenderRoutes","/docs/api/utils/prerender-routes","docs/3.api/3.utils/prerender-routes",{"title":627,"path":628,"stem":629,"titleTemplate":6,"badge":383},"refreshCookie","/docs/api/utils/refresh-cookie","docs/3.api/3.utils/refresh-cookie",{"title":631,"path":632,"stem":633,"titleTemplate":6},"refreshNuxtData","/docs/api/utils/refresh-nuxt-data","docs/3.api/3.utils/refresh-nuxt-data",{"title":635,"path":636,"stem":637,"titleTemplate":6},"reloadNuxtApp","/docs/api/utils/reload-nuxt-app","docs/3.api/3.utils/reload-nuxt-app",{"title":639,"path":640,"stem":641,"titleTemplate":6},"setPageLayout","/docs/api/utils/set-page-layout","docs/3.api/3.utils/set-page-layout",{"title":643,"path":644,"stem":645,"titleTemplate":6},"setResponseStatus","/docs/api/utils/set-response-status","docs/3.api/3.utils/set-response-status",{"title":647,"path":648,"stem":649,"titleTemplate":6},"showError","/docs/api/utils/show-error","docs/3.api/3.utils/show-error",{"title":651,"path":652,"stem":653,"titleTemplate":6},"updateAppConfig","/docs/api/utils/update-app-config","docs/3.api/3.utils/update-app-config",{"title":655,"titleTemplate":656,"icon":657,"path":658,"stem":659,"children":660,"page":108},"Commands","%s · Nuxt Commands","i-lucide-square-terminal","/docs/api/commands","docs/3.api/4.commands",[661,665,669,673,677,681,685,689,693,697,701,705,709,713,717],{"title":662,"path":663,"stem":664,"titleTemplate":6},"nuxi add","/docs/api/commands/add","docs/3.api/4.commands/add",{"title":666,"path":667,"stem":668,"titleTemplate":6},"nuxi analyze","/docs/api/commands/analyze","docs/3.api/4.commands/analyze",{"title":670,"path":671,"stem":672,"titleTemplate":6},"nuxi build","/docs/api/commands/build","docs/3.api/4.commands/build",{"title":674,"path":675,"stem":676,"titleTemplate":6},"nuxi build-module","/docs/api/commands/build-module","docs/3.api/4.commands/build-module",{"title":678,"path":679,"stem":680,"titleTemplate":6},"nuxi cleanup","/docs/api/commands/cleanup","docs/3.api/4.commands/cleanup",{"title":682,"path":683,"stem":684,"titleTemplate":6},"nuxi dev","/docs/api/commands/dev","docs/3.api/4.commands/dev",{"title":686,"path":687,"stem":688,"titleTemplate":6},"nuxi devtools","/docs/api/commands/devtools","docs/3.api/4.commands/devtools",{"title":690,"path":691,"stem":692,"titleTemplate":6},"nuxi generate","/docs/api/commands/generate","docs/3.api/4.commands/generate",{"title":694,"path":695,"stem":696,"titleTemplate":6},"nuxi info","/docs/api/commands/info","docs/3.api/4.commands/info",{"title":698,"path":699,"stem":700,"titleTemplate":6},"nuxi init","/docs/api/commands/init","docs/3.api/4.commands/init",{"title":702,"path":703,"stem":704,"titleTemplate":6},"nuxi module","/docs/api/commands/module","docs/3.api/4.commands/module",{"title":706,"path":707,"stem":708,"titleTemplate":6},"nuxi prepare","/docs/api/commands/prepare","docs/3.api/4.commands/prepare",{"title":710,"path":711,"stem":712,"titleTemplate":6},"nuxi preview","/docs/api/commands/preview","docs/3.api/4.commands/preview",{"title":714,"path":715,"stem":716,"titleTemplate":6},"nuxi typecheck","/docs/api/commands/typecheck","docs/3.api/4.commands/typecheck",{"title":718,"path":719,"stem":720,"titleTemplate":6},"nuxi upgrade","/docs/api/commands/upgrade","docs/3.api/4.commands/upgrade",{"title":307,"titleTemplate":722,"icon":723,"path":724,"stem":725,"children":726,"page":108},"%s · Nuxt Kit","i-lucide-package","/docs/api/kit","docs/3.api/5.kit",[727,730,733,737,741,745,749,753,757,761,765,768,771,775,779,783],{"title":143,"path":728,"stem":729,"titleTemplate":6},"/docs/api/kit/modules","docs/3.api/5.kit/1.modules",{"title":291,"path":731,"stem":732,"titleTemplate":6},"/docs/api/kit/runtime-config","docs/3.api/5.kit/10.runtime-config",{"title":734,"path":735,"stem":736,"titleTemplate":6},"Templates","/docs/api/kit/templates","docs/3.api/5.kit/10.templates",{"title":738,"path":739,"stem":740,"titleTemplate":6},"Nitro","/docs/api/kit/nitro","docs/3.api/5.kit/11.nitro",{"title":742,"path":743,"stem":744,"titleTemplate":6},"Resolving","/docs/api/kit/resolving","docs/3.api/5.kit/12.resolving",{"title":746,"path":747,"stem":748,"titleTemplate":6},"Logging","/docs/api/kit/logging","docs/3.api/5.kit/13.logging",{"title":750,"path":751,"stem":752,"titleTemplate":6},"Builder","/docs/api/kit/builder","docs/3.api/5.kit/14.builder",{"title":754,"path":755,"stem":756,"titleTemplate":6},"Examples","/docs/api/kit/examples","docs/3.api/5.kit/15.examples",{"title":758,"path":759,"stem":760,"titleTemplate":6},"Programmatic Usage","/docs/api/kit/programmatic","docs/3.api/5.kit/2.programmatic",{"title":762,"path":763,"stem":764,"titleTemplate":6},"Compatibility","/docs/api/kit/compatibility","docs/3.api/5.kit/3.compatibility",{"title":123,"path":766,"stem":767,"titleTemplate":6},"/docs/api/kit/autoimports","docs/3.api/5.kit/4.autoimports",{"title":353,"path":769,"stem":770,"titleTemplate":6},"/docs/api/kit/components","docs/3.api/5.kit/5.components",{"title":772,"path":773,"stem":774,"titleTemplate":6},"Context","/docs/api/kit/context","docs/3.api/5.kit/6.context",{"title":776,"path":777,"stem":778,"titleTemplate":6},"Pages","/docs/api/kit/pages","docs/3.api/5.kit/7.pages",{"title":780,"path":781,"stem":782,"titleTemplate":6},"Layout","/docs/api/kit/layout","docs/3.api/5.kit/8.layout",{"title":784,"path":785,"stem":786,"titleTemplate":6},"Plugins","/docs/api/kit/plugins","docs/3.api/5.kit/9.plugins",{"title":788,"titleTemplate":6,"icon":789,"path":790,"stem":791,"children":792,"page":108},"Advanced","i-lucide-brain","/docs/api/advanced","docs/3.api/6.advanced",[793,796],{"title":299,"path":794,"stem":795,"titleTemplate":6},"/docs/api/advanced/hooks","docs/3.api/6.advanced/1.hooks",{"title":797,"path":798,"stem":799,"titleTemplate":6},"Import meta","/docs/api/advanced/import-meta","docs/3.api/6.advanced/2.import-meta",{"title":801,"path":802,"stem":803,"titleTemplate":804,"icon":32},"Nuxt Configuration","/docs/api/nuxt-config","docs/3.api/6.nuxt-config","%s",{"title":754,"titleTemplate":806,"icon":807,"path":808,"stem":809,"children":810,"page":108},"%s · Nuxt Examples","i-lucide-app-window-mac","/docs/examples","docs/4.examples",[811,815,837,852,888],{"title":812,"path":813,"stem":814,"titleTemplate":6},"Hello World","/docs/examples/hello-world","docs/4.examples/0.hello-world",{"title":283,"path":816,"stem":817,"children":818,"page":108},"/docs/examples/features","docs/4.examples/1.features",[819,823,826,829,833],{"title":820,"path":821,"stem":822,"titleTemplate":6},"Auto Imports","/docs/examples/features/auto-imports","docs/4.examples/1.features/1.auto-imports",{"title":64,"path":824,"stem":825,"titleTemplate":6},"/docs/examples/features/data-fetching","docs/4.examples/1.features/2.data-fetching",{"title":69,"path":827,"stem":828,"titleTemplate":6},"/docs/examples/features/state-management","docs/4.examples/1.features/3.state-management",{"title":830,"path":831,"stem":832,"titleTemplate":6},"Meta Tags","/docs/examples/features/meta-tags","docs/4.examples/1.features/4.meta-tags",{"title":834,"path":835,"stem":836,"titleTemplate":6},"Layouts","/docs/examples/features/layouts","docs/4.examples/1.features/5.layouts",{"title":49,"path":838,"stem":839,"children":840,"page":108},"/docs/examples/routing","docs/4.examples/2.routing",[841,845,848],{"title":842,"path":843,"stem":844,"titleTemplate":6},"Middleware","/docs/examples/routing/middleware","docs/4.examples/2.routing/middleware",{"title":776,"path":846,"stem":847,"titleTemplate":6},"/docs/examples/routing/pages","docs/4.examples/2.routing/pages",{"title":849,"path":850,"stem":851,"titleTemplate":6},"Universal Router","/docs/examples/routing/universal-router","docs/4.examples/2.routing/universal-router",{"title":788,"path":853,"stem":854,"children":855,"page":108},"/docs/examples/advanced","docs/4.examples/4.advanced",[856,859,862,866,870,874,878,881,884],{"title":84,"path":857,"stem":858,"titleTemplate":6},"/docs/examples/advanced/config-extends","docs/4.examples/4.advanced/config-extends",{"title":74,"path":860,"stem":861,"titleTemplate":6},"/docs/examples/advanced/error-handling","docs/4.examples/4.advanced/error-handling",{"title":863,"path":864,"stem":865,"titleTemplate":6},"JSX / TSX","/docs/examples/advanced/jsx","docs/4.examples/4.advanced/jsx",{"title":867,"path":868,"stem":869,"titleTemplate":6},"Locale","/docs/examples/advanced/locale","docs/4.examples/4.advanced/locale",{"title":871,"path":872,"stem":873,"titleTemplate":6},"Module Extend Pages","/docs/examples/advanced/module-extend-pages","docs/4.examples/4.advanced/module-extend-pages",{"title":875,"path":876,"stem":877,"titleTemplate":6},"Teleport","/docs/examples/advanced/teleport","docs/4.examples/4.advanced/teleport",{"title":99,"path":879,"stem":880,"titleTemplate":6},"/docs/examples/advanced/testing","docs/4.examples/4.advanced/testing",{"title":436,"path":882,"stem":883,"titleTemplate":6},"/docs/examples/advanced/use-cookie","docs/4.examples/4.advanced/use-cookie",{"title":885,"path":886,"stem":887,"titleTemplate":6},"Use Custom Fetch Composable","/docs/examples/advanced/use-custom-fetch-composable","docs/4.examples/4.advanced/use-custom-fetch-composable",{"title":889,"path":890,"stem":891,"children":892,"page":108},"Experimental","/docs/examples/experimental","docs/4.examples/7.experimental",[893],{"title":894,"path":895,"stem":896,"titleTemplate":6},"WASM","/docs/examples/experimental/wasm","docs/4.examples/7.experimental/wasm",{"title":898,"titleTemplate":899,"icon":900,"path":901,"stem":902,"children":903,"page":108},"Community","%s · Nuxt Community","i-lucide-messages-square","/docs/community","docs/5.community",[904,909,914,919,924,929],{"title":905,"path":906,"stem":907,"titleTemplate":6,"icon":908},"Getting Help","/docs/community/getting-help","docs/5.community/2.getting-help","i-lucide-life-buoy",{"title":910,"path":911,"stem":912,"titleTemplate":6,"icon":913},"Reporting Bugs","/docs/community/reporting-bugs","docs/5.community/3.reporting-bugs","i-lucide-bug",{"title":915,"path":916,"stem":917,"titleTemplate":6,"icon":918},"Contribution","/docs/community/contribution","docs/5.community/4.contribution","i-lucide-git-pull-request",{"title":920,"path":921,"stem":922,"titleTemplate":6,"icon":923},"Framework","/docs/community/framework-contribution","docs/5.community/5.framework-contribution","i-lucide-github",{"title":925,"path":926,"stem":927,"titleTemplate":6,"icon":928},"Roadmap","/docs/community/roadmap","docs/5.community/6.roadmap","i-lucide-map",{"title":930,"path":931,"stem":932,"titleTemplate":6,"icon":933},"Releases","/docs/community/changelog","docs/5.community/7.changelog","i-lucide-bell-dot",{"title":935,"titleTemplate":936,"icon":937,"path":938,"stem":939,"children":940,"page":108},"Migrate to Nuxt Bridge","Migrate to Nuxt Bridge: %s","i-lucide-ship","/docs/bridge","docs/6.bridge",[941,945,948,951,955,959,963,966,969,972],{"title":942,"path":943,"stem":944,"titleTemplate":6},"Overview","/docs/bridge/overview","docs/6.bridge/1.overview",{"title":29,"path":946,"stem":947,"titleTemplate":6},"/docs/bridge/configuration","docs/6.bridge/10.configuration",{"title":151,"path":949,"stem":950,"titleTemplate":6},"/docs/bridge/typescript","docs/6.bridge/2.typescript",{"title":952,"path":953,"stem":954,"titleTemplate":6},"Legacy Composition API","/docs/bridge/bridge-composition-api","docs/6.bridge/3.bridge-composition-api",{"title":956,"path":957,"stem":958,"titleTemplate":6},"Plugins and Middleware","/docs/bridge/plugins-and-middleware","docs/6.bridge/4.plugins-and-middleware",{"title":960,"path":961,"stem":962,"titleTemplate":6},"New Composition API","/docs/bridge/nuxt3-compatible-api","docs/6.bridge/5.nuxt3-compatible-api",{"title":830,"path":964,"stem":965,"titleTemplate":6},"/docs/bridge/meta","docs/6.bridge/6.meta",{"title":291,"path":967,"stem":968,"titleTemplate":6},"/docs/bridge/runtime-config","docs/6.bridge/7.runtime-config",{"title":738,"path":970,"stem":971,"titleTemplate":6},"/docs/bridge/nitro","docs/6.bridge/8.nitro",{"title":973,"path":974,"stem":975,"titleTemplate":6},"Vite","/docs/bridge/vite","docs/6.bridge/9.vite",{"title":977,"titleTemplate":978,"icon":107,"path":979,"stem":980,"children":981,"page":108},"Migrate to Nuxt 3","Migrate to Nuxt 3: %s","/docs/migration","docs/7.migration",[982,985,989,992,995,998,1001,1004,1007,1011,1015],{"title":942,"path":983,"stem":984,"titleTemplate":6},"/docs/migration/overview","docs/7.migration/1.overview",{"title":986,"path":987,"stem":988,"titleTemplate":6},"Build Tooling","/docs/migration/bundling","docs/7.migration/10.bundling",{"title":79,"path":990,"stem":991,"titleTemplate":6},"/docs/migration/server","docs/7.migration/11.server",{"title":29,"path":993,"stem":994,"titleTemplate":6},"/docs/migration/configuration","docs/7.migration/2.configuration",{"title":143,"path":996,"stem":997,"titleTemplate":6},"/docs/migration/module-authors","docs/7.migration/20.module-authors",{"title":820,"path":999,"stem":1000,"titleTemplate":6},"/docs/migration/auto-imports","docs/7.migration/3.auto-imports",{"title":830,"path":1002,"stem":1003,"titleTemplate":6},"/docs/migration/meta","docs/7.migration/4.meta",{"title":956,"path":1005,"stem":1006,"titleTemplate":6},"/docs/migration/plugins-and-middleware","docs/7.migration/5.plugins-and-middleware",{"title":1008,"path":1009,"stem":1010,"titleTemplate":6},"Pages and Layouts","/docs/migration/pages-and-layouts","docs/7.migration/6.pages-and-layouts",{"title":1012,"path":1013,"stem":1014,"titleTemplate":6},"Component Options","/docs/migration/component-options","docs/7.migration/7.component-options",{"title":291,"path":1016,"stem":1017,"titleTemplate":6},"/docs/migration/runtime-config","docs/7.migration/8.runtime-config",{"title":1019,"path":1020,"stem":1021,"children":1022,"page":108},"Blog","/blog","blog",[1023,1027,1031,1035,1039,1043,1047,1051,1055,1059,1063,1067,1071,1075,1079,1083,1087,1091,1095,1099,1103],{"title":1024,"path":1025,"stem":1026},"Announcing 3.0","/blog/v3","blog/1.v3",{"title":1028,"path":1029,"stem":1030},"Nuxt 3.3","/blog/v3-3","blog/10.v3-3",{"title":1032,"path":1033,"stem":1034},"Nuxt 3.4","/blog/v3-4","blog/11.v3-4",{"title":1036,"path":1037,"stem":1038},"Nuxt 3.5","/blog/v3-5","blog/12.v3-5",{"title":1040,"path":1041,"stem":1042},"Nuxt 3.6","/blog/v3-6","blog/13.v3-6",{"title":1044,"path":1045,"stem":1046},"Nuxt on the Edge","/blog/nuxt-on-the-edge","blog/14.nuxt-on-the-edge",{"title":1048,"path":1049,"stem":1050},"Nuxt DevTools v1.0","/blog/nuxt-devtools-v1-0","blog/18.nuxt-devtools-v1-0",{"title":1052,"path":1053,"stem":1054},"Nuxt: A vision for 2023","/blog/vision-2023","blog/2.vision-2023",{"title":1056,"path":1057,"stem":1058},"The Evolution of Shiki v1.0","/blog/shiki-v1","blog/21.shiki-v1",{"title":1060,"path":1061,"stem":1062},"Refreshed Nuxt ESLint Integrations","/blog/eslint-module","blog/24.eslint-module",{"title":1064,"path":1065,"stem":1066},"Introducing Nuxt Scripts","/blog/nuxt-scripts","blog/26.nuxt-scripts",{"title":1068,"path":1069,"stem":1070},"Introducing Nuxt Icon v1","/blog/nuxt-icon-v1-0","blog/29.nuxt-icon-v1-0",{"title":1072,"path":1073,"stem":1074},"Introducing Nuxt DevTools","/blog/introducing-nuxt-devtools","blog/3.introducing-nuxt-devtools",{"title":1076,"path":1077,"stem":1078},"Announcing Nuxt 3 Release Candidate","/blog/nuxt3-rc","blog/3.nuxt3-rc",{"title":1080,"path":1081,"stem":1082},"Nuxt 2 End-of-Life (EOL)","/blog/nuxt2-eol","blog/4.nuxt2-eol",{"title":1084,"path":1085,"stem":1086},"Introducing Nuxt 3 Beta","/blog/nuxt3-beta","blog/4.nuxt3-beta",{"title":1088,"path":1089,"stem":1090},"Going Full Static","/blog/going-full-static","blog/5.going-full-static",{"title":1092,"path":1093,"stem":1094},"Introducing Smart Prefetching","/blog/introducing-smart-prefetching","blog/6.introducing-smart-prefetching",{"title":1096,"path":1097,"stem":1098},"Understanding how fetch works in Nuxt 2.12","/blog/understanding-how-fetch-works-in-nuxt-2-12","blog/7.understanding-how-fetch-works-in-nuxt-2-12",{"title":1100,"path":1101,"stem":1102},"Nuxt 2 Static Improvements","/blog/nuxt-static-improvements","blog/8.nuxt-static-improvements",{"title":1104,"path":1105,"stem":1106},"Nuxt 2: From Terminal to Browser","/blog/nuxtjs-from-terminal-to-browser","blog/9.nuxtjs-from-terminal-to-browser",{"id":1108,"title":1109,"body":1110,"cta":6,"description":1113,"extension":1114,"head":6,"headline":6,"image":6,"links":6,"meta":1115,"navigation":1116,"path":1020,"seo":1117,"stem":1021,"__hash__":1118},"landing/blog.yml","The Nuxt Blog",{"title":1109,"navigation":1111,"description":1113},{"title":1019,"icon":1112},"i-lucide-newspaper","Read the latest news about all Nuxt solutions, from framework announcements to integration tutorials.","yml",{},{"title":1019,"icon":1112},{"title":1109,"description":1113},"HzmzFRuQzL",[1120,2185,3658,4062,4660,4976,5689,7715,7887,8417,9841,10419,11622,13244,14259,14949,15616,16900,17327,17901,18349,18691,19444,20162,20852,21541,21765,21917,22279,22523,23177,23889,25518,25661],{"id":1121,"title":1122,"authors":1123,"body":1139,"category":2176,"date":2177,"description":2178,"draft":108,"extension":1954,"image":2179,"meta":2180,"navigation":108,"path":2181,"seo":2182,"stem":2183,"tags":6,"__hash__":2184},"blog/blog/32.nuxt-ui-v3.md","Nuxt UI v3",[1124,1129,1134],{"name":1125,"avatar":1126,"to":1128},"Benjamin Canac",{"src":1127},"https://github.com/benjamincanac.png","https://x.com/benjamincanac",{"name":1130,"avatar":1131,"to":1133},"Sébastien Chopin",{"src":1132},"https://github.com/atinux.png","https://x.com/atinux",{"name":1135,"avatar":1136,"to":1138},"Hugo Richard",{"src":1137},"https://github.com/hugorcd.png","https://x.com/hugorcd__",{"type":1140,"value":1141,"toc":2163},"minimal",[1142,1146,1151,1154,1162,1165,1168,1171,1174,1177,1180,1186,1189,1196,1202,1205,1208,1212,1362,1505,1508,1645,1648,1652,1655,1658,1661,1664,1667,1805,1809,1812,1818,1824,1830,1836,1841,1844,1848,1851,1864,1998,2002,2013,2017,2020,2053,2116,2140,2149,2153,2156,2159],[1143,1144,1145],"p",{},"We are thrilled to announce the release of Nuxt UI v3, a complete redesign of our UI library that brings significant improvements in accessibility, performance, and developer experience. This major update represents over 1500 commits of hard work, collaboration, and innovation from our team and the community.",[1147,1148,1150],"h2",{"id":1149},"reimagined-from-the-ground-up","🚀 Reimagined from the Ground Up",[1143,1152,1153],{},"Nuxt UI v3 represents a major leap forward in our journey to provide the most comprehensive UI solution for Vue and Nuxt developers. This version has been rebuilt from the ground up with modern technologies and best practices in mind.",[1155,1156,1158],"h3",{"id":1157},"from-headlessui-to-reka-ui",[1159,1160,1161],"strong",{},"From HeadlessUI to Reka UI",[1143,1163,1164],{},"With Reka UI at its core, Nuxt UI v3 delivers:",[1143,1166,1167],{},"• Proper keyboard navigation across all interactive components",[1143,1169,1170],{},"• ARIA attributes automatically handled for you",[1143,1172,1173],{},"• Focus management that just works",[1143,1175,1176],{},"• Screen reader friendly components out of the box",[1143,1178,1179],{},"This means you can build applications that work for everyone without becoming an accessibility expert.",[1155,1181,1183],{"id":1182},"tailwind-css-v4-integration",[1159,1184,1185],{},"Tailwind CSS v4 Integration",[1143,1187,1188],{},"The integration with Tailwind CSS v4 brings huge performance improvements:",[1143,1190,1191,1192,1195],{},"• ",[1159,1193,1194],{},"5x faster runtime"," with optimized component rendering",[1143,1197,1191,1198,1201],{},[1159,1199,1200],{},"100x faster build times"," thanks to the new CSS-first engine",[1143,1203,1204],{},"• Smaller bundle sizes with more efficient styling",[1143,1206,1207],{},"Your applications will feel snappier, build quicker, and load faster for your users.",[1147,1209,1211],{"id":1210},"a-brand-new-design-system","🎨 A Brand New Design System",[1213,1214,1219],"pre",{"className":1215,"code":1216,"language":1217,"meta":1218,"style":1218},"language-html shiki shiki-themes material-theme-lighter material-theme-lighter material-theme-palenight","\u003C!-- Before: Inconsistent color usage with duplicate dark mode classes -->\n\u003Cdiv class=\"bg-gray-100 dark:bg-gray-800 p-4 rounded-lg\">\n  \u003Ch2 class=\"text-gray-900 dark:text-white text-xl mb-2\">User Profile\u003C/h2>\n  \u003Cp class=\"text-gray-600 dark:text-gray-300\">Account settings and preferences\u003C/p>\n  \u003Cbutton class=\"bg-blue-500 text-white px-3 py-1 rounded mt-2\">Edit Profile\u003C/button>\n\u003C/div>\n","html","",[1220,1221,1222,1231,1261,1294,1323,1353],"code",{"__ignoreMap":1218},[1223,1224,1227],"span",{"class":1225,"line":1226},"line",1,[1223,1228,1230],{"class":1229},"svXlt","\u003C!-- Before: Inconsistent color usage with duplicate dark mode classes -->\n",[1223,1232,1234,1238,1242,1246,1249,1252,1256,1258],{"class":1225,"line":1233},2,[1223,1235,1237],{"class":1236},"sYp4K","\u003C",[1223,1239,1241],{"class":1240},"sQ5dg","div",[1223,1243,1245],{"class":1244},"sRBFq"," class",[1223,1247,1248],{"class":1236},"=",[1223,1250,1251],{"class":1236},"\"",[1223,1253,1255],{"class":1254},"s5UST","bg-gray-100 dark:bg-gray-800 p-4 rounded-lg",[1223,1257,1251],{"class":1236},[1223,1259,1260],{"class":1236},">\n",[1223,1262,1264,1267,1269,1271,1273,1275,1278,1280,1283,1287,1290,1292],{"class":1225,"line":1263},3,[1223,1265,1266],{"class":1236},"  \u003C",[1223,1268,1147],{"class":1240},[1223,1270,1245],{"class":1244},[1223,1272,1248],{"class":1236},[1223,1274,1251],{"class":1236},[1223,1276,1277],{"class":1254},"text-gray-900 dark:text-white text-xl mb-2",[1223,1279,1251],{"class":1236},[1223,1281,1282],{"class":1236},">",[1223,1284,1286],{"class":1285},"spdxX","User Profile",[1223,1288,1289],{"class":1236},"\u003C/",[1223,1291,1147],{"class":1240},[1223,1293,1260],{"class":1236},[1223,1295,1297,1299,1301,1303,1305,1307,1310,1312,1314,1317,1319,1321],{"class":1225,"line":1296},4,[1223,1298,1266],{"class":1236},[1223,1300,1143],{"class":1240},[1223,1302,1245],{"class":1244},[1223,1304,1248],{"class":1236},[1223,1306,1251],{"class":1236},[1223,1308,1309],{"class":1254},"text-gray-600 dark:text-gray-300",[1223,1311,1251],{"class":1236},[1223,1313,1282],{"class":1236},[1223,1315,1316],{"class":1285},"Account settings and preferences",[1223,1318,1289],{"class":1236},[1223,1320,1143],{"class":1240},[1223,1322,1260],{"class":1236},[1223,1324,1326,1328,1331,1333,1335,1337,1340,1342,1344,1347,1349,1351],{"class":1225,"line":1325},5,[1223,1327,1266],{"class":1236},[1223,1329,1330],{"class":1240},"button",[1223,1332,1245],{"class":1244},[1223,1334,1248],{"class":1236},[1223,1336,1251],{"class":1236},[1223,1338,1339],{"class":1254},"bg-blue-500 text-white px-3 py-1 rounded mt-2",[1223,1341,1251],{"class":1236},[1223,1343,1282],{"class":1236},[1223,1345,1346],{"class":1285},"Edit Profile",[1223,1348,1289],{"class":1236},[1223,1350,1330],{"class":1240},[1223,1352,1260],{"class":1236},[1223,1354,1356,1358,1360],{"class":1225,"line":1355},6,[1223,1357,1289],{"class":1236},[1223,1359,1241],{"class":1240},[1223,1361,1260],{"class":1236},[1213,1363,1365],{"className":1215,"code":1364,"language":1217,"meta":1218,"style":1218},"\u003C!-- After: Semantic design tokens with automatic dark mode support -->\n\u003Cdiv class=\"bg-(--ui-background-muted) p-4 rounded-lg\">\n  \u003Ch2 class=\"text-(--ui-text-highlighted) text-xl mb-2\">User Profile\u003C/h2>\n  \u003Cp class=\"text-(--ui-text-muted)\">Account settings and preferences\u003C/p>\n  \u003CUButton color=\"primary\" size=\"sm\" class=\"mt-2\">Edit Profile\u003C/UButton>\n\u003C/div>\n",[1220,1366,1367,1372,1391,1418,1445,1497],{"__ignoreMap":1218},[1223,1368,1369],{"class":1225,"line":1226},[1223,1370,1371],{"class":1229},"\u003C!-- After: Semantic design tokens with automatic dark mode support -->\n",[1223,1373,1374,1376,1378,1380,1382,1384,1387,1389],{"class":1225,"line":1233},[1223,1375,1237],{"class":1236},[1223,1377,1241],{"class":1240},[1223,1379,1245],{"class":1244},[1223,1381,1248],{"class":1236},[1223,1383,1251],{"class":1236},[1223,1385,1386],{"class":1254},"bg-(--ui-background-muted) p-4 rounded-lg",[1223,1388,1251],{"class":1236},[1223,1390,1260],{"class":1236},[1223,1392,1393,1395,1397,1399,1401,1403,1406,1408,1410,1412,1414,1416],{"class":1225,"line":1263},[1223,1394,1266],{"class":1236},[1223,1396,1147],{"class":1240},[1223,1398,1245],{"class":1244},[1223,1400,1248],{"class":1236},[1223,1402,1251],{"class":1236},[1223,1404,1405],{"class":1254},"text-(--ui-text-highlighted) text-xl mb-2",[1223,1407,1251],{"class":1236},[1223,1409,1282],{"class":1236},[1223,1411,1286],{"class":1285},[1223,1413,1289],{"class":1236},[1223,1415,1147],{"class":1240},[1223,1417,1260],{"class":1236},[1223,1419,1420,1422,1424,1426,1428,1430,1433,1435,1437,1439,1441,1443],{"class":1225,"line":1296},[1223,1421,1266],{"class":1236},[1223,1423,1143],{"class":1240},[1223,1425,1245],{"class":1244},[1223,1427,1248],{"class":1236},[1223,1429,1251],{"class":1236},[1223,1431,1432],{"class":1254},"text-(--ui-text-muted)",[1223,1434,1251],{"class":1236},[1223,1436,1282],{"class":1236},[1223,1438,1316],{"class":1285},[1223,1440,1289],{"class":1236},[1223,1442,1143],{"class":1240},[1223,1444,1260],{"class":1236},[1223,1446,1447,1449,1452,1455,1457,1459,1462,1464,1467,1469,1471,1474,1476,1478,1480,1482,1485,1487,1489,1491,1493,1495],{"class":1225,"line":1325},[1223,1448,1266],{"class":1236},[1223,1450,1451],{"class":1240},"UButton",[1223,1453,1454],{"class":1244}," color",[1223,1456,1248],{"class":1236},[1223,1458,1251],{"class":1236},[1223,1460,1461],{"class":1254},"primary",[1223,1463,1251],{"class":1236},[1223,1465,1466],{"class":1244}," size",[1223,1468,1248],{"class":1236},[1223,1470,1251],{"class":1236},[1223,1472,1473],{"class":1254},"sm",[1223,1475,1251],{"class":1236},[1223,1477,1245],{"class":1244},[1223,1479,1248],{"class":1236},[1223,1481,1251],{"class":1236},[1223,1483,1484],{"class":1254},"mt-2",[1223,1486,1251],{"class":1236},[1223,1488,1282],{"class":1236},[1223,1490,1346],{"class":1285},[1223,1492,1289],{"class":1236},[1223,1494,1451],{"class":1240},[1223,1496,1260],{"class":1236},[1223,1498,1499,1501,1503],{"class":1225,"line":1355},[1223,1500,1289],{"class":1236},[1223,1502,1241],{"class":1240},[1223,1504,1260],{"class":1236},[1143,1506,1507],{},"Our new color system includes 7 semantic color aliases:",[1509,1510,1511,1527],"table",{},[1512,1513,1514],"thead",{},[1515,1516,1517,1521,1524],"tr",{},[1518,1519,1520],"th",{},"Color",[1518,1522,1523],{},"Default",[1518,1525,1526],{},"Description",[1528,1529,1530,1547,1563,1580,1596,1613,1630],"tbody",{},[1515,1531,1532,1539,1544],{},[1533,1534,1535],"td",{},[1220,1536,1461],{"className":1537},[1538],"text-(--ui-primary)",[1533,1540,1541],{},[1220,1542,1543],{},"blue",[1533,1545,1546],{},"Primary color to represent the brand.",[1515,1548,1549,1556,1560],{},[1533,1550,1551],{},[1220,1552,1555],{"className":1553},[1554],"text-(--ui-secondary)","secondary",[1533,1557,1558],{},[1220,1559,1543],{},[1533,1561,1562],{},"Secondary color to complement the primary color.",[1515,1564,1565,1572,1577],{},[1533,1566,1567],{},[1220,1568,1571],{"className":1569},[1570],"text-(--ui-success)","success",[1533,1573,1574],{},[1220,1575,1576],{},"green",[1533,1578,1579],{},"Used for success states.",[1515,1581,1582,1589,1593],{},[1533,1583,1584],{},[1220,1585,1588],{"className":1586},[1587],"text-(--ui-info)","info",[1533,1590,1591],{},[1220,1592,1543],{},[1533,1594,1595],{},"Used for informational states.",[1515,1597,1598,1605,1610],{},[1533,1599,1600],{},[1220,1601,1604],{"className":1602},[1603],"text-(--ui-warning)","warning",[1533,1606,1607],{},[1220,1608,1609],{},"yellow",[1533,1611,1612],{},"Used for warning states.",[1515,1614,1615,1622,1627],{},[1533,1616,1617],{},[1220,1618,1621],{"className":1619},[1620],"text-(--ui-error)","error",[1533,1623,1624],{},[1220,1625,1626],{},"red",[1533,1628,1629],{},"Used for form error validation states.",[1515,1631,1632,1637,1642],{},[1533,1633,1634],{},[1220,1635,1636],{},"neutral",[1533,1638,1639],{},[1220,1640,1641],{},"slate",[1533,1643,1644],{},"Neutral color for backgrounds, text, etc.",[1143,1646,1647],{},"This approach makes your codebase more maintainable and your UI more consistent—especially when working in teams. With these semantic tokens, light and dark mode transitions become effortless, as the system automatically handles the appropriate color values for each theme without requiring duplicate class definitions.",[1147,1649,1651],{"id":1650},"complete-vue-compatibility","💚 Complete Vue Compatibility",[1143,1653,1654],{},"We're really happy to expand the scope of Nuxt UI beyond the Nuxt framework. With v3, both Nuxt UI and Nuxt UI Pro now work seamlessly in any Vue project, this means you can:",[1143,1656,1657],{},"• Use the same components across all your Vue projects",[1143,1659,1660],{},"• Benefit from Nuxt UI's theming system in any Vue application",[1143,1662,1663],{},"• Enjoy auto-imports and TypeScript support outside of Nuxt",[1143,1665,1666],{},"• Leverage both basic components and advanced Pro components in any Vue project",[1213,1668,1673],{"className":1669,"code":1670,"filename":1671,"language":1672,"meta":1218,"style":1218},"language-ts shiki shiki-themes material-theme-lighter material-theme-lighter material-theme-palenight","import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\nimport ui from '@nuxt/ui/vite'\n\nexport default defineConfig({\n  plugins: [\n    vue(),\n    ui()\n  ]\n})\n","vite.config.ts","ts",[1220,1674,1675,1702,1719,1735,1741,1758,1769,1781,1790,1796],{"__ignoreMap":1218},[1223,1676,1677,1681,1684,1687,1690,1693,1696,1699],{"class":1225,"line":1226},[1223,1678,1680],{"class":1679},"sFVN2","import",[1223,1682,1683],{"class":1236}," {",[1223,1685,1686],{"class":1285}," defineConfig",[1223,1688,1689],{"class":1236}," }",[1223,1691,1692],{"class":1679}," from",[1223,1694,1695],{"class":1236}," '",[1223,1697,1698],{"class":1254},"vite",[1223,1700,1701],{"class":1236},"'\n",[1223,1703,1704,1706,1709,1712,1714,1717],{"class":1225,"line":1233},[1223,1705,1680],{"class":1679},[1223,1707,1708],{"class":1285}," vue ",[1223,1710,1711],{"class":1679},"from",[1223,1713,1695],{"class":1236},[1223,1715,1716],{"class":1254},"@vitejs/plugin-vue",[1223,1718,1701],{"class":1236},[1223,1720,1721,1723,1726,1728,1730,1733],{"class":1225,"line":1263},[1223,1722,1680],{"class":1679},[1223,1724,1725],{"class":1285}," ui ",[1223,1727,1711],{"class":1679},[1223,1729,1695],{"class":1236},[1223,1731,1732],{"class":1254},"@nuxt/ui/vite",[1223,1734,1701],{"class":1236},[1223,1736,1737],{"class":1225,"line":1296},[1223,1738,1740],{"emptyLinePlaceholder":1739},true,"\n",[1223,1742,1743,1746,1749,1752,1755],{"class":1225,"line":1325},[1223,1744,1745],{"class":1679},"export",[1223,1747,1748],{"class":1679}," default",[1223,1750,1686],{"class":1751},"szd4z",[1223,1753,1754],{"class":1285},"(",[1223,1756,1757],{"class":1236},"{\n",[1223,1759,1760,1763,1766],{"class":1225,"line":1355},[1223,1761,1762],{"class":1240},"  plugins",[1223,1764,1765],{"class":1236},":",[1223,1767,1768],{"class":1285}," [\n",[1223,1770,1772,1775,1778],{"class":1225,"line":1771},7,[1223,1773,1774],{"class":1751},"    vue",[1223,1776,1777],{"class":1285},"()",[1223,1779,1780],{"class":1236},",\n",[1223,1782,1784,1787],{"class":1225,"line":1783},8,[1223,1785,1786],{"class":1751},"    ui",[1223,1788,1789],{"class":1285},"()\n",[1223,1791,1793],{"class":1225,"line":1792},9,[1223,1794,1795],{"class":1285},"  ]\n",[1223,1797,1799,1802],{"class":1225,"line":1798},10,[1223,1800,1801],{"class":1236},"}",[1223,1803,1804],{"class":1285},")\n",[1147,1806,1808],{"id":1807},"components-for-every-need","📦 Components for Every Need",[1143,1810,1811],{},"With 54 core components, 50 Pro components, and 42 Prose components, Nuxt UI v3 provides solutions for virtually any UI challenge:",[1143,1813,1191,1814,1817],{},[1159,1815,1816],{},"Data Display",": Tables, charts, and visualizations that adapt to your data",[1143,1819,1191,1820,1823],{},[1159,1821,1822],{},"Navigation",": Menus, tabs, and breadcrumbs that guide users intuitively",[1143,1825,1191,1826,1829],{},[1159,1827,1828],{},"Feedback",": Toasts, alerts, and modals that communicate clearly",[1143,1831,1191,1832,1835],{},[1159,1833,1834],{},"Forms",": Inputs, selectors, and validation that simplify data collection",[1143,1837,1191,1838,1840],{},[1159,1839,780],{},": Grids, containers, and responsive systems that organize content beautifully",[1143,1842,1843],{},"Each component is designed to be both beautiful out of the box and deeply customizable when needed.",[1147,1845,1847],{"id":1846},"improved-typescript-integration","🔷 Improved TypeScript Integration",[1143,1849,1850],{},"We've completely revamped our TypeScript integration, with features that make you more productive:",[1852,1853,1854,1858,1861],"ul",{},[1855,1856,1857],"li",{},"Complete type safety with helpful autocompletion",[1855,1859,1860],{},"Generic-based components for flexible APIs",[1855,1862,1863],{},"Type-safe theming through a clear, consistent API",[1213,1865,1867],{"className":1669,"code":1866,"language":1672,"meta":1218,"style":1218},"export default defineAppConfig({\n  ui: {\n    button: {\n      // Your IDE will show all available options\n      slots: {\n        base: 'font-bold rounded-lg'\n      },\n      defaultVariants: {\n        size: 'md',\n        color: 'error'\n      }\n    }\n  }\n})\n",[1220,1868,1869,1882,1892,1901,1906,1915,1929,1934,1943,1960,1973,1979,1985,1991],{"__ignoreMap":1218},[1223,1870,1871,1873,1875,1878,1880],{"class":1225,"line":1226},[1223,1872,1745],{"class":1679},[1223,1874,1748],{"class":1679},[1223,1876,1877],{"class":1751}," defineAppConfig",[1223,1879,1754],{"class":1285},[1223,1881,1757],{"class":1236},[1223,1883,1884,1887,1889],{"class":1225,"line":1233},[1223,1885,1886],{"class":1240},"  ui",[1223,1888,1765],{"class":1236},[1223,1890,1891],{"class":1236}," {\n",[1223,1893,1894,1897,1899],{"class":1225,"line":1263},[1223,1895,1896],{"class":1240},"    button",[1223,1898,1765],{"class":1236},[1223,1900,1891],{"class":1236},[1223,1902,1903],{"class":1225,"line":1296},[1223,1904,1905],{"class":1229},"      // Your IDE will show all available options\n",[1223,1907,1908,1911,1913],{"class":1225,"line":1325},[1223,1909,1910],{"class":1240},"      slots",[1223,1912,1765],{"class":1236},[1223,1914,1891],{"class":1236},[1223,1916,1917,1920,1922,1924,1927],{"class":1225,"line":1355},[1223,1918,1919],{"class":1240},"        base",[1223,1921,1765],{"class":1236},[1223,1923,1695],{"class":1236},[1223,1925,1926],{"class":1254},"font-bold rounded-lg",[1223,1928,1701],{"class":1236},[1223,1930,1931],{"class":1225,"line":1771},[1223,1932,1933],{"class":1236},"      },\n",[1223,1935,1936,1939,1941],{"class":1225,"line":1783},[1223,1937,1938],{"class":1240},"      defaultVariants",[1223,1940,1765],{"class":1236},[1223,1942,1891],{"class":1236},[1223,1944,1945,1948,1950,1952,1955,1958],{"class":1225,"line":1792},[1223,1946,1947],{"class":1240},"        size",[1223,1949,1765],{"class":1236},[1223,1951,1695],{"class":1236},[1223,1953,1954],{"class":1254},"md",[1223,1956,1957],{"class":1236},"'",[1223,1959,1780],{"class":1236},[1223,1961,1962,1965,1967,1969,1971],{"class":1225,"line":1798},[1223,1963,1964],{"class":1240},"        color",[1223,1966,1765],{"class":1236},[1223,1968,1695],{"class":1236},[1223,1970,1621],{"class":1254},[1223,1972,1701],{"class":1236},[1223,1974,1976],{"class":1225,"line":1975},11,[1223,1977,1978],{"class":1236},"      }\n",[1223,1980,1982],{"class":1225,"line":1981},12,[1223,1983,1984],{"class":1236},"    }\n",[1223,1986,1988],{"class":1225,"line":1987},13,[1223,1989,1990],{"class":1236},"  }\n",[1223,1992,1994,1996],{"class":1225,"line":1993},14,[1223,1995,1801],{"class":1236},[1223,1997,1804],{"class":1285},[1147,1999,2001],{"id":2000},"️-upgrading-to-v3","⬆️ Upgrading to v3",[1143,2003,2004,2005,2012],{},"We've prepared a comprehensive ",[2006,2007,2011],"a",{"href":2008,"rel":2009},"https://ui.nuxt.com/getting-started/migration",[2010],"nofollow","migration"," guide to help you upgrade from v2 to v3. While there are breaking changes due to our complete overhaul, we've worked hard to make the transition as smooth as possible.",[1147,2014,2016],{"id":2015},"getting-started","🎯 Getting Started",[1143,2018,2019],{},"Whether you're starting a new project or upgrading an existing one, getting started with Nuxt UI v3 is easy:",[1213,2021,2025],{"className":2022,"code":2023,"language":2024,"meta":1218,"style":1218},"language-bash shiki shiki-themes material-theme-lighter material-theme-lighter material-theme-palenight","# Create a new Nuxt project with Nuxt UI\nnpx nuxi@latest init my-app -t ui\n","bash",[1220,2026,2027,2032],{"__ignoreMap":1218},[1223,2028,2029],{"class":1225,"line":1226},[1223,2030,2031],{"class":1229},"# Create a new Nuxt project with Nuxt UI\n",[1223,2033,2034,2038,2041,2044,2047,2050],{"class":1225,"line":1233},[1223,2035,2037],{"class":2036},"sT2Ow","npx",[1223,2039,2040],{"class":1254}," nuxi@latest",[1223,2042,2043],{"class":1254}," init",[1223,2045,2046],{"class":1254}," my-app",[1223,2048,2049],{"class":1254}," -t",[1223,2051,2052],{"class":1254}," ui\n",[2054,2055,2057,2073,2087,2102],"code-group",{"sync":2056},"pm",[1213,2058,2061],{"className":2022,"code":2059,"filename":2060,"language":2024,"meta":1218,"style":1218},"pnpm add @nuxt/ui@latest\n","pnpm",[1220,2062,2063],{"__ignoreMap":1218},[1223,2064,2065,2067,2070],{"class":1225,"line":1226},[1223,2066,2060],{"class":2036},[1223,2068,2069],{"class":1254}," add",[1223,2071,2072],{"class":1254}," @nuxt/ui@latest\n",[1213,2074,2077],{"className":2022,"code":2075,"filename":2076,"language":2024,"meta":1218,"style":1218},"yarn add @nuxt/ui@latest\n","yarn",[1220,2078,2079],{"__ignoreMap":1218},[1223,2080,2081,2083,2085],{"class":1225,"line":1226},[1223,2082,2076],{"class":2036},[1223,2084,2069],{"class":1254},[1223,2086,2072],{"class":1254},[1213,2088,2091],{"className":2022,"code":2089,"filename":2090,"language":2024,"meta":1218,"style":1218},"npm install @nuxt/ui@latest\n","npm",[1220,2092,2093],{"__ignoreMap":1218},[1223,2094,2095,2097,2100],{"class":1225,"line":1226},[1223,2096,2090],{"class":2036},[1223,2098,2099],{"class":1254}," install",[1223,2101,2072],{"class":1254},[1213,2103,2106],{"className":2022,"code":2104,"filename":2105,"language":2024,"meta":1218,"style":1218},"bun add @nuxt/ui@latest\n","bun",[1220,2107,2108],{"__ignoreMap":1218},[1223,2109,2110,2112,2114],{"class":1225,"line":1226},[1223,2111,2105],{"class":2036},[1223,2113,2069],{"class":1254},[1223,2115,2072],{"class":1254},[1604,2117,2118],{},[1143,2119,2120,2121,2123,2124,2131,2132,2135,2136,2139],{},"If you're using ",[1159,2122,2060],{},", ensure that you either set ",[2006,2125,2128],{"href":2126,"rel":2127},"https://pnpm.io/npmrc#shamefully-hoist",[2010],[1220,2129,2130],{},"shamefully-hoist=true"," in your ",[1220,2133,2134],{},".npmrc"," file or install ",[1220,2137,2138],{},"tailwindcss"," in your project's root directory.",[1143,2141,2142,2143,2148],{},"Visit our ",[2006,2144,2147],{"href":2145,"rel":2146},"https://ui.nuxt.com/getting-started",[2010],"documentation"," to explore all the components and features available in Nuxt UI v3.",[1147,2150,2152],{"id":2151},"thank-you","🙏 Thank You",[1143,2154,2155],{},"This release represents thousands of hours of work from our team and the community. We'd like to thank everyone who contributed to making Nuxt UI v3 a reality.",[1143,2157,2158],{},"We're excited to see what you'll build with Nuxt UI v3!",[2160,2161,2162],"style",{},"html pre.shiki code .svXlt, html code.shiki .svXlt{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}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 .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}",{"title":1218,"searchDepth":1233,"depth":1233,"links":2164},[2165,2169,2170,2171,2172,2173,2174,2175],{"id":1149,"depth":1233,"text":1150,"children":2166},[2167,2168],{"id":1157,"depth":1263,"text":1161},{"id":1182,"depth":1263,"text":1185},{"id":1210,"depth":1233,"text":1211},{"id":1650,"depth":1233,"text":1651},{"id":1807,"depth":1233,"text":1808},{"id":1846,"depth":1233,"text":1847},{"id":2000,"depth":1233,"text":2001},{"id":2015,"depth":1233,"text":2016},{"id":2151,"depth":1233,"text":2152},"Release","2025-03-12T10:00:00.000Z","Nuxt UI v3 is out! After 1500+ commits, this major redesign brings improved accessibility, Tailwind CSS v4 support, and full Vue compatibility","/assets/blog/nuxt-ui-v3.png",{},"/blog/nuxt-ui-v3",{"title":1122,"description":2178},"blog/32.nuxt-ui-v3","jEWTVTstTR",{"id":2186,"title":2187,"authors":2188,"body":2194,"category":2176,"date":3650,"description":3651,"draft":108,"extension":1954,"image":3652,"meta":3653,"navigation":108,"path":3654,"seo":3655,"stem":3656,"tags":6,"__hash__":3657},"blog/blog/31.v3-16.md","Nuxt 3.16",[2189],{"name":2190,"avatar":2191,"to":2193},"Daniel Roe",{"src":2192},"https://github.com/danielroe.png","https://bsky.app/profile/danielroe.dev",{"type":1140,"value":2195,"toc":3632},[2196,2199,2203,2216,2222,2225,2240,2252,2267,2282,2286,2297,2305,2408,2411,2430,2433,2445,2449,2458,2461,2464,2472,2476,2479,2542,2545,2560,2575,2579,2593,2749,2756,2787,2794,2798,2807,2871,2875,2888,3033,3040,3044,3053,3099,3239,3243,3263,3266,3319,3326,3330,3338,3354,3363,3366,3370,3381,3519,3523,3526,3534,3542,3545,3577,3581,3584,3603,3606,3610,3623,3626,3629],[1143,2197,2198],{},"There's a lot in this one!",[1147,2200,2202],{"id":2201},"️-a-new-new-nuxt","⚡️ A New New Nuxt",[1143,2204,2205,2206,2209,2210,2215],{},"Say hello to ",[1220,2207,2208],{},"create-nuxt",", a new tool for starting Nuxt projects (big thanks to ",[2006,2211,2214],{"href":2212,"rel":2213},"https://github.com/devgar",[2010],"@devgar"," for donating the package name)!",[1143,2217,2218,2219,2221],{},"It's a streamlined version of ",[1220,2220,698],{}," - just a sixth of the size and bundled as a single file with all dependencies inlined, to get you going as fast as possible.",[1143,2223,2224],{},"Starting a new project is as simple as:",[1213,2226,2228],{"className":2022,"code":2227,"language":2024,"meta":1218,"style":1218},"npm create nuxt\n",[1220,2229,2230],{"__ignoreMap":1218},[1223,2231,2232,2234,2237],{"class":1225,"line":1226},[1223,2233,2090],{"class":2036},[1223,2235,2236],{"class":1254}," create",[1223,2238,2239],{"class":1254}," nuxt\n",[1143,2241,2242],{},[2243,2244],"img",{"alt":2245,"className":2246,"src":2251},"screenshot of create nuxt app",[2247,2248,2249,2250],"border","border-gray-200","dark:border-gray-700","rounded-lg","/assets/blog/create-nuxt-ascii.jpeg",[1143,2253,2254,2255,2260,2261,2266],{},"Special thanks to ",[2006,2256,2259],{"href":2257,"rel":2258},"https://github.com/cmang",[2010],"@cmang"," for the ",[2006,2262,2265],{"href":2263,"rel":2264},"https://bsky.app/profile/durdraw.org/post/3liadod3gv22a",[2010],"beautiful ASCII-art",". ❤️",[1143,2268,2269,2270,2275,2276,2281],{},"Want to learn more about where we're headed with the Nuxt CLI? Check out our roadmap ",[2006,2271,2274],{"href":2272,"rel":2273},"https://github.com/nuxt/cli/issues/648",[2010],"here",", including our plans for an ",[2006,2277,2280],{"href":2278,"rel":2279},"https://github.com/nuxt/cli/issues/754",[2010],"interactive modules selector",".",[1147,2283,2285],{"id":2284},"unhead-v2","🚀 Unhead v2",[1143,2287,2288,2289,2292,2293,2296],{},"We've upgraded to ",[1220,2290,2291],{},"unhead"," v2, the engine behind Nuxt's ",[1220,2294,2295],{},"\u003Chead>"," management. This major version removes deprecations and improves how context works:",[1852,2298,2299,2302],{},[1855,2300,2301],{},"For Nuxt 3 users, we're shipping a legacy compatibility build so nothing breaks",[1855,2303,2304],{},"The context implementation is now more direct via Nuxt itself",[1213,2306,2308],{"className":1669,"code":2307,"language":1672,"meta":1218,"style":1218},"// Nuxt now re-exports composables while properly resolving the context\nexport function useHead(input, options = {}) {\n  const unhead = injectHead(options.nuxt)\n  return head(input, { head: unhead, ...options })\n}\n",[1220,2309,2310,2315,2345,2370,2403],{"__ignoreMap":1218},[1223,2311,2312],{"class":1225,"line":1226},[1223,2313,2314],{"class":1229},"// Nuxt now re-exports composables while properly resolving the context\n",[1223,2316,2317,2319,2322,2325,2327,2331,2334,2337,2340,2343],{"class":1225,"line":1233},[1223,2318,1745],{"class":1679},[1223,2320,2321],{"class":1244}," function",[1223,2323,2324],{"class":1751}," useHead",[1223,2326,1754],{"class":1236},[1223,2328,2330],{"class":2329},"ssYd4","input",[1223,2332,2333],{"class":1236},",",[1223,2335,2336],{"class":2329}," options",[1223,2338,2339],{"class":1236}," =",[1223,2341,2342],{"class":1236}," {})",[1223,2344,1891],{"class":1236},[1223,2346,2347,2350,2353,2355,2358,2360,2363,2365,2368],{"class":1225,"line":1263},[1223,2348,2349],{"class":1244},"  const",[1223,2351,2352],{"class":1285}," unhead",[1223,2354,2339],{"class":1236},[1223,2356,2357],{"class":1751}," injectHead",[1223,2359,1754],{"class":1240},[1223,2361,2362],{"class":1285},"options",[1223,2364,2281],{"class":1236},[1223,2366,2367],{"class":1285},"nuxt",[1223,2369,1804],{"class":1240},[1223,2371,2372,2375,2378,2380,2382,2384,2386,2388,2390,2392,2394,2397,2399,2401],{"class":1225,"line":1296},[1223,2373,2374],{"class":1679},"  return",[1223,2376,2377],{"class":1751}," head",[1223,2379,1754],{"class":1240},[1223,2381,2330],{"class":1285},[1223,2383,2333],{"class":1236},[1223,2385,1683],{"class":1236},[1223,2387,2377],{"class":1240},[1223,2389,1765],{"class":1236},[1223,2391,2352],{"class":1285},[1223,2393,2333],{"class":1236},[1223,2395,2396],{"class":1236}," ...",[1223,2398,2362],{"class":1285},[1223,2400,1689],{"class":1236},[1223,2402,1804],{"class":1240},[1223,2404,2405],{"class":1225,"line":1325},[1223,2406,2407],{"class":1236},"}\n",[1143,2409,2410],{},"If you're using Unhead directly in your app, keep in mind:",[2412,2413,2414,2424],"ol",{},[1855,2415,2416,2417,2420,2421],{},"Import from Nuxt's auto-imports or ",[1220,2418,2419],{},"#app/composables/head"," instead of ",[1220,2422,2423],{},"@unhead/vue",[1855,2425,2426,2427,2429],{},"Importing directly from ",[1220,2428,2423],{}," might lose async context",[1143,2431,2432],{},"Don't worry though - we've maintained backward compatibility in Nuxt 3, so most users won't need to change anything!",[1143,2434,2435,2436,2439,2440,2444],{},"If you've opted into ",[1220,2437,2438],{},"compatibilityVersion: 4",", check out ",[2006,2441,2443],{"href":2442},"/docs/getting-started/upgrade#unhead-v2","our upgrade guide"," for additional changes.",[1147,2446,2448],{"id":2447},"devtools-v2-upgrade","🔧 Devtools v2 Upgrade",[1143,2450,2451,2452,2457],{},"Nuxt Devtools has leveled up to v2 (",[2006,2453,2456],{"href":2454,"rel":2455},"https://github.com/nuxt/nuxt/pull/30889",[2010],"#30889",")!",[1143,2459,2460],{},"You'll love the new features like custom editor selection, Discovery.js for inspecting resolved configs (perfect for debugging), the return of the schema generator, and slimmer dependencies.",[1143,2462,2463],{},"One of our favorite improvements is the ability to track how modules modify your Nuxt configuration - giving you X-ray vision into what's happening under the hood.",[1143,2465,2466,2467,2281],{},"👉 Discover all the details in the ",[2006,2468,2471],{"href":2469,"rel":2470},"https://github.com/nuxt/devtools/releases",[2010],"Nuxt DevTools release notes",[1147,2473,2475],{"id":2474},"️-performance-improvements","⚡️ Performance Improvements",[1143,2477,2478],{},"We're continuing to make Nuxt faster, and there are a number of improvements in v3.16:",[2412,2480,2481,2498,2507,2516,2529],{},[1855,2482,2483,2484,2491,2492,2497],{},"Using ",[2006,2485,2488],{"href":2486,"rel":2487},"https://github.com/unjs/exsolve",[2010],[1220,2489,2490],{},"exsolve"," for module resolution (",[2006,2493,2496],{"href":2494,"rel":2495},"https://github.com/nuxt/nuxt/pull/31124",[2010],"#31124",") along with the rest of the unjs ecosystem (nitro, c12, pkg-types, and more) - which dramatically speeds up module resolution",[1855,2499,2500,2501,2506],{},"Smarter module resolution paths (",[2006,2502,2505],{"href":2503,"rel":2504},"https://github.com/nuxt/nuxt/pull/31037",[2010],"#31037",") - prioritizes direct imports for better efficiency",[1855,2508,2509,2510,2515],{},"Eliminated duplicated Nitro alias resolution (",[2006,2511,2514],{"href":2512,"rel":2513},"https://github.com/nuxt/nuxt/pull/31088",[2010],"#31088",") - leaner file handling",[1855,2517,2518,2519,2522,2523,2528],{},"Streamlined ",[1220,2520,2521],{},"loadNuxt"," by skipping unnecessary resolution steps (",[2006,2524,2527],{"href":2525,"rel":2526},"https://github.com/nuxt/nuxt/pull/31176",[2010],"#31176",") - faster startups",[1855,2530,2531,2532,2535,2536,2541],{},"Adopt ",[1220,2533,2534],{},"oxc-parser"," for parsing in Nuxt plugins (",[2006,2537,2540],{"href":2538,"rel":2539},"https://github.com/nuxt/nuxt/pull/30066",[2010],"#30066",")",[1143,2543,2544],{},"All these speed boosts happen automatically - no configuration needed!",[1143,2546,2547,2548,2553,2554,2559],{},"Shout out to ",[2006,2549,2552],{"href":2550,"rel":2551},"https://codspeed.io/",[2010],"CodSpeed"," with ",[2006,2555,2558],{"href":2556,"rel":2557},"https://vitest.dev/guide/features.html#benchmarking",[2010],"Vitest benchmarking"," to measure these improvements in CI - it has been really helpful.",[1143,2561,2562,2563,2568,2569,2574],{},"To add some anecdotal evidence, my personal site at ",[2006,2564,2567],{"href":2565,"rel":2566},"https://github.com/danielroe/roe.dev",[2010],"roe.dev"," loads 32% faster with v3.16, and ",[2006,2570,2573],{"href":2571,"rel":2572},"https://github.com/nuxt/nuxt.com",[2010],"nuxt.com"," is 28% faster. I hope you see similar results! ⚡️",[1147,2576,2578],{"id":2577},"️-delayed-hydration-support","🕰️ Delayed Hydration Support",[1143,2580,2581,2582,2587,2588,2281],{},"We're very pleased to bring you native delayed/lazy hydration support (",[2006,2583,2586],{"href":2584,"rel":2585},"https://github.com/nuxt/nuxt/pull/26468",[2010],"#26468",")! This lets you control exactly when components hydrate, which can improve initial load performance and time-to-interactive. We're leveraging Vue's built-in hydration strategies - ",[2006,2589,2592],{"href":2590,"rel":2591},"https://vuejs.org/guide/components/async.html#lazy-hydration",[2010],"check them out in the Vue docs",[1213,2594,2598],{"className":2595,"code":2596,"language":2597,"meta":1218,"style":1218},"language-vue shiki shiki-themes material-theme-lighter material-theme-lighter material-theme-palenight","\u003Ctemplate>\n  \u003C!-- Hydrate when component becomes visible in viewport -->\n  \u003CLazyExpensiveComponent hydrate-on-visible />\n  \n  \u003C!-- Hydrate when browser is idle -->\n  \u003CLazyHeavyComponent hydrate-on-idle />\n  \n  \u003C!-- Hydrate on interaction (mouseover in this case) -->\n  \u003CLazyDropdown hydrate-on-interaction=\"mouseover\" />\n  \n  \u003C!-- Hydrate when media query matches -->\n  \u003CLazyMobileMenu hydrate-on-media-query=\"(max-width: 768px)\" />\n  \n  \u003C!-- Hydrate after a specific delay in milliseconds -->\n  \u003CLazyFooter :hydrate-after=\"2000\" />\n\u003C/template>\n","vue",[1220,2599,2600,2609,2614,2627,2632,2637,2649,2653,2658,2679,2683,2688,2709,2713,2718,2740],{"__ignoreMap":1218},[1223,2601,2602,2604,2607],{"class":1225,"line":1226},[1223,2603,1237],{"class":1236},[1223,2605,2606],{"class":1240},"template",[1223,2608,1260],{"class":1236},[1223,2610,2611],{"class":1225,"line":1233},[1223,2612,2613],{"class":1229},"  \u003C!-- Hydrate when component becomes visible in viewport -->\n",[1223,2615,2616,2618,2621,2624],{"class":1225,"line":1263},[1223,2617,1266],{"class":1236},[1223,2619,2620],{"class":1240},"LazyExpensiveComponent",[1223,2622,2623],{"class":1244}," hydrate-on-visible",[1223,2625,2626],{"class":1236}," />\n",[1223,2628,2629],{"class":1225,"line":1296},[1223,2630,2631],{"class":1285},"  \n",[1223,2633,2634],{"class":1225,"line":1325},[1223,2635,2636],{"class":1229},"  \u003C!-- Hydrate when browser is idle -->\n",[1223,2638,2639,2641,2644,2647],{"class":1225,"line":1355},[1223,2640,1266],{"class":1236},[1223,2642,2643],{"class":1240},"LazyHeavyComponent",[1223,2645,2646],{"class":1244}," hydrate-on-idle",[1223,2648,2626],{"class":1236},[1223,2650,2651],{"class":1225,"line":1771},[1223,2652,2631],{"class":1285},[1223,2654,2655],{"class":1225,"line":1783},[1223,2656,2657],{"class":1229},"  \u003C!-- Hydrate on interaction (mouseover in this case) -->\n",[1223,2659,2660,2662,2665,2668,2670,2672,2675,2677],{"class":1225,"line":1792},[1223,2661,1266],{"class":1236},[1223,2663,2664],{"class":1240},"LazyDropdown",[1223,2666,2667],{"class":1244}," hydrate-on-interaction",[1223,2669,1248],{"class":1236},[1223,2671,1251],{"class":1236},[1223,2673,2674],{"class":1254},"mouseover",[1223,2676,1251],{"class":1236},[1223,2678,2626],{"class":1236},[1223,2680,2681],{"class":1225,"line":1798},[1223,2682,2631],{"class":1285},[1223,2684,2685],{"class":1225,"line":1975},[1223,2686,2687],{"class":1229},"  \u003C!-- Hydrate when media query matches -->\n",[1223,2689,2690,2692,2695,2698,2700,2702,2705,2707],{"class":1225,"line":1981},[1223,2691,1266],{"class":1236},[1223,2693,2694],{"class":1240},"LazyMobileMenu",[1223,2696,2697],{"class":1244}," hydrate-on-media-query",[1223,2699,1248],{"class":1236},[1223,2701,1251],{"class":1236},[1223,2703,2704],{"class":1254},"(max-width: 768px)",[1223,2706,1251],{"class":1236},[1223,2708,2626],{"class":1236},[1223,2710,2711],{"class":1225,"line":1987},[1223,2712,2631],{"class":1285},[1223,2714,2715],{"class":1225,"line":1993},[1223,2716,2717],{"class":1229},"  \u003C!-- Hydrate after a specific delay in milliseconds -->\n",[1223,2719,2721,2723,2726,2729,2731,2733,2736,2738],{"class":1225,"line":2720},15,[1223,2722,1266],{"class":1236},[1223,2724,2725],{"class":1240},"LazyFooter",[1223,2727,2728],{"class":1244}," :hydrate-after",[1223,2730,1248],{"class":1236},[1223,2732,1251],{"class":1236},[1223,2734,2735],{"class":1254},"2000",[1223,2737,1251],{"class":1236},[1223,2739,2626],{"class":1236},[1223,2741,2743,2745,2747],{"class":1225,"line":2742},16,[1223,2744,1289],{"class":1236},[1223,2746,2606],{"class":1240},[1223,2748,1260],{"class":1236},[1143,2750,2751,2752,2755],{},"You can also listen for when hydration happens with the ",[1220,2753,2754],{},"@hydrated"," event:",[1213,2757,2759],{"className":2595,"code":2758,"language":2597,"meta":1218,"style":1218},"\u003CLazyComponent hydrate-on-visible @hydrated=\"onComponentHydrated\" />\n",[1220,2760,2761],{"__ignoreMap":1218},[1223,2762,2763,2765,2768,2770,2773,2776,2778,2780,2783,2785],{"class":1225,"line":1226},[1223,2764,1237],{"class":1236},[1223,2766,2767],{"class":1240},"LazyComponent",[1223,2769,2623],{"class":1244},[1223,2771,2772],{"class":1236}," @",[1223,2774,2775],{"class":1244},"hydrated",[1223,2777,1248],{"class":1236},[1223,2779,1251],{"class":1236},[1223,2781,2782],{"class":1285},"onComponentHydrated",[1223,2784,1251],{"class":1236},[1223,2786,2626],{"class":1236},[1143,2788,2789,2790,2281],{},"Learn more about lazy hydration in ",[2006,2791,2793],{"href":2792},"/docs/guide/directory-structure/components#delayed-or-lazy-hydration","our components documentation",[1147,2795,2797],{"id":2796},"advanced-pages-configuration","🧩 Advanced Pages Configuration",[1143,2799,2800,2801,2806],{},"You can now fine-tune which files Nuxt scans for pages (",[2006,2802,2805],{"href":2803,"rel":2804},"https://github.com/nuxt/nuxt/pull/31090",[2010],"#31090","), giving you more control over your project structure:",[1213,2808,2810],{"className":1669,"code":2809,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  pages: {\n    // Filter specific files or directories\n    pattern: ['**/*.vue'],\n  }\n})\n",[1220,2811,2812,2825,2834,2839,2861,2865],{"__ignoreMap":1218},[1223,2813,2814,2816,2818,2821,2823],{"class":1225,"line":1226},[1223,2815,1745],{"class":1679},[1223,2817,1748],{"class":1679},[1223,2819,2820],{"class":1751}," defineNuxtConfig",[1223,2822,1754],{"class":1285},[1223,2824,1757],{"class":1236},[1223,2826,2827,2830,2832],{"class":1225,"line":1233},[1223,2828,2829],{"class":1240},"  pages",[1223,2831,1765],{"class":1236},[1223,2833,1891],{"class":1236},[1223,2835,2836],{"class":1225,"line":1263},[1223,2837,2838],{"class":1229},"    // Filter specific files or directories\n",[1223,2840,2841,2844,2846,2849,2851,2854,2856,2859],{"class":1225,"line":1296},[1223,2842,2843],{"class":1240},"    pattern",[1223,2845,1765],{"class":1236},[1223,2847,2848],{"class":1285}," [",[1223,2850,1957],{"class":1236},[1223,2852,2853],{"class":1254},"**/*.vue",[1223,2855,1957],{"class":1236},[1223,2857,2858],{"class":1285},"]",[1223,2860,1780],{"class":1236},[1223,2862,2863],{"class":1225,"line":1325},[1223,2864,1990],{"class":1236},[1223,2866,2867,2869],{"class":1225,"line":1355},[1223,2868,1801],{"class":1236},[1223,2870,1804],{"class":1285},[1147,2872,2874],{"id":2873},"enhanced-debugging","🔍 Enhanced Debugging",[1143,2876,2877,2878,2881,2882,2887],{},"We've made debugging with the ",[1220,2879,2880],{},"debug"," option more flexible! Now you can enable just the debug logs you need (",[2006,2883,2886],{"href":2884,"rel":2885},"https://github.com/nuxt/nuxt/pull/30578",[2010],"#30578","):",[1213,2889,2891],{"className":1669,"code":2890,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  debug: {\n    // Enable specific debugging features\n    templates: true,\n    modules: true,\n    watchers: true,\n    hooks: {\n      client: true,\n      server: true,\n    },\n    nitro: true,\n    router: true,\n    hydration: true,\n  }\n})\n",[1220,2892,2893,2905,2914,2919,2932,2943,2954,2963,2974,2985,2990,3001,3012,3023,3027],{"__ignoreMap":1218},[1223,2894,2895,2897,2899,2901,2903],{"class":1225,"line":1226},[1223,2896,1745],{"class":1679},[1223,2898,1748],{"class":1679},[1223,2900,2820],{"class":1751},[1223,2902,1754],{"class":1285},[1223,2904,1757],{"class":1236},[1223,2906,2907,2910,2912],{"class":1225,"line":1233},[1223,2908,2909],{"class":1240},"  debug",[1223,2911,1765],{"class":1236},[1223,2913,1891],{"class":1236},[1223,2915,2916],{"class":1225,"line":1263},[1223,2917,2918],{"class":1229},"    // Enable specific debugging features\n",[1223,2920,2921,2924,2926,2930],{"class":1225,"line":1296},[1223,2922,2923],{"class":1240},"    templates",[1223,2925,1765],{"class":1236},[1223,2927,2929],{"class":2928},"sagxc"," true",[1223,2931,1780],{"class":1236},[1223,2933,2934,2937,2939,2941],{"class":1225,"line":1325},[1223,2935,2936],{"class":1240},"    modules",[1223,2938,1765],{"class":1236},[1223,2940,2929],{"class":2928},[1223,2942,1780],{"class":1236},[1223,2944,2945,2948,2950,2952],{"class":1225,"line":1355},[1223,2946,2947],{"class":1240},"    watchers",[1223,2949,1765],{"class":1236},[1223,2951,2929],{"class":2928},[1223,2953,1780],{"class":1236},[1223,2955,2956,2959,2961],{"class":1225,"line":1771},[1223,2957,2958],{"class":1240},"    hooks",[1223,2960,1765],{"class":1236},[1223,2962,1891],{"class":1236},[1223,2964,2965,2968,2970,2972],{"class":1225,"line":1783},[1223,2966,2967],{"class":1240},"      client",[1223,2969,1765],{"class":1236},[1223,2971,2929],{"class":2928},[1223,2973,1780],{"class":1236},[1223,2975,2976,2979,2981,2983],{"class":1225,"line":1792},[1223,2977,2978],{"class":1240},"      server",[1223,2980,1765],{"class":1236},[1223,2982,2929],{"class":2928},[1223,2984,1780],{"class":1236},[1223,2986,2987],{"class":1225,"line":1798},[1223,2988,2989],{"class":1236},"    },\n",[1223,2991,2992,2995,2997,2999],{"class":1225,"line":1975},[1223,2993,2994],{"class":1240},"    nitro",[1223,2996,1765],{"class":1236},[1223,2998,2929],{"class":2928},[1223,3000,1780],{"class":1236},[1223,3002,3003,3006,3008,3010],{"class":1225,"line":1981},[1223,3004,3005],{"class":1240},"    router",[1223,3007,1765],{"class":1236},[1223,3009,2929],{"class":2928},[1223,3011,1780],{"class":1236},[1223,3013,3014,3017,3019,3021],{"class":1225,"line":1987},[1223,3015,3016],{"class":1240},"    hydration",[1223,3018,1765],{"class":1236},[1223,3020,2929],{"class":2928},[1223,3022,1780],{"class":1236},[1223,3024,3025],{"class":1225,"line":1993},[1223,3026,1990],{"class":1236},[1223,3028,3029,3031],{"class":1225,"line":2720},[1223,3030,1801],{"class":1236},[1223,3032,1804],{"class":1285},[1143,3034,3035,3036,3039],{},"Or keep it simple with ",[1220,3037,3038],{},"debug: true"," to enable all these debugging features.",[1147,3041,3043],{"id":3042},"decorators-support","🎨 Decorators Support",[1143,3045,3046,3047,3052],{},"For the decorator fans out there (whoever you are!), we've added experimental support (",[2006,3048,3051],{"href":3049,"rel":3050},"https://github.com/nuxt/nuxt/pull/27672",[2010],"#27672","). As with all experimental features, feedback is much appreciated.",[1213,3054,3056],{"className":1669,"code":3055,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  experimental: {\n    decorators: true\n  }\n})\n",[1220,3057,3058,3070,3079,3089,3093],{"__ignoreMap":1218},[1223,3059,3060,3062,3064,3066,3068],{"class":1225,"line":1226},[1223,3061,1745],{"class":1679},[1223,3063,1748],{"class":1679},[1223,3065,2820],{"class":1751},[1223,3067,1754],{"class":1285},[1223,3069,1757],{"class":1236},[1223,3071,3072,3075,3077],{"class":1225,"line":1233},[1223,3073,3074],{"class":1240},"  experimental",[1223,3076,1765],{"class":1236},[1223,3078,1891],{"class":1236},[1223,3080,3081,3084,3086],{"class":1225,"line":1263},[1223,3082,3083],{"class":1240},"    decorators",[1223,3085,1765],{"class":1236},[1223,3087,3088],{"class":2928}," true\n",[1223,3090,3091],{"class":1225,"line":1296},[1223,3092,1990],{"class":1236},[1223,3094,3095,3097],{"class":1225,"line":1325},[1223,3096,1801],{"class":1236},[1223,3098,1804],{"class":1285},[1213,3100,3102],{"className":1669,"code":3101,"language":1672,"meta":1218,"style":1218},"function something (_method: () => unknown) {\n  return () => 'decorated'\n}\n\nclass SomeClass {\n  @something\n  public someMethod () {\n    return 'initial'\n  }\n}\n\nconst value = new SomeClass().someMethod()\n// returns 'decorated'\n",[1220,3103,3104,3133,3148,3152,3156,3166,3174,3186,3198,3202,3206,3210,3234],{"__ignoreMap":1218},[1223,3105,3106,3109,3112,3115,3118,3120,3123,3126,3129,3131],{"class":1225,"line":1226},[1223,3107,3108],{"class":1244},"function",[1223,3110,3111],{"class":1751}," something",[1223,3113,3114],{"class":1236}," (",[1223,3116,3117],{"class":1751},"_method",[1223,3119,1765],{"class":1236},[1223,3121,3122],{"class":1236}," ()",[1223,3124,3125],{"class":1244}," =>",[1223,3127,3128],{"class":2036}," unknown",[1223,3130,2541],{"class":1236},[1223,3132,1891],{"class":1236},[1223,3134,3135,3137,3139,3141,3143,3146],{"class":1225,"line":1233},[1223,3136,2374],{"class":1679},[1223,3138,3122],{"class":1236},[1223,3140,3125],{"class":1244},[1223,3142,1695],{"class":1236},[1223,3144,3145],{"class":1254},"decorated",[1223,3147,1701],{"class":1236},[1223,3149,3150],{"class":1225,"line":1263},[1223,3151,2407],{"class":1236},[1223,3153,3154],{"class":1225,"line":1296},[1223,3155,1740],{"emptyLinePlaceholder":1739},[1223,3157,3158,3161,3164],{"class":1225,"line":1325},[1223,3159,3160],{"class":1244},"class",[1223,3162,3163],{"class":2036}," SomeClass",[1223,3165,1891],{"class":1236},[1223,3167,3168,3171],{"class":1225,"line":1355},[1223,3169,3170],{"class":1236},"  @",[1223,3172,3173],{"class":1285},"something\n",[1223,3175,3176,3179,3182,3184],{"class":1225,"line":1771},[1223,3177,3178],{"class":1244},"  public",[1223,3180,3181],{"class":1240}," someMethod",[1223,3183,3122],{"class":1236},[1223,3185,1891],{"class":1236},[1223,3187,3188,3191,3193,3196],{"class":1225,"line":1783},[1223,3189,3190],{"class":1679},"    return",[1223,3192,1695],{"class":1236},[1223,3194,3195],{"class":1254},"initial",[1223,3197,1701],{"class":1236},[1223,3199,3200],{"class":1225,"line":1792},[1223,3201,1990],{"class":1236},[1223,3203,3204],{"class":1225,"line":1798},[1223,3205,2407],{"class":1236},[1223,3207,3208],{"class":1225,"line":1975},[1223,3209,1740],{"emptyLinePlaceholder":1739},[1223,3211,3212,3215,3218,3220,3223,3225,3227,3229,3232],{"class":1225,"line":1981},[1223,3213,3214],{"class":1244},"const",[1223,3216,3217],{"class":1285}," value ",[1223,3219,1248],{"class":1236},[1223,3221,3222],{"class":1236}," new",[1223,3224,3163],{"class":1751},[1223,3226,1777],{"class":1285},[1223,3228,2281],{"class":1236},[1223,3230,3231],{"class":1751},"someMethod",[1223,3233,1789],{"class":1285},[1223,3235,3236],{"class":1225,"line":1987},[1223,3237,3238],{"class":1229},"// returns 'decorated'\n",[1147,3240,3242],{"id":3241},"named-layer-aliases","📛 Named Layer Aliases",[1143,3244,3245,3246,3249,3250,3253,3254,3114,3257,3262],{},"It's been much requested, and it's here! Auto-scanned local layers (from your ",[1220,3247,3248],{},"~~/layers"," directory) now automatically create aliases. You can access your ",[1220,3251,3252],{},"~~/layers/test"," layer via ",[1220,3255,3256],{},"#layers/test",[2006,3258,3261],{"href":3259,"rel":3260},"https://github.com/nuxt/nuxt/pull/30948",[2010],"#30948",") - no configuration needed.",[1143,3264,3265],{},"If you want named aliases for other layers, you can add a name to your layer configuration:",[1213,3267,3269],{"className":1669,"code":3268,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  $meta: {\n    name: 'example-layer',\n  },\n})\n",[1220,3270,3271,3283,3292,3308,3313],{"__ignoreMap":1218},[1223,3272,3273,3275,3277,3279,3281],{"class":1225,"line":1226},[1223,3274,1745],{"class":1679},[1223,3276,1748],{"class":1679},[1223,3278,2820],{"class":1751},[1223,3280,1754],{"class":1285},[1223,3282,1757],{"class":1236},[1223,3284,3285,3288,3290],{"class":1225,"line":1233},[1223,3286,3287],{"class":1240},"  $meta",[1223,3289,1765],{"class":1236},[1223,3291,1891],{"class":1236},[1223,3293,3294,3297,3299,3301,3304,3306],{"class":1225,"line":1263},[1223,3295,3296],{"class":1240},"    name",[1223,3298,1765],{"class":1236},[1223,3300,1695],{"class":1236},[1223,3302,3303],{"class":1254},"example-layer",[1223,3305,1957],{"class":1236},[1223,3307,1780],{"class":1236},[1223,3309,3310],{"class":1225,"line":1296},[1223,3311,3312],{"class":1236},"  },\n",[1223,3314,3315,3317],{"class":1225,"line":1325},[1223,3316,1801],{"class":1236},[1223,3318,1804],{"class":1285},[1143,3320,3321,3322,3325],{},"This creates the alias ",[1220,3323,3324],{},"#layers/example-layer"," pointing to your layer - making imports cleaner and more intuitive.",[1147,3327,3329],{"id":3328},"error-handling-improvements","🧪 Error Handling Improvements",[1143,3331,3332,3333,2887],{},"We've greatly improved error messages and source tracking (",[2006,3334,3337],{"href":3335,"rel":3336},"https://github.com/nuxt/nuxt/pull/31144",[2010],"#31144",[2412,3339,3340,3346],{},[1855,3341,3342,3343,3345],{},"Better warnings for undefined ",[1220,3344,432],{}," calls with precise file location information",[1855,3347,3348,3349,2541],{},"Error pages now appear correctly on island page errors (",[2006,3350,3353],{"href":3351,"rel":3352},"https://github.com/nuxt/nuxt/pull/31081",[2010],"#31081",[1143,3355,3356,3357,3362],{},"Plus, we're now using Nitro's beautiful error handling (powered by ",[2006,3358,3361],{"href":3359,"rel":3360},"https://github.com/poppinss/youch",[2010],"youch",") to provide more helpful error messages in the terminal, complete with stacktrace support.",[1143,3364,3365],{},"Nitro now also automatically applies source maps without requiring extra Node options, and we set appropriate security headers when rendering error pages.",[1147,3367,3369],{"id":3368},"module-development-improvements","📦 Module Development Improvements",[1143,3371,3372,3373,3114,3376,2887],{},"For module authors, we've added the ability to augment Nitro types with ",[1220,3374,3375],{},"addTypeTemplate",[2006,3377,3380],{"href":3378,"rel":3379},"https://github.com/nuxt/nuxt/pull/31079",[2010],"#31079",[1213,3382,3384],{"className":1669,"code":3383,"language":1672,"meta":1218,"style":1218},"// Inside your Nuxt module\nexport default defineNuxtModule({\n  setup(options, nuxt) {\n    addTypeTemplate({\n      filename: 'types/my-module.d.ts',\n      getContents: () => `\n        declare module 'nitropack' {\n          interface NitroRouteConfig {\n            myCustomOption?: boolean\n          }\n        }\n      `\n    }, { nitro: true })\n  }\n})\n",[1220,3385,3386,3391,3404,3422,3431,3447,3461,3466,3471,3476,3481,3486,3491,3509,3513],{"__ignoreMap":1218},[1223,3387,3388],{"class":1225,"line":1226},[1223,3389,3390],{"class":1229},"// Inside your Nuxt module\n",[1223,3392,3393,3395,3397,3400,3402],{"class":1225,"line":1233},[1223,3394,1745],{"class":1679},[1223,3396,1748],{"class":1679},[1223,3398,3399],{"class":1751}," defineNuxtModule",[1223,3401,1754],{"class":1285},[1223,3403,1757],{"class":1236},[1223,3405,3406,3409,3411,3413,3415,3418,3420],{"class":1225,"line":1263},[1223,3407,3408],{"class":1240},"  setup",[1223,3410,1754],{"class":1236},[1223,3412,2362],{"class":2329},[1223,3414,2333],{"class":1236},[1223,3416,3417],{"class":2329}," nuxt",[1223,3419,2541],{"class":1236},[1223,3421,1891],{"class":1236},[1223,3423,3424,3427,3429],{"class":1225,"line":1296},[1223,3425,3426],{"class":1751},"    addTypeTemplate",[1223,3428,1754],{"class":1240},[1223,3430,1757],{"class":1236},[1223,3432,3433,3436,3438,3440,3443,3445],{"class":1225,"line":1325},[1223,3434,3435],{"class":1240},"      filename",[1223,3437,1765],{"class":1236},[1223,3439,1695],{"class":1236},[1223,3441,3442],{"class":1254},"types/my-module.d.ts",[1223,3444,1957],{"class":1236},[1223,3446,1780],{"class":1236},[1223,3448,3449,3452,3454,3456,3458],{"class":1225,"line":1355},[1223,3450,3451],{"class":1751},"      getContents",[1223,3453,1765],{"class":1236},[1223,3455,3122],{"class":1236},[1223,3457,3125],{"class":1244},[1223,3459,3460],{"class":1236}," `\n",[1223,3462,3463],{"class":1225,"line":1771},[1223,3464,3465],{"class":1254},"        declare module 'nitropack' {\n",[1223,3467,3468],{"class":1225,"line":1783},[1223,3469,3470],{"class":1254},"          interface NitroRouteConfig {\n",[1223,3472,3473],{"class":1225,"line":1792},[1223,3474,3475],{"class":1254},"            myCustomOption?: boolean\n",[1223,3477,3478],{"class":1225,"line":1798},[1223,3479,3480],{"class":1254},"          }\n",[1223,3482,3483],{"class":1225,"line":1975},[1223,3484,3485],{"class":1254},"        }\n",[1223,3487,3488],{"class":1225,"line":1981},[1223,3489,3490],{"class":1236},"      `\n",[1223,3492,3493,3496,3498,3501,3503,3505,3507],{"class":1225,"line":1987},[1223,3494,3495],{"class":1236},"    },",[1223,3497,1683],{"class":1236},[1223,3499,3500],{"class":1240}," nitro",[1223,3502,1765],{"class":1236},[1223,3504,2929],{"class":2928},[1223,3506,1689],{"class":1236},[1223,3508,1804],{"class":1240},[1223,3510,3511],{"class":1225,"line":1993},[1223,3512,1990],{"class":1236},[1223,3514,3515,3517],{"class":1225,"line":2720},[1223,3516,1801],{"class":1236},[1223,3518,1804],{"class":1285},[1147,3520,3522],{"id":3521},"️-nitro-v211-upgrade","⚙️ Nitro v2.11 Upgrade",[1143,3524,3525],{},"We've upgraded to Nitro v2.11. There are so many improvements - more than I can cover in these brief release notes.",[1143,3527,3528,3529,2281],{},"👉 Check out all the details in the ",[2006,3530,3533],{"href":3531,"rel":3532},"https://github.com/nitrojs/nitro/releases/tag/v2.11.0",[2010],"Nitro v2.11.0 release notes",[1147,3535,3537,3538,3541],{"id":3536},"new-unjs-major-versions","📦 New ",[1220,3539,3540],{},"unjs"," Major Versions",[1143,3543,3544],{},"This release includes several major version upgrades from the unjs ecosystem, focused on performance and smaller bundle sizes through ESM-only distributions:",[1852,3546,3547,3550,3553,3556,3559,3562,3565,3568,3571,3574],{},[1855,3548,3549],{},"unenv upgraded to v2 (full rewrite)",[1855,3551,3552],{},"db0 upgraded to v0.3 (ESM-only, native node:sql, improvements)",[1855,3554,3555],{},"ohash upgraded to v2 (ESM-only, native node:crypto support, much faster)",[1855,3557,3558],{},"untyped upgraded to v2 (ESM-only, smaller install size)",[1855,3560,3561],{},"unimport upgraded to v4 (improvements)",[1855,3563,3564],{},"c12 upgraded to v3 (ESM-only)",[1855,3566,3567],{},"pathe upgraded to v2 (ESM-only)",[1855,3569,3570],{},"cookie-es upgraded to v2 (ESM-only)",[1855,3572,3573],{},"esbuild upgraded to v0.25",[1855,3575,3576],{},"chokidar upgraded to v4",[1147,3578,3580],{"id":3579},"upgrading","✅ Upgrading",[1143,3582,3583],{},"As usual, our recommendation for upgrading is to run:",[1213,3585,3589],{"className":3586,"code":3587,"language":3588,"meta":1218,"style":1218},"language-sh shiki shiki-themes material-theme-lighter material-theme-lighter material-theme-palenight","npx nuxi@latest upgrade --dedupe\n","sh",[1220,3590,3591],{"__ignoreMap":1218},[1223,3592,3593,3595,3597,3600],{"class":1225,"line":1226},[1223,3594,2037],{"class":2036},[1223,3596,2040],{"class":1254},[1223,3598,3599],{"class":1254}," upgrade",[1223,3601,3602],{"class":1254}," --dedupe\n",[1143,3604,3605],{},"This refreshes your lockfile and pulls in all the latest dependencies that Nuxt relies on, especially from the unjs ecosystem.",[1147,3607,3609],{"id":3608},"full-release-notes","Full release notes",[3611,3612,3617],"read-more",{"color":3613,"icon":3614,"target":3615,"to":3616},"gray","i-simple-icons-github","_blank","https://github.com/nuxt/nuxt/releases/tag/v3.16.0",[1143,3618,3619,3620,2281],{},"Read the full release notes of Nuxt ",[1220,3621,3622],{},"v3.16.0",[1143,3624,3625],{},"A huge thank you to everyone who's been a part of this release. ❤️",[1143,3627,3628],{},"I'm aware there have been lots of very significant changes in this release - please don't hesitate to let us know if you have any feedback or issues! 🙏",[2160,3630,3631],{},"html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}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 .svXlt, html code.shiki .svXlt{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .ssYd4, html code.shiki .ssYd4{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .sagxc, html code.shiki .sagxc{--shiki-light:#FF5370;--shiki-default:#FF5370;--shiki-dark:#FF9CAC}",{"title":1218,"searchDepth":1233,"depth":1233,"links":3633},[3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,3644,3645,3646,3648,3649],{"id":2201,"depth":1233,"text":2202},{"id":2284,"depth":1233,"text":2285},{"id":2447,"depth":1233,"text":2448},{"id":2474,"depth":1233,"text":2475},{"id":2577,"depth":1233,"text":2578},{"id":2796,"depth":1233,"text":2797},{"id":2873,"depth":1233,"text":2874},{"id":3042,"depth":1233,"text":3043},{"id":3241,"depth":1233,"text":3242},{"id":3328,"depth":1233,"text":3329},{"id":3368,"depth":1233,"text":3369},{"id":3521,"depth":1233,"text":3522},{"id":3536,"depth":1233,"text":3647},"📦 New unjs Major Versions",{"id":3579,"depth":1233,"text":3580},{"id":3608,"depth":1233,"text":3609},"2025-03-07T10:00:00.000Z","Nuxt 3.16 is out - with packed with features and performance improvements","/assets/blog/v3.16.png",{},"/blog/v3-16",{"title":2187,"description":3651},"blog/31.v3-16","8rNOslSuw3",{"id":3659,"title":3660,"authors":3661,"body":3664,"category":2176,"date":4054,"description":4055,"draft":108,"extension":1954,"image":4056,"meta":4057,"navigation":108,"path":4058,"seo":4059,"stem":4060,"tags":6,"__hash__":4061},"blog/blog/30.v3-15.md","Nuxt 3.15",[3662],{"name":2190,"avatar":3663,"to":2193},{"src":2192},{"type":1140,"value":3665,"toc":4041},[3666,3669,3673,3682,3686,3701,3704,3712,3716,3719,3728,3734,3740,3764,3812,3816,3827,3830,3834,3850,3861,3965,3969,3977,3988,3992,4000,4002,4004,4020,4023,4025,4033,4035,4038],[1143,3667,3668],{},"We're continuing to work on the release of Nitro v3, Nuxt v4 and more. But we're delighted to ship Nuxt v3.15 (just) in time for Christmas.",[1147,3670,3672],{"id":3671},"️-snowfall","❄️ Snowfall!",[1143,3674,3675,3676,3681],{},"Happy holidays! You'll notice when you start Nuxt that (if you're in the Northern Hemisphere) there's some snow on the loading screen (",[2006,3677,3680],{"href":3678,"rel":3679},"https://github.com/nuxt/nuxt/pull/29871",[2010],"#29871",").",[1147,3683,3685],{"id":3684},"️-vite-6-included","⚡️ Vite 6 included",[1143,3687,3688,3689,3694,3695,3700],{},"Nuxt v3.15 includes ",[2006,3690,3693],{"href":3691,"rel":3692},"https://vite.dev/blog/announcing-vite6",[2010],"Vite 6"," for the first time. Although this is a major version, we expect that this won't be a breaking change for Nuxt users (see full ",[2006,3696,3699],{"href":3697,"rel":3698},"https://vite.dev/guide/migration.html",[2010],"migration guide","). However, please take care if you have dependencies that rely on a particular Vite version.",[1143,3702,3703],{},"One of the most significant changes with Vite 6 is the new Environment API, which we hope to use in conjunction with Nitro to improve the server dev environment. Watch this space!",[1143,3705,3706,3707,2281],{},"You can read the full list of changes in the ",[2006,3708,3711],{"href":3709,"rel":3710},"https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#600-2024-11-26",[2010],"Vite 6 changelog",[1147,3713,3715],{"id":3714},"chromium-devtools-improvements","🪵 Chromium devtools improvements",[1143,3717,3718],{},"We talk a lot about the Nuxt DevTools, but v3.15 ships with better integration in dev mode for Chromium-based browser devtools.",[1143,3720,3721,3722,3727],{},"We now use the ",[2006,3723,3726],{"href":3724,"rel":3725},"https://developer.chrome.com/docs/devtools/performance/extension",[2010],"Chrome DevTools extensibility API"," to add support for printing nuxt hook timings in the browser devtools performance panel.",[1143,3729,3730],{},[2243,3731],{"alt":3732,"src":3733},"CleanShot 2024-11-14 at 15 05 22@2x","https://github.com/user-attachments/assets/57525027-750a-462f-b713-398302aec0cd",[1147,3735,3737,3738],{"id":3736},"️-navigation-mode-for-callonce","🗺️ Navigation mode for ",[1220,3739,559],{},[1143,3741,3742,3744,3745,3749,3750,3753,3754,3757,3758,3763],{},[1220,3743,559],{}," is a built-in Nuxt composable for running code only once. For example, if the code runs on the server it won't run again on the client. But sometimes you do want code to run on ",[3746,3747,3748],"em",{},"every navigation"," - just avoid the initial server/client double load. For this, there's a new ",[1220,3751,3752],{},"mode: 'navigation'"," option that will run the code only once ",[3746,3755,3756],{},"per navigation",". (See ",[2006,3759,3762],{"href":3760,"rel":3761},"https://github.com/nuxt/nuxt/pull/30260",[2010],"#30260"," for more info.)",[1213,3765,3767],{"className":1669,"code":3766,"language":1672,"meta":1218,"style":1218},"await callOnce(() => counter.value++, { mode: 'navigation' })\n",[1220,3768,3769],{"__ignoreMap":1218},[1223,3770,3771,3774,3777,3779,3781,3783,3786,3788,3791,3794,3796,3799,3801,3803,3806,3808,3810],{"class":1225,"line":1226},[1223,3772,3773],{"class":1679},"await",[1223,3775,3776],{"class":1751}," callOnce",[1223,3778,1754],{"class":1285},[1223,3780,1777],{"class":1236},[1223,3782,3125],{"class":1244},[1223,3784,3785],{"class":1285}," counter",[1223,3787,2281],{"class":1236},[1223,3789,3790],{"class":1285},"value",[1223,3792,3793],{"class":1236},"++,",[1223,3795,1683],{"class":1236},[1223,3797,3798],{"class":1240}," mode",[1223,3800,1765],{"class":1236},[1223,3802,1695],{"class":1236},[1223,3804,3805],{"class":1254},"navigation",[1223,3807,1957],{"class":1236},[1223,3809,1689],{"class":1236},[1223,3811,1804],{"class":1285},[1147,3813,3815],{"id":3814},"hmr-for-templates-pages-page-metadata","🥵 HMR for templates, pages + page metadata",[1143,3817,3818,3819,3821,3822,3681],{},"We now implement hot module reloading for Nuxt's virtual files (like routes, plugins, generated files) as well as for the content of page metadata (within a ",[1220,3820,587],{}," macro) (",[2006,3823,3826],{"href":3824,"rel":3825},"https://github.com/nuxt/nuxt/pull/30113",[2010],"#30113",[1143,3828,3829],{},"This should mean you have a faster experience in development, as well as not needing to reload the page when making changes to your routes.",[1147,3831,3833],{"id":3832},"page-meta-enhancements","📋 Page meta enhancements",[1143,3835,3836,3837,3114,3840,3845,3846,3849],{},"We now support extracting extra page meta keys (likely used by module authors) via ",[1220,3838,3839],{},"experimental.extraPageMetaExtractionKeys",[2006,3841,3844],{"href":3842,"rel":3843},"https://github.com/nuxt/nuxt/pull/30015",[2010],"#30015","). This enables module authors to use this information at build time, in the ",[1220,3847,3848],{},"pages:resolved"," hook.",[1143,3851,3852,3853,3114,3855,3860],{},"We also now support local functions in ",[1220,3854,587],{},[2006,3856,3859],{"href":3857,"rel":3858},"https://github.com/nuxt/nuxt/pull/30241",[2010],"#30241","). This means you can do something like this:",[1213,3862,3864],{"className":1669,"code":3863,"language":1672,"meta":1218,"style":1218},"function validateIdParam(route) {\n  return !!(route.params.id && !isNaN(Number(route.params.id)))\n}\n\ndefinePageMeta({\n  validate: validateIdParam,\n})\n",[1220,3865,3866,3882,3932,3936,3940,3948,3959],{"__ignoreMap":1218},[1223,3867,3868,3870,3873,3875,3878,3880],{"class":1225,"line":1226},[1223,3869,3108],{"class":1244},[1223,3871,3872],{"class":1751}," validateIdParam",[1223,3874,1754],{"class":1236},[1223,3876,3877],{"class":2329},"route",[1223,3879,2541],{"class":1236},[1223,3881,1891],{"class":1236},[1223,3883,3884,3886,3889,3891,3893,3895,3898,3900,3903,3906,3909,3912,3914,3917,3919,3921,3923,3925,3927,3929],{"class":1225,"line":1233},[1223,3885,2374],{"class":1679},[1223,3887,3888],{"class":1236}," !!",[1223,3890,1754],{"class":1240},[1223,3892,3877],{"class":1285},[1223,3894,2281],{"class":1236},[1223,3896,3897],{"class":1285},"params",[1223,3899,2281],{"class":1236},[1223,3901,3902],{"class":1285},"id",[1223,3904,3905],{"class":1236}," &&",[1223,3907,3908],{"class":1236}," !",[1223,3910,3911],{"class":1751},"isNaN",[1223,3913,1754],{"class":1240},[1223,3915,3916],{"class":1751},"Number",[1223,3918,1754],{"class":1240},[1223,3920,3877],{"class":1285},[1223,3922,2281],{"class":1236},[1223,3924,3897],{"class":1285},[1223,3926,2281],{"class":1236},[1223,3928,3902],{"class":1285},[1223,3930,3931],{"class":1240},")))\n",[1223,3933,3934],{"class":1225,"line":1263},[1223,3935,2407],{"class":1236},[1223,3937,3938],{"class":1225,"line":1296},[1223,3939,1740],{"emptyLinePlaceholder":1739},[1223,3941,3942,3944,3946],{"class":1225,"line":1325},[1223,3943,587],{"class":1751},[1223,3945,1754],{"class":1285},[1223,3947,1757],{"class":1236},[1223,3949,3950,3953,3955,3957],{"class":1225,"line":1355},[1223,3951,3952],{"class":1240},"  validate",[1223,3954,1765],{"class":1236},[1223,3956,3872],{"class":1285},[1223,3958,1780],{"class":1236},[1223,3960,3961,3963],{"class":1225,"line":1771},[1223,3962,1801],{"class":1236},[1223,3964,1804],{"class":1285},[1147,3966,3968],{"id":3967},"performance-improvements","🔥 Performance improvements",[1143,3970,3971,3972,3681],{},"We now preload the app manifest in the browser if it will be used when hydrating the app (",[2006,3973,3976],{"href":3974,"rel":3975},"https://github.com/nuxt/nuxt/pull/30017",[2010],"#30017",[1143,3978,3979,3980,3114,3983,3681],{},"We'll also tree shake vue-router's hash mode history out of your bundle if we can - specifically, if you haven't customised your ",[1220,3981,3982],{},"app/router.options.ts",[2006,3984,3987],{"href":3985,"rel":3986},"https://github.com/nuxt/nuxt/pull/30297",[2010],"#30297",[1147,3989,3991],{"id":3990},"v4-updates","🐣 v4 updates",[1143,3993,3994,3995,3681],{},"If A few more changes shipped for the new defaults for v4, including only inlining styles by default for Vue components (",[2006,3996,3999],{"href":3997,"rel":3998},"https://github.com/nuxt/nuxt/pull/30305",[2010],"#30305",[1147,4001,3580],{"id":3579},[1143,4003,3583],{},[1213,4005,4007],{"className":3586,"code":4006,"language":3588,"meta":1218,"style":1218},"npx nuxi@latest upgrade --force\n",[1220,4008,4009],{"__ignoreMap":1218},[1223,4010,4011,4013,4015,4017],{"class":1225,"line":1226},[1223,4012,2037],{"class":2036},[1223,4014,2040],{"class":1254},[1223,4016,3599],{"class":1254},[1223,4018,4019],{"class":1254}," --force\n",[1143,4021,4022],{},"This will refresh your lockfile as well, and ensures that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.",[1147,4024,3609],{"id":3608},[3611,4026,4028],{"color":3613,"icon":3614,"target":3615,"to":4027},"https://github.com/nuxt/nuxt/releases/tag/v3.15.0",[1143,4029,3619,4030,2281],{},[1220,4031,4032],{},"v3.15.0",[1143,4034,3625],{},[1143,4036,4037],{},"Don't hesitate to let us know if you have any feedback or issues! 🙏",[2160,4039,4040],{},"html pre.shiki code .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}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 .ssYd4, html code.shiki .ssYd4{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}",{"title":1218,"searchDepth":1233,"depth":1233,"links":4042},[4043,4044,4045,4046,4048,4049,4050,4051,4052,4053],{"id":3671,"depth":1233,"text":3672},{"id":3684,"depth":1233,"text":3685},{"id":3714,"depth":1233,"text":3715},{"id":3736,"depth":1233,"text":4047},"🗺️ Navigation mode for callOnce",{"id":3814,"depth":1233,"text":3815},{"id":3832,"depth":1233,"text":3833},{"id":3967,"depth":1233,"text":3968},{"id":3990,"depth":1233,"text":3991},{"id":3579,"depth":1233,"text":3580},{"id":3608,"depth":1233,"text":3609},"2024-12-24T10:00:00.000Z","Nuxt 3.15 is out - with Vite 6, better HMR and faster performance","/assets/blog/v3.15.png",{},"/blog/v3-15",{"title":3660,"description":4055},"blog/30.v3-15","P53sMpT0zT",{"id":4063,"title":1068,"authors":4064,"body":4071,"category":2176,"date":4654,"description":4655,"draft":108,"extension":1954,"image":4656,"meta":4657,"navigation":1739,"path":1069,"seo":4658,"stem":1070,"tags":6,"__hash__":4659},"blog/blog/29.nuxt-icon-v1-0.md",[4065],{"name":4066,"avatar":4067,"to":4069,"twitter":4070},"Anthony Fu",{"src":4068},"https://github.com/antfu.png","https://github.com/antfu","antfu7",{"type":1140,"value":4072,"toc":4635},[4073,4076,4083,4086,4089,4093,4096,4103,4106,4144,4151,4154,4156,4160,4163,4171,4177,4183,4190,4193,4195,4199,4202,4205,4208,4215,4218,4220,4224,4227,4230,4233,4240,4243,4246,4248,4252,4260,4263,4270,4273,4275,4279,4290,4301,4308,4311,4313,4317,4331,4334,4341,4348,4351,4353,4357,4369,4401,4408,4411,4414,4417,4420,4422,4426,4429,4433,4440,4443,4450,4452,4456,4459,4466,4473,4476,4483,4485,4489,4492,4521,4528,4531,4533,4537,4540,4543,4563,4577,4619,4627,4632],[1143,4074,4075],{},"Icons are essential to modern web interfaces. They simplify navigation, clarify functionality, and enhance visual appeal. However, implementing icons efficiently involves challenges like scalability, dynamic loading, and server-side rendering (SSR) compatibility.",[1143,4077,4078,4079,4082],{},"To address these challenges, we developed ",[1159,4080,4081],{},"Nuxt Icon v1"," — a versatile, modern solution tailored for Nuxt projects. By building on established icon rendering techniques and introducing novel approaches, Nuxt Icon bridges the gap between performance, usability, and flexibility.",[1143,4084,4085],{},"In this post, we’ll explore the challenges of icon rendering, the evolution of icon solutions, and how Nuxt Icon combines the best aspects of these methods to offer a seamless experience for developers.",[4087,4088],"hr",{},[1147,4090,4092],{"id":4091},"why-are-icons-challenging","Why Are Icons Challenging?",[1143,4094,4095],{},"At first glance, icons seem simple - they are essentially just tiny image elements that enhance a user interface, providing visual cues and enhancing usability.",[1143,4097,4098],{},[2243,4099],{"alt":4100,"className":4101,"src":4102},"Icons Showcases",[2247,2248,2249,2250],"/assets/blog/nuxt-icon/icons-showcase.png",[1143,4104,4105],{},"However, from an engineering perspective, they pose several challenges. Ideal icons should be:",[1852,4107,4108,4114,4120,4126,4132,4138],{},[1855,4109,4110,4113],{},[1159,4111,4112],{},"Colorable",": Adaptable to themes and color schemes.",[1855,4115,4116,4119],{},[1159,4117,4118],{},"Scalable",": Render crisply at various sizes and resolutions.",[1855,4121,4122,4125],{},[1159,4123,4124],{},"Manageable",": Icon sets can contain hundreds or thousands of icons.",[1855,4127,4128,4131],{},[1159,4129,4130],{},"Efficiently Bundled",": Minimize network requests.",[1855,4133,4134,4137],{},[1159,4135,4136],{},"Optimally Loaded",": Affect application performance and user experience.",[1855,4139,4140,4143],{},[1159,4141,4142],{},"Dynamic",": Support dynamic loading for user-generated or runtime-defined icons.",[1143,4145,4146],{},[2243,4147],{"alt":4148,"className":4149,"src":4150},"Engineering Challenges with Icons",[2247,2248,2249,2250],"/assets/blog/nuxt-icon/challenges.png",[1143,4152,4153],{},"Meeting all these needs requires a carefully engineered solution that balances trade-offs. Let’s explore the evolution of icon solutions and how they address these challenges.",[4087,4155],{},[1147,4157,4159],{"id":4158},"a-journey-through-icon-solutions","A Journey Through Icon Solutions",[1143,4161,4162],{},"Over the years, developers have experimented with various techniques to render icons efficiently. Let’s explore the evolution of these solutions and the challenges they faced.",[1155,4164,4166,4167,4170],{"id":4165},"_1-img-tags-the-early-days","1. ",[1220,4168,4169],{},"\u003Cimg>"," Tags: The Early Days",[1143,4172,4173,4174,4176],{},"The most straightforward solution: using the ",[1220,4175,4169],{}," tag. This was the go-to method in the early days of the web.",[1143,4178,4179,4180,4182],{},"You'd host your image assets and use an ",[1220,4181,4169],{}," tag to link to that image, specifying its width and height. It's simple, requires no setup or runtime dependencies, and works natively in browsers.",[1143,4184,4185],{},[2243,4186],{"alt":4187,"className":4188,"src":4189},"Solution 1",[2247,2248,2249,2250],"/assets/blog/nuxt-icon/solution-1.png",[1143,4191,4192],{},"However, there are drawbacks. Images can become pixelated, lack color control, and don't scale well. Each icon being a separate image file results in many network requests, which could be slow, especially back in the days of HTTP 1.1. Before the image is downloaded, you might see a flash of invisible icons, which can hurt the user experience. Lastly, it's quite verbose to write, as you need to specify the full path of the image and manage the relative paths. It explains why this approach is rarely used on modern websites today.",[4087,4194],{},[1155,4196,4198],{"id":4197},"_2-web-fonts-icon-fonts","2. Web Fonts: Icon Fonts",[1143,4200,4201],{},"As the next step in icon evolution, web fonts emerged as a popular solution. Fonts are inherently vectorized and colorable, making them a natural fit for icons.",[1143,4203,4204],{},"Iconset providers typically compile their icons into a special font file, assigning a unique Unicode character to each icon. This is accompanied by a CSS file that maps these Unicode values to specific icon classes.",[1143,4206,4207],{},"The advantages of this approach are clear: it's easy to use, colorable, scalable, and requires only a single request to load all icons.",[1143,4209,4210],{},[2243,4211],{"alt":4212,"className":4213,"src":4214},"Solution 2",[2247,2248,2249,2250],"/assets/blog/nuxt-icon/solution-2.png",[1143,4216,4217],{},"However, there are some downsides. Loading a large font file upfront can be slow, and customizing the icon set is challenging. Additionally, you might experience a flash of invisible icons before the font loads, as there are no fallback fonts available.",[4087,4219],{},[1155,4221,4223],{"id":4222},"_3-inline-svgs-component-based-icons","3. Inline SVGs: Component-Based Icons",[1143,4225,4226],{},"With the advent of modern frontend frameworks, reusing HTML elements has become significantly easier. This led to the idea of directly inlining SVG tags as components.",[1143,4228,4229],{},"To support this approach, many icon sets provide packages with wrappers tailored for each framework. For instance, MDI icons use a shared component and pass icon data as props, while Tabler icons offer a dedicated component for each icon.",[1143,4231,4232],{},"Since these are SVGs, they are inherently colorable, scalable, and retain all the features of SVGs. Typically, icons are bundled into the app, eliminating additional network requests and ensuring they are SSR-friendly and visible on the first render.",[1143,4234,4235],{},[2243,4236],{"alt":4237,"className":4238,"src":4239},"Solution 3",[2247,2248,2249,2250],"/assets/blog/nuxt-icon/solution-3.png",[1143,4241,4242],{},"However, this method has its downsides. It generates numerous SVG DOM elements, which can impact performance when many icons are used. It also increases the bundle size and requires specific integration support for each icon set and framework combination, leading to a degree of vendor lock-in. This makes it challenging to switch to a different icon set or framework.",[1143,4244,4245],{},"Despite these trade-offs, this approach is widely adopted today, as switching icon sets or frameworks is not a frequent necessity for most projects.",[4087,4247],{},[1155,4249,4251],{"id":4250},"_4-iconify-runtime-dynamic-api-access","4. Iconify Runtime: Dynamic API Access",[1143,4253,4254,4259],{},[2006,4255,4258],{"href":4256,"rel":4257},"https://iconify.design/",[2010],"Iconify"," revolutionized icon usage by aggregating over 200,000 icons across 100+ collections. Its runtime solution dynamically fetched icons via an API, enabling dynamic access to any icon without pre-bundling.",[1143,4261,4262],{},"This is a great fit for rendering icons from user-provided content or other dynamic content that you don't know at build time. And it's super easy to set up, as you can even use it as a CDN without any build tools.",[1143,4264,4265],{},[2243,4266],{"alt":4267,"className":4268,"src":4269},"Solution 4",[2247,2248,2249,2250],"/assets/blog/nuxt-icon/solution-4.png",[1143,4271,4272],{},"While this method offers great flexibility, it does come with some trade-offs. It introduces runtime dependencies, meaning icons will only render after JavaScript is loaded and the icon data is fetched. This approach also poses challenges for server-side rendering (SSR) and caching layers, such as those used in Progressive Web Apps (PWAs).",[4087,4274],{},[1155,4276,4278],{"id":4277},"_5-on-demand-component-icons","5. On-Demand Component Icons",[1143,4280,4281,4282,4289],{},"With the unified interface from Iconify and Vite's on-demand approach, we developed ",[2006,4283,4286],{"href":4284,"rel":4285},"https://github.com/unplugin/unplugin-icons",[2010],[1220,4287,4288],{},"unplugin-icons",". This tool allows you to import any icons as components on-demand.",[1143,4291,4292,4293,4300],{},"As an ",[2006,4294,4297],{"href":4295,"rel":4296},"https://github.com/unjs/unplugin",[2010],[1220,4298,4299],{},"unplugin",", it supports all popular build tools, including Vite, webpack, and rspack. We provide compilers for popular frameworks like Vue, React, Svelte, and Solid. With Iconify, you can use any icon across any framework, minimizing vendor lock-in.",[1143,4302,4303],{},[2243,4304],{"alt":4305,"className":4306,"src":4307},"Solution 5",[2247,2248,2249,2250],"/assets/blog/nuxt-icon/solution-5.png",[1143,4309,4310],{},"While this technique shares the same pros and cons as previous component icon solutions, the integration with build tools allows us to serve the full Iconify collection while only shipping the icons you actually use. However, runtime concerns like DOM element management still persist.",[4087,4312],{},[1155,4314,4316],{"id":4315},"_6-pure-css-icons","6. Pure CSS Icons",[1143,4318,4319,4320,4325,4326,2281],{},"As a side-effect of working on ",[2006,4321,4324],{"href":4322,"rel":4323},"https://unocss.dev/",[2010],"UnoCSS",", we discovered the potential of embedding icons entirely in CSS, leading to the innovative solution of ",[2006,4327,4330],{"href":4328,"rel":4329},"https://antfu.me/posts/icons-in-pure-css",[2010],"Pure CSS Icons",[1143,4332,4333],{},"This method involves inlining SVG icons as data URLs and providing a single class to display the icons. With some tweaks, these icons become colorable, scalable, and even capable of displaying SVG animations.",[1143,4335,4336,4337,4340],{},"Browsers can cache the CSS rules, and each icon requires only ",[1159,4338,4339],{},"one DOM element"," to render. This approach ships the icons in a single CSS file with no additional requests. Since it's pure CSS, the icons display along with the rest of your UI, require zero runtime, and work naturally with SSR—your server doesn't need any extra work on the server side.",[1143,4342,4343],{},[2243,4344],{"alt":4345,"className":4346,"src":4347},"Solution 6",[2247,2248,2249,2250],"/assets/blog/nuxt-icon/solution-6.png",[1143,4349,4350],{},"The only downsides are the lack of full customization for elements inside the SVG and the need to bundle icons at build-time, which isn't dynamic.",[4087,4352],{},[1147,4354,4356],{"id":4355},"the-challenges-to-integrate-in-nuxt","The Challenges to Integrate in Nuxt",[1143,4358,4359,4360,4363,4364,4368],{},"While I would say that the ",[2006,4361,4330],{"href":4362},"#_6-pure-css-icons"," and ",[2006,4365,4367],{"href":4366},"#_5-on-demand-component-icons","On-demand Component Icons"," would be pretty sufficient for most of the static usages, Nuxt as a full featured framework, has a bit more requirements to integrate icons efficiently:",[1852,4370,4371,4377,4389,4395],{},[1855,4372,4373,4376],{},[1159,4374,4375],{},"SSR/CSR",": Nuxt works in both server-side rendering (SSR) and client-side rendering (CSR) modes. We care a lot about the end user experience, and we want to ensure that icons are rendered instantly without flickers.",[1855,4378,4379,4382,4383,4388],{},[1159,4380,4381],{},"Dynamic Icons",": In integrations like ",[2006,4384,4387],{"href":4385,"rel":4386},"https://content.nuxt.com/",[2010],"Nuxt Content",", the content can be provided at runtime or from external sources, which we are not aware at build time. We want to ensure we have the capability to integrate with those cases well.",[1855,4390,4391,4394],{},[1159,4392,4393],{},"Performance",": We want to ensure that the icons are bundled efficiently, and the loading of icons is optimized for the best performance.",[1855,4396,4397,4400],{},[1159,4398,4399],{},"Custom Icons",": While Iconify provides a wide range of icons for selection, we also aware it's pretty common for projects to have their own icon sets, or wanted to use paid icons that are not available in Iconify. Supporting custom icons is crucial for our users.",[1143,4402,4403],{},[2243,4404],{"alt":4405,"className":4406,"src":4407},"Nuxt Integration Challenges and Solutions",[2247,2248,2249,2250],"/assets/blog/nuxt-icon/nuxt-icon-challenges.png",[1143,4409,4410],{},"With these requirements in mind, let's revisit the solutions we discussed earlier and see how they stack up.",[1143,4412,4413],{},"For dynamic icons, the Iconify Runtime stands out as a viable option. It allows for dynamic fetching of icons, making it suitable for content that isn't known at build time. However, it has its drawbacks. The reliance on runtime dependencies means it doesn't integrate seamlessly with SSR, and it doesn't support custom icons since the requests are directed to Iconify's servers, which don't have access to our local icon setup.",[1143,4415,4416],{},"Conversely, Pure CSS Icons offer excellent performance and SSR compatibility. They ensure icons are rendered instantly without flickers and are bundled efficiently. However, they fall short when it comes to dynamic icons, as they need to be bundled at build time and lack the flexibility to adapt to runtime content changes.",[1143,4418,4419],{},"Balancing these trade-offs is indeed challenging. So, why not leverage the strengths of both approaches? By understanding these trade-offs, we can better appreciate the balanced solution that Nuxt Icon v1 offers.",[4087,4421],{},[1147,4423,4425],{"id":4424},"introducing-nuxt-icon-v1-the-balance-of-both-worlds","Introducing Nuxt Icon v1: The Balance of Both Worlds",[1143,4427,4428],{},"With the flexibility of the Nuxt Module system, Nuxt Icon combines the best of both worlds: the instant rendering of CSS icons and the dynamic fetching of Iconify icons. This dual approach provides a versatile, modern, and customizable icon solution that seamlessly adapts to your project's needs.",[1155,4430,4432],{"id":4431},"dual-rendering-modes","Dual Rendering Modes",[1143,4434,4435,4436,4439],{},"To address the trade-offs in rendering approaches, Nuxt Icon introduces a versatile ",[1220,4437,4438],{},"\u003CIcon>"," component that supports both CSS and SVG modes, both of which are SSR-friendly. Depending on your customization needs, you can switch between these modes for each icon.",[1143,4441,4442],{},"In CSS mode, icons are included in the CSS during SSR, ensuring they render instantly without any runtime cost. In SVG mode, icons are inlined as HTML during SSR, providing the same immediate rendering benefits. Both approaches ensure that icons appear on the initial screen without any delay, offering a seamless user experience.",[1143,4444,4445],{},[2243,4446],{"alt":4447,"className":4448,"src":4449},"Dual rendering mode",[2247,2248,2249,2250],"/assets/blog/nuxt-icon/dual-rendering-modes.png",[4087,4451],{},[1155,4453,4455],{"id":4454},"icon-bundles","Icon Bundles",[1143,4457,4458],{},"Dynamic icons present unique challenges, especially when it comes to loading them efficiently. To address this, we leverage Iconify's API, which allows us to serve any icon on demand via network requests. However, relying solely on this API can introduce delays, especially if the servers are geographically distant from your users.",[1143,4460,4461,4462,4465],{},"To mitigate this, we introduced the concept of Icon Bundles. We can bundle frequently used icons directly into the ",[1220,4463,4464],{},"Client Bundle",". This ensures that these icons render instantly without additional network requests. However, bundling all possible icons isn't feasible due to the potential increase in bundle size.",[1143,4467,4468,4469,4472],{},"Given that Nuxt is a full-stack framework, we can strike a balance by introducing a ",[1220,4470,4471],{},"Server Bundle",". On the server side, bundle size is less of an issue, allowing us to include a more extensive set of icons. During SSR, these icons can be fetched quickly and sent to the client as needed. This setup ensures high performance for commonly used icons while still providing the flexibility to serve any icon from Iconify as a fallback.",[1143,4474,4475],{},"By combining client-side bundling for static icons and server-side bundling for dynamic icons, we achieve an optimal balance between performance and flexibility.",[1143,4477,4478],{},[2243,4479],{"alt":4480,"className":4481,"src":4482},"Icon Bundles in Nuxt Icons",[2247,2248,2249,2250],"/assets/blog/nuxt-icon/bundles.png",[4087,4484],{},[1155,4486,4488],{"id":4487},"data-flow","Data Flow",[1143,4490,4491],{},"Here is a data flow diagram illustrating how Nuxt Icon requests icon data:",[2412,4493,4494,4503,4509,4515,4518],{},[1855,4495,4496,4497,4499,4500,2281],{},"You use the ",[1220,4498,4438],{}," component and provide the icon ",[1220,4501,4502],{},"name",[1855,4504,4505,4506,4508],{},"Nuxt Icon will first check if the icon is available in the ",[1220,4507,4464],{},", or the SSR payload (icons that are known at SSR will be presented in the payload). If so, the icon will be rendered instantly.",[1855,4510,4511,4512,4514],{},"If the icon is not available on the client side, Nuxt Icon will fetch the icon data from the server API shipped along with your Nuxt app. Inside the server endpoint, it will query from the ",[1220,4513,4471],{}," to see if the icon is available.",[1855,4516,4517],{},"Between that, there are multiple cache systems involved. Server endpoint cache, HTTP cache, and client-side cache to ensure the icon is fetched efficiently and quickly. Since icon data does not change frequently, we use hard cache strategies to ensure the best performance.",[1855,4519,4520],{},"When the icon is unknown to both the client and server (dynamic icons), the server endpoint will fallback to the Iconify API to fetch the icon data. Since the server endpoint is cached, the Iconify API will be called only once for each unique icon regardless of how many clients are requesting it, to save resources on both sides.",[1143,4522,4523],{},[2243,4524],{"alt":4525,"className":4526,"src":4527},"Nuxt Icon Requesting Data flow",[2247,2248,2249,2250],"/assets/blog/nuxt-icon/dataflow.png",[1143,4529,4530],{},"This layered approach ensures efficient icon delivery, balancing speed and flexibility, while being as dynamic as possible. And balance out the trade-offs between each solution.",[4087,4532],{},[1147,4534,4536],{"id":4535},"try-nuxt-icon-today","Try Nuxt Icon Today",[1143,4538,4539],{},"Nuxt Icon v1 represents the culmination of years of innovation in icon rendering. Whether you’re building a dynamic app, a static website, or anything in between, Nuxt Icon adapts to your needs.",[1143,4541,4542],{},"It’s easy to add Nuxt Icon to your project by running the following command:",[1213,4544,4546],{"className":2022,"code":4545,"language":2024,"meta":1218,"style":1218},"npx nuxi module add icon\n",[1220,4547,4548],{"__ignoreMap":1218},[1223,4549,4550,4552,4555,4558,4560],{"class":1225,"line":1226},[1223,4551,2037],{"class":2036},[1223,4553,4554],{"class":1254}," nuxi",[1223,4556,4557],{"class":1254}," module",[1223,4559,2069],{"class":1254},[1223,4561,4562],{"class":1254}," icon\n",[1143,4564,4565,4566,4568,4569,4571,4572,1765],{},"Then, import the ",[1220,4567,4438],{}," component in your Vue components, providing icon ",[1220,4570,4502],{}," following ",[2006,4573,4576],{"href":4574,"rel":4575},"https://iconify.design/docs/icons/icon-basics.html",[2010],"Iconify's conventions",[1213,4578,4580],{"className":2595,"code":4579,"language":2597,"meta":1218,"style":1218},"\u003Ctemplate>\n  \u003CIcon name=\"i-lucide-activity\" />\n\u003C/template>\n",[1220,4581,4582,4590,4611],{"__ignoreMap":1218},[1223,4583,4584,4586,4588],{"class":1225,"line":1226},[1223,4585,1237],{"class":1236},[1223,4587,2606],{"class":1240},[1223,4589,1260],{"class":1236},[1223,4591,4592,4594,4597,4600,4602,4604,4607,4609],{"class":1225,"line":1233},[1223,4593,1266],{"class":1236},[1223,4595,4596],{"class":1240},"Icon",[1223,4598,4599],{"class":1244}," name",[1223,4601,1248],{"class":1236},[1223,4603,1251],{"class":1236},[1223,4605,4606],{"class":1254},"i-lucide-activity",[1223,4608,1251],{"class":1236},[1223,4610,2626],{"class":1236},[1223,4612,4613,4615,4617],{"class":1225,"line":1263},[1223,4614,1289],{"class":1236},[1223,4616,2606],{"class":1240},[1223,4618,1260],{"class":1236},[1143,4620,4621,4622,4626],{},"Explore more with the ",[2006,4623,2147],{"href":4624,"rel":4625},"https://github.com/nuxt/icon",[2010],", experiment with its features, and let us know your thoughts. We’re excited to see how Nuxt Icon transforms your projects!",[1143,4628,4629],{},[1159,4630,4631],{},"Happy Nuxting ✨",[2160,4633,4634],{},"html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}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 .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}",{"title":1218,"searchDepth":1233,"depth":1233,"links":4636},[4637,4638,4647,4648,4653],{"id":4091,"depth":1233,"text":4092},{"id":4158,"depth":1233,"text":4159,"children":4639},[4640,4642,4643,4644,4645,4646],{"id":4165,"depth":1263,"text":4641},"1. \u003Cimg> Tags: The Early Days",{"id":4197,"depth":1263,"text":4198},{"id":4222,"depth":1263,"text":4223},{"id":4250,"depth":1263,"text":4251},{"id":4277,"depth":1263,"text":4278},{"id":4315,"depth":1263,"text":4316},{"id":4355,"depth":1233,"text":4356},{"id":4424,"depth":1233,"text":4425,"children":4649},[4650,4651,4652],{"id":4431,"depth":1263,"text":4432},{"id":4454,"depth":1263,"text":4455},{"id":4487,"depth":1263,"text":4488},{"id":4535,"depth":1233,"text":4536},"2024-11-25T00:00:00.000Z","Discover Nuxt Icon v1 - a modern, versatile, and customizable icon solution for your Nuxt projects.","/assets/blog/nuxt-icon/cover.png",{},{"title":1068,"description":4655},"V7DFWyU2vN",{"id":4661,"title":4662,"authors":4663,"body":4666,"category":2176,"date":4968,"description":4969,"draft":108,"extension":1954,"image":4970,"meta":4971,"navigation":108,"path":4972,"seo":4973,"stem":4974,"tags":6,"__hash__":4975},"blog/blog/27.v3-14.md","Nuxt 3.14",[4664],{"name":2190,"avatar":4665,"to":2193},{"src":2192},{"type":1140,"value":4667,"toc":4955},[4668,4674,4681,4693,4697,4704,4724,4731,4745,4753,4762,4765,4782,4786,4804,4808,4821,4825,4835,4885,4889,4892,4916,4918,4920,4934,4936,4939,4947,4950,4952],[1143,4669,4670,4671,4673],{},"Behind the scenes, a lot has been going on in preparation for the release of Nuxt v4 (particularly on the ",[1220,4672,3540],{}," side with preparations for Nitro v3!)",[1155,4675,4677,4678],{"id":4676},"️-faster-starts-powered-by-jiti","⚡️ Faster starts powered by ",[1220,4679,4680],{},"jiti",[1143,4682,4683,4684,4686,4687,4692],{},"Loading the nuxt config file, as well as modules and other build-time code, is now powered by ",[1220,4685,4680],{}," v2. You can see more about the release in the ",[2006,4688,4691],{"href":4689,"rel":4690},"https://github.com/unjs/jiti/releases/tag/v2.0.0",[2010],"jiti v2 release notes",", but one of the most important pieces is native node esm import (where possible), which should mean a faster start. ✨",[1155,4694,4696],{"id":4695},"shared-folder-for-code-and-types-shared-with-clientserver","📂 Shared folder for code and types shared with client/server",[1143,4698,4699,4700,4703],{},"You should never import Vue app code in your nitro code (or the other way around). But this has meant a friction point when it comes to sharing types or utilities that ",[3746,4701,4702],{},"don't"," rely on the nitro/vue contexts.",[1143,4705,4706,4707,4710,4711,4716,4717,4720,4721,4723],{},"For this, we have a new ",[1220,4708,4709],{},"shared/"," folder (",[2006,4712,4715],{"href":4713,"rel":4714},"https://github.com/nuxt/nuxt/pull/28682",[2010],"#28682","). You can't import Vue or nitro code ",[3746,4718,4719],{},"into"," files in this folder, but it produces auto-imports (if you're using ",[1220,4722,2438],{},") which you can consume throughout the rest of your app.",[1143,4725,4726,4727,4730],{},"If needed you can use the new ",[1220,4728,4729],{},"#shared"," alias which points to this folder.",[1143,4732,4733,4734,4737,4738,4740,4741,4744],{},"The shared folder is alongside your ",[1220,4735,4736],{},"server/"," folder. (If you're using ",[1220,4739,2438],{},", this means it's not inside your ",[1220,4742,4743],{},"app/"," folder.)",[1155,4746,4748,4749,4752],{"id":4747},"rspack-builder","🦀 ",[1220,4750,4751],{},"rspack"," builder",[1143,4754,4755,4756,4758,4759,4761],{},"We're excited to announce a new first-class Nuxt builder for ",[1220,4757,4751],{},". It's still experimental but we've refactored the internal Nuxt virtual file system to use ",[1220,4760,4299],{}," to make this possible.",[1143,4763,4764],{},"Let us know if you like it - and feel free to raise any issues you experience with it.",[1143,4766,4767,4768,4773,4774,4777,4778,4781],{},"👉 To try it out, you can use ",[2006,4769,4772],{"href":4770,"rel":4771},"https://github.com/danielroe/nuxt-rspack-starter",[2010],"this starter"," - or just install ",[1220,4775,4776],{},"@nuxt/rspack-builder"," and set ",[1220,4779,4780],{},"builder: 'rspack'"," in your nuxt config file.",[1155,4783,4785],{"id":4784},"new-composables","✨ New composables",[1143,4787,4788,4789,4363,4791,4793,4794,4363,4799,3681],{},"We have new ",[1220,4790,504],{},[1220,4792,524],{}," composables (",[2006,4795,4798],{"href":4796,"rel":4797},"https://github.com/nuxt/nuxt/pull/27131",[2010],"#27131",[2006,4800,4803],{"href":4801,"rel":4802},"https://github.com/nuxt/nuxt/pull/29741",[2010],"#29741",[1155,4805,4807],{"id":4806},"new-module-utilities","🔧 New module utilities",[1143,4809,4810,4811,4814,4815,4820],{},"We now have a new ",[1220,4812,4813],{},"addServerTemplate"," utility (",[2006,4816,4819],{"href":4817,"rel":4818},"https://github.com/nuxt/nuxt/pull/29320",[2010],"#29320",") for adding virtual files for access inside nitro runtime routes.",[1155,4822,4824],{"id":4823},"v4-changes","🚧 v4 changes",[1143,4826,4827,4828,4830,4831,2281],{},"We've merged some changes which only take effect with ",[1220,4829,2438],{},", but which ",[2006,4832,4834],{"href":4833},"/docs/getting-started/upgrade#testing-nuxt-4","you can opt-into earlier",[2412,4836,4837,4861],{},[1855,4838,4839,4840,4843,4844,4847,4848,4851,4852,4855,4856,3681],{},"previously, if you had a component like ",[1220,4841,4842],{},"~/components/App/Header.vue"," this would be visible in your devtools as ",[1220,4845,4846],{},"\u003CHeader>",". From v4 we ensure this is ",[1220,4849,4850],{},"\u003CAppHeader>",", but it's opt-in to avoid breaking any manual ",[1220,4853,4854],{},"\u003CKeepAlive>"," you might have implemented. (",[2006,4857,4860],{"href":4858,"rel":4859},"https://github.com/nuxt/nuxt/pull/28745",[2010],"#28745",[1855,4862,4863,4864,4867,4868,4870,4871,4873,4874,4876,4877,4880,4881,4884],{},"Nuxt scans page metadata from your files, before calling ",[1220,4865,4866],{},"pages:extend",". But this has led to some confusing behaviour, as pages added at this point do not end up having their page metadata respected. So we now do not scan metadata before calling ",[1220,4869,4866],{},". Instead, we have a new ",[1220,4872,3848],{}," hook, which is called after ",[1220,4875,4866],{},", after all pages have been augmented with their metadata. I'd recommend opting into this by setting ",[1220,4878,4879],{},"experimental.scanPageMeta"," to ",[1220,4882,4883],{},"after-resolve",", as it solves a number of bugs.",[1147,4886,4888],{"id":4887},"️-roadmap-to-v315","🗺️ Roadmap to v3.15",[1143,4890,4891],{},"They didn't quite make it in time for v3.14 but for the next minor release you can expect (among other things):",[1852,4893,4894,4902,4910],{},[1855,4895,4896,4897,2541],{},"auto-imported directives from modules (",[2006,4898,4901],{"href":4899,"rel":4900},"https://github.com/nuxt/nuxt/pull/29203",[2010],"#29203",[1855,4903,4904,4905,2541],{},"'isolated' page renders (",[2006,4906,4909],{"href":4907,"rel":4908},"https://github.com/nuxt/nuxt/pull/29366",[2010],"#29366",[1855,4911,4912,4913,2541],{},"delayed hydration (",[2006,4914,2586],{"href":2584,"rel":4915},[2010],[1147,4917,3580],{"id":3579},[1143,4919,3583],{},[1213,4921,4922],{"className":3586,"code":4006,"language":3588,"meta":1218,"style":1218},[1220,4923,4924],{"__ignoreMap":1218},[1223,4925,4926,4928,4930,4932],{"class":1225,"line":1226},[1223,4927,2037],{"class":2036},[1223,4929,2040],{"class":1254},[1223,4931,3599],{"class":1254},[1223,4933,4019],{"class":1254},[1143,4935,4022],{},[1147,4937,4938],{"id":3608},"Full Release Notes",[3611,4940,4942],{"color":3613,"icon":3614,"target":3615,"to":4941},"https://github.com/nuxt/nuxt/releases/tag/v3.14.0",[1143,4943,3619,4944,2281],{},[1220,4945,4946],{},"v3.14.0",[1143,4948,4949],{},"A huge thank you to everyone who's been a part of this release. We have exciting things in store with our next releases! ❤️",[1143,4951,4037],{},[2160,4953,4954],{},"html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}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);}",{"title":1218,"searchDepth":1233,"depth":1233,"links":4956},[4957,4959,4960,4962,4963,4964,4965,4966,4967],{"id":4676,"depth":1263,"text":4958},"⚡️ Faster starts powered by jiti",{"id":4695,"depth":1263,"text":4696},{"id":4747,"depth":1263,"text":4961},"🦀 rspack builder",{"id":4784,"depth":1263,"text":4785},{"id":4806,"depth":1263,"text":4807},{"id":4823,"depth":1263,"text":4824},{"id":4887,"depth":1233,"text":4888},{"id":3579,"depth":1233,"text":3580},{"id":3608,"depth":1233,"text":4938},"2024-11-04T10:00:00.000Z","Nuxt 3.14 is out - with a new rspack builder, shared folder, and performance enhancements!","/assets/blog/v3.14.png",{},"/blog/v3-14",{"title":4662,"description":4969},"blog/27.v3-14","JzOgClkNOS",{"id":4977,"title":4978,"authors":4979,"body":4982,"category":2176,"date":5681,"description":5682,"draft":108,"extension":1954,"image":5683,"meta":5684,"navigation":108,"path":5685,"seo":5686,"stem":5687,"tags":6,"__hash__":5688},"blog/blog/27.v3-13.md","Nuxt 3.13",[4980],{"name":2190,"avatar":4981,"to":2193},{"src":2192},{"type":1140,"value":4983,"toc":5670},[4984,4988,4991,4994,5056,5073,5081,5085,5088,5095,5099,5110,5112,5224,5227,5229,5330,5334,5344,5352,5358,5416,5420,5442,5446,5460,5464,5492,5502,5509,5526,5632,5634,5636,5650,5652,5654,5662,5665,5667],[1147,4985,4987],{"id":4986},"️-route-groups","🏘️ Route Groups",[1143,4989,4990],{},"We now support naming directories with parentheses/brackets to organise your routes without affecting the path.",[1143,4992,4993],{},"For example:",[1213,4995,4998],{"className":2022,"code":4996,"filename":4997,"language":2024,"meta":1218,"style":1218},"-| pages/\n---| index.vue\n---| (marketing)/\n-----| about.vue\n-----| contact.vue\n","Directory structure",[1220,4999,5000,5011,5021,5037,5047],{"__ignoreMap":1218},[1223,5001,5002,5005,5008],{"class":1225,"line":1226},[1223,5003,5004],{"class":2036},"-",[1223,5006,5007],{"class":1236},"|",[1223,5009,5010],{"class":2036}," pages/\n",[1223,5012,5013,5016,5018],{"class":1225,"line":1233},[1223,5014,5015],{"class":2036},"---",[1223,5017,5007],{"class":1236},[1223,5019,5020],{"class":2036}," index.vue\n",[1223,5022,5023,5025,5027,5029,5032,5034],{"class":1225,"line":1263},[1223,5024,5015],{"class":2036},[1223,5026,5007],{"class":1236},[1223,5028,3114],{"class":1236},[1223,5030,5031],{"class":2036},"marketing",[1223,5033,2541],{"class":1236},[1223,5035,5036],{"class":2036},"/\n",[1223,5038,5039,5042,5044],{"class":1225,"line":1296},[1223,5040,5041],{"class":2036},"-----",[1223,5043,5007],{"class":1236},[1223,5045,5046],{"class":2036}," about.vue\n",[1223,5048,5049,5051,5053],{"class":1225,"line":1325},[1223,5050,5041],{"class":2036},[1223,5052,5007],{"class":1236},[1223,5054,5055],{"class":2036}," contact.vue\n",[1143,5057,5058,5059,5062,5063,4363,5066,5069,5070,5072],{},"This will produce ",[1220,5060,5061],{},"/",", ",[1220,5064,5065],{},"/about",[1220,5067,5068],{},"/contact"," pages in your app. The ",[1220,5071,5031],{}," group is ignored for purposes of your URL structure.",[1143,5074,5075,5076,2281],{},"Read more in ",[2006,5077,5080],{"href":5078,"rel":5079},"https://github.com/nuxt/nuxt/pull/28276",[2010],"the original PR",[1147,5082,5084],{"id":5083},"️-islands-and-head-metadata","🏝️ Islands and Head Metadata",[1143,5086,5087],{},"It's now possible for server component islands to manipulate the head, such as by adding SEO metadata when rendering.",[1143,5089,5075,5090,2281],{},[2006,5091,5094],{"href":5092,"rel":5093},"https://github.com/nuxt/nuxt/pull/27987",[2010],"#27987",[1147,5096,5098],{"id":5097},"custom-prefetch-triggers","🪝 Custom Prefetch Triggers",[1143,5100,5101,5102,3114,5105,3681],{},"We now support custom prefetch triggers for ",[1220,5103,5104],{},"NuxtLink",[2006,5106,5109],{"href":5107,"rel":5108},"https://github.com/nuxt/nuxt/pull/27846",[2010],"#27846",[1143,5111,4993],{},[1213,5113,5116],{"className":2595,"code":5114,"filename":5115,"language":2597,"meta":1218,"style":1218},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003CNuxtLink prefetch-on=\"interaction\">\n      This will prefetch when hovered or when it gains focus\n    \u003C/NuxtLink>\n    \u003C!-- note that you probably don't want both enabled! -->\n    \u003CNuxtLink :prefetch-on=\"{ visibility: true, interaction: true }\">\n      This will prefetch when hovered/focus - or when it becomes visible\n    \u003C/NuxtLink>\n  \u003C/div>\n\u003C/template>\n","pages/index.vue",[1220,5117,5118,5126,5134,5155,5160,5169,5174,5194,5199,5207,5216],{"__ignoreMap":1218},[1223,5119,5120,5122,5124],{"class":1225,"line":1226},[1223,5121,1237],{"class":1236},[1223,5123,2606],{"class":1240},[1223,5125,1260],{"class":1236},[1223,5127,5128,5130,5132],{"class":1225,"line":1233},[1223,5129,1266],{"class":1236},[1223,5131,1241],{"class":1240},[1223,5133,1260],{"class":1236},[1223,5135,5136,5139,5141,5144,5146,5148,5151,5153],{"class":1225,"line":1263},[1223,5137,5138],{"class":1236},"    \u003C",[1223,5140,5104],{"class":1240},[1223,5142,5143],{"class":1244}," prefetch-on",[1223,5145,1248],{"class":1236},[1223,5147,1251],{"class":1236},[1223,5149,5150],{"class":1254},"interaction",[1223,5152,1251],{"class":1236},[1223,5154,1260],{"class":1236},[1223,5156,5157],{"class":1225,"line":1296},[1223,5158,5159],{"class":1285},"      This will prefetch when hovered or when it gains focus\n",[1223,5161,5162,5165,5167],{"class":1225,"line":1325},[1223,5163,5164],{"class":1236},"    \u003C/",[1223,5166,5104],{"class":1240},[1223,5168,1260],{"class":1236},[1223,5170,5171],{"class":1225,"line":1355},[1223,5172,5173],{"class":1229},"    \u003C!-- note that you probably don't want both enabled! -->\n",[1223,5175,5176,5178,5180,5183,5185,5187,5190,5192],{"class":1225,"line":1771},[1223,5177,5138],{"class":1236},[1223,5179,5104],{"class":1240},[1223,5181,5182],{"class":1244}," :prefetch-on",[1223,5184,1248],{"class":1236},[1223,5186,1251],{"class":1236},[1223,5188,5189],{"class":1254},"{ visibility: true, interaction: true }",[1223,5191,1251],{"class":1236},[1223,5193,1260],{"class":1236},[1223,5195,5196],{"class":1225,"line":1783},[1223,5197,5198],{"class":1285},"      This will prefetch when hovered/focus - or when it becomes visible\n",[1223,5200,5201,5203,5205],{"class":1225,"line":1792},[1223,5202,5164],{"class":1236},[1223,5204,5104],{"class":1240},[1223,5206,1260],{"class":1236},[1223,5208,5209,5212,5214],{"class":1225,"line":1798},[1223,5210,5211],{"class":1236},"  \u003C/",[1223,5213,1241],{"class":1240},[1223,5215,1260],{"class":1236},[1223,5217,5218,5220,5222],{"class":1225,"line":1975},[1223,5219,1289],{"class":1236},[1223,5221,2606],{"class":1240},[1223,5223,1260],{"class":1236},[1143,5225,5226],{},"It's also possible to enable/disable these globally for your app and override them per link.",[1143,5228,4993],{},[1213,5230,5232],{"className":1669,"code":5231,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  experimental: {\n    defaults: {\n      nuxtLink: {\n        prefetch: true,\n        prefetchOn: { visibility: false, interaction: true }\n      }\n    }\n  }\n})\n",[1220,5233,5234,5246,5254,5263,5272,5283,5312,5316,5320,5324],{"__ignoreMap":1218},[1223,5235,5236,5238,5240,5242,5244],{"class":1225,"line":1226},[1223,5237,1745],{"class":1679},[1223,5239,1748],{"class":1679},[1223,5241,2820],{"class":1751},[1223,5243,1754],{"class":1285},[1223,5245,1757],{"class":1236},[1223,5247,5248,5250,5252],{"class":1225,"line":1233},[1223,5249,3074],{"class":1240},[1223,5251,1765],{"class":1236},[1223,5253,1891],{"class":1236},[1223,5255,5256,5259,5261],{"class":1225,"line":1263},[1223,5257,5258],{"class":1240},"    defaults",[1223,5260,1765],{"class":1236},[1223,5262,1891],{"class":1236},[1223,5264,5265,5268,5270],{"class":1225,"line":1296},[1223,5266,5267],{"class":1240},"      nuxtLink",[1223,5269,1765],{"class":1236},[1223,5271,1891],{"class":1236},[1223,5273,5274,5277,5279,5281],{"class":1225,"line":1325},[1223,5275,5276],{"class":1240},"        prefetch",[1223,5278,1765],{"class":1236},[1223,5280,2929],{"class":2928},[1223,5282,1780],{"class":1236},[1223,5284,5285,5288,5290,5292,5295,5297,5300,5302,5305,5307,5309],{"class":1225,"line":1355},[1223,5286,5287],{"class":1240},"        prefetchOn",[1223,5289,1765],{"class":1236},[1223,5291,1683],{"class":1236},[1223,5293,5294],{"class":1240}," visibility",[1223,5296,1765],{"class":1236},[1223,5298,5299],{"class":2928}," false",[1223,5301,2333],{"class":1236},[1223,5303,5304],{"class":1240}," interaction",[1223,5306,1765],{"class":1236},[1223,5308,2929],{"class":2928},[1223,5310,5311],{"class":1236}," }\n",[1223,5313,5314],{"class":1225,"line":1771},[1223,5315,1978],{"class":1236},[1223,5317,5318],{"class":1225,"line":1783},[1223,5319,1984],{"class":1236},[1223,5321,5322],{"class":1225,"line":1792},[1223,5323,1990],{"class":1236},[1223,5325,5326,5328],{"class":1225,"line":1798},[1223,5327,1801],{"class":1236},[1223,5329,1804],{"class":1285},[1147,5331,5333],{"id":5332},"️-better-server-source-maps","🗺️  Better Server Source Maps",[1143,5335,5336,5337,5340,5341,3681],{},"When running with ",[1220,5338,5339],{},"node --enable-source-maps",", you may have noticed that the source maps for the Vue files in your server build pointed to the Vite build output (something like ",[1220,5342,5343],{},".nuxt/dist/server/_nuxt/index-O15BBwZ3.js",[1143,5345,5346,5347,3681],{},"Now, even after your Nitro build, your server source maps will reference your original source files (",[2006,5348,5351],{"href":5349,"rel":5350},"https://github.com/nuxt/nuxt/pull/28521",[2010],"#28521",[1143,5353,5354,5355,1765],{},"Note that one of the easiest ways of improving your build performance is to turn off source maps if you aren't using them, which you can do easily in your ",[1220,5356,5357],{},"nuxt.config",[1213,5359,5361],{"className":1669,"code":5360,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  sourcemap: {\n    server: false,\n    client: true,\n  },\n})\n",[1220,5362,5363,5375,5384,5395,5406,5410],{"__ignoreMap":1218},[1223,5364,5365,5367,5369,5371,5373],{"class":1225,"line":1226},[1223,5366,1745],{"class":1679},[1223,5368,1748],{"class":1679},[1223,5370,2820],{"class":1751},[1223,5372,1754],{"class":1285},[1223,5374,1757],{"class":1236},[1223,5376,5377,5380,5382],{"class":1225,"line":1233},[1223,5378,5379],{"class":1240},"  sourcemap",[1223,5381,1765],{"class":1236},[1223,5383,1891],{"class":1236},[1223,5385,5386,5389,5391,5393],{"class":1225,"line":1263},[1223,5387,5388],{"class":1240},"    server",[1223,5390,1765],{"class":1236},[1223,5392,5299],{"class":2928},[1223,5394,1780],{"class":1236},[1223,5396,5397,5400,5402,5404],{"class":1225,"line":1296},[1223,5398,5399],{"class":1240},"    client",[1223,5401,1765],{"class":1236},[1223,5403,2929],{"class":2928},[1223,5405,1780],{"class":1236},[1223,5407,5408],{"class":1225,"line":1325},[1223,5409,3312],{"class":1236},[1223,5411,5412,5414],{"class":1225,"line":1355},[1223,5413,1801],{"class":1236},[1223,5415,1804],{"class":1285},[1147,5417,5419],{"id":5418},"new-features-for-module-authors","🎁 New Features for Module Authors",[1143,5421,5422,5423,5426,5427,5432,5433,5436,5437,3681],{},"In the run-up to Nuxt v4, we're working on adding some key functionality for module authors, including a new ",[1220,5424,5425],{},"isNuxtMajorVersion"," utility where required (",[2006,5428,5431],{"href":5429,"rel":5430},"https://github.com/nuxt/nuxt/pull/27579",[2010],"#27579",") and better inferred typing for merged module options using the new ",[1220,5434,5435],{},"defineNuxtModule().with()"," method (",[2006,5438,5441],{"href":5439,"rel":5440},"https://github.com/nuxt/nuxt/pull/27520",[2010],"#27520",[1147,5443,5445],{"id":5444},"improved-dev-warnings","✨ Improved Dev Warnings",[1143,5447,5448,5449,5454,5455,3681],{},"We no longer warn when using data fetching composables in middleware (",[2006,5450,5453],{"href":5451,"rel":5452},"https://github.com/nuxt/nuxt/pull/28604",[2010],"#28604",") and we warn when user components' names begin with Lazy (",[2006,5456,5459],{"href":5457,"rel":5458},"https://github.com/nuxt/nuxt/pull/27838",[2010],"#27838",[1147,5461,5463],{"id":5462},"vue-typescript-changes","🚨 Vue TypeScript Changes",[1143,5465,5466,5467,5470,5471,5473,5474,5476,5477,5062,5482,4363,5487,3681],{},"For a while, in the Vue ecosystem, we've been augmenting ",[1220,5468,5469],{},"@vue/runtime-core"," to add custom properties and more to ",[1220,5472,2597],{},". However, this inadvertently breaks the types for projects that augment ",[1220,5475,2597],{}," - which is now the officially recommended and documented way to augment these interfaces (for example, ",[2006,5478,5481],{"href":5479,"rel":5480},"https://vuejs.org/api/utility-types.html#componentcustomproperties",[2010],"ComponentCustomProperties",[2006,5483,5486],{"href":5484,"rel":5485},"https://vuejs.org/guide/extras/web-components.html#web-components-and-typescript",[2010],"GlobalComponents",[2006,5488,5491],{"href":5489,"rel":5490},"https://vuejs.org/guide/typescript/options-api.html#augmenting-global-properties",[2010],"so on",[1143,5493,5494,5495,5498,5499,5501],{},"This means ",[3746,5496,5497],{},"all"," libraries must update their code (or it will break the types of libraries that augment ",[1220,5500,2597],{}," instead).",[1143,5503,5504,5505,5508],{},"We've updated our types in Nuxt along these lines but you may experience issues with the latest ",[1220,5506,5507],{},"vue-router"," when used with libraries which haven't yet done so.",[1143,5510,5511,5512,5515,5516,4880,5521,2887],{},"Please create an issue with a reproduction - I'll happily help create a PR to resolve in the upstream library in question. Or you may be able to work around the issue by creating a ",[1220,5513,5514],{},"declarations.d.ts"," in the root of your project with the following code (",[2006,5517,5520],{"href":5518,"rel":5519},"https://github.com/nuxt/nuxt/pull/28542#issuecomment-2293282891",[2010],"credit",[2006,5522,5525],{"href":5523,"rel":5524},"https://github.com/BobbieGoede",[2010],"@BobbieGoede",[1213,5527,5529],{"className":1669,"code":5528,"filename":5514,"language":1672,"meta":1218,"style":1218},"import type {\n  ComponentCustomOptions as _ComponentCustomOptions,\n  ComponentCustomProperties as _ComponentCustomProperties,\n} from 'vue';\n\ndeclare module '@vue/runtime-core' {\n  interface ComponentCustomProperties extends _ComponentCustomProperties {}\n  interface ComponentCustomOptions extends _ComponentCustomOptions {}\n}\n",[1220,5530,5531,5540,5553,5565,5580,5584,5599,5615,5628],{"__ignoreMap":1218},[1223,5532,5533,5535,5538],{"class":1225,"line":1226},[1223,5534,1680],{"class":1679},[1223,5536,5537],{"class":1679}," type",[1223,5539,1891],{"class":1236},[1223,5541,5542,5545,5548,5551],{"class":1225,"line":1233},[1223,5543,5544],{"class":1285},"  ComponentCustomOptions",[1223,5546,5547],{"class":1679}," as",[1223,5549,5550],{"class":1285}," _ComponentCustomOptions",[1223,5552,1780],{"class":1236},[1223,5554,5555,5558,5560,5563],{"class":1225,"line":1263},[1223,5556,5557],{"class":1285},"  ComponentCustomProperties",[1223,5559,5547],{"class":1679},[1223,5561,5562],{"class":1285}," _ComponentCustomProperties",[1223,5564,1780],{"class":1236},[1223,5566,5567,5569,5571,5573,5575,5577],{"class":1225,"line":1296},[1223,5568,1801],{"class":1236},[1223,5570,1692],{"class":1679},[1223,5572,1695],{"class":1236},[1223,5574,2597],{"class":1254},[1223,5576,1957],{"class":1236},[1223,5578,5579],{"class":1236},";\n",[1223,5581,5582],{"class":1225,"line":1325},[1223,5583,1740],{"emptyLinePlaceholder":1739},[1223,5585,5586,5589,5591,5593,5595,5597],{"class":1225,"line":1355},[1223,5587,5588],{"class":1244},"declare",[1223,5590,4557],{"class":1244},[1223,5592,1695],{"class":1236},[1223,5594,5469],{"class":1254},[1223,5596,1957],{"class":1236},[1223,5598,1891],{"class":1236},[1223,5600,5601,5604,5607,5610,5612],{"class":1225,"line":1771},[1223,5602,5603],{"class":1244},"  interface",[1223,5605,5606],{"class":2036}," ComponentCustomProperties",[1223,5608,5609],{"class":1244}," extends",[1223,5611,5562],{"class":2036},[1223,5613,5614],{"class":1236}," {}\n",[1223,5616,5617,5619,5622,5624,5626],{"class":1225,"line":1783},[1223,5618,5603],{"class":1244},[1223,5620,5621],{"class":2036}," ComponentCustomOptions",[1223,5623,5609],{"class":1244},[1223,5625,5550],{"class":2036},[1223,5627,5614],{"class":1236},[1223,5629,5630],{"class":1225,"line":1792},[1223,5631,2407],{"class":1236},[1147,5633,3580],{"id":3579},[1143,5635,3583],{},[1213,5637,5638],{"className":3586,"code":4006,"language":3588,"meta":1218,"style":1218},[1220,5639,5640],{"__ignoreMap":1218},[1223,5641,5642,5644,5646,5648],{"class":1225,"line":1226},[1223,5643,2037],{"class":2036},[1223,5645,2040],{"class":1254},[1223,5647,3599],{"class":1254},[1223,5649,4019],{"class":1254},[1143,5651,4022],{},[1147,5653,4938],{"id":3608},[3611,5655,5657],{"color":3613,"icon":3614,"target":3615,"to":5656},"https://github.com/nuxt/nuxt/releases/tag/v3.13.0",[1143,5658,3619,5659,2281],{},[1220,5660,5661],{},"v3.13.0",[1143,5663,5664],{},"A huge thank you to everyone who's been a part of this release - you are the ones who make Nuxt possible. ❤️",[1143,5666,4037],{},[2160,5668,5669],{},"html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}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 .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .svXlt, html code.shiki .svXlt{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .sagxc, html code.shiki .sagxc{--shiki-light:#FF5370;--shiki-default:#FF5370;--shiki-dark:#FF9CAC}",{"title":1218,"searchDepth":1233,"depth":1233,"links":5671},[5672,5673,5674,5675,5676,5677,5678,5679,5680],{"id":4986,"depth":1233,"text":4987},{"id":5083,"depth":1233,"text":5084},{"id":5097,"depth":1233,"text":5098},{"id":5332,"depth":1233,"text":5333},{"id":5418,"depth":1233,"text":5419},{"id":5444,"depth":1233,"text":5445},{"id":5462,"depth":1233,"text":5463},{"id":3579,"depth":1233,"text":3580},{"id":3608,"depth":1233,"text":4938},"2024-08-22T10:00:00.000Z","Nuxt 3.13 is out - porting back some of the new features we're building for Nuxt 4!","/assets/blog/v3.13.png",{},"/blog/v3-13",{"title":4978,"description":5682},"blog/27.v3-13","QbyR1ctD3h",{"id":5690,"title":1064,"authors":5691,"body":5698,"category":2176,"date":7710,"description":7711,"draft":108,"extension":1954,"image":5723,"meta":7712,"navigation":1739,"path":1065,"seo":7713,"stem":1066,"tags":6,"__hash__":7714},"blog/blog/26.nuxt-scripts.md",[5692],{"name":5693,"avatar":5694,"to":5696,"twitter":5697},"Harlan Wilton",{"src":5695},"https://github.com/harlan-zw.png","https://github.com/harlan-zw","harlan_zw",{"type":1140,"value":5699,"toc":7691},[5700,5714,5717,5724,5728,5737,5746,5760,5763,5767,5780,5789,5792,5795,5799,5810,5815,5868,5871,5874,5885,6368,6372,6375,6391,6411,6423,6431,6440,6443,6446,6453,6457,6461,6471,6477,6504,6507,6515,6784,6788,6796,6803,6810,6819,6881,6885,6909,6918,6921,7345,7349,7362,7365,7383,7512,7516,7519,7533,7536,7575,7582,7586,7589,7596,7599,7629,7632,7635,7644,7648,7678,7681,7688],[1143,5701,5702,5703,5708,5709,2281],{},"The Nuxt team, in collaboration with the ",[2006,5704,5707],{"href":5705,"rel":5706},"https://developer.chrome.com/aurora",[2010],"Chrome Aurora"," team at Google, is excited to announce the public beta release of ",[2006,5710,5713],{"href":5711,"rel":5712},"https://scripts.nuxt.com",[2010],"Nuxt Scripts",[1143,5715,5716],{},"Nuxt Scripts is a better way to work with third-party scripts, providing improved performance, privacy, security, and developer experience.",[1143,5718,5719],{},[2243,5720],{"alt":5721,"className":5722,"src":5723},"Nuxt Scripts Banner",[2247,2248,2249,2250],"/assets/blog/nuxt-scripts/banner.png",[1147,5725,5727],{"id":5726},"getting-to-nuxt-scripts","Getting to Nuxt Scripts",[1143,5729,5730,5731,5736],{},"Over a year ago, Daniel published the initial ",[2006,5732,5735],{"href":5733,"rel":5734},"https://github.com/nuxt/nuxt/discussions/22016",[2010],"Nuxt Scripts RFC",". The RFC proposed a module that would \"allow third-party scripts to be managed and optimized, following best practices for performant and compliant websites\".",[1143,5738,5739,5740,5745],{},"Having ",[2006,5741,5744],{"href":5742,"rel":5743},"https://github.com/harlan-zw/nuxt-delay-hydration",[2010],"personal experience"," with solving performance issues related to third-party scripts, I knew how difficult these performance optimizations could be. Nonetheless, I was keen to tackle the problem and took over the project.",[1143,5747,5748,5749,5754,5755,2281],{},"With the RFC as the seed of the idea, I started prototyping what it could ",[2006,5750,5753],{"href":5751,"rel":5752},"https://github.com/nuxt/nuxt/discussions/22016#discussioncomment-6527001",[2010],"look like"," using ",[2006,5756,5759],{"href":5757,"rel":5758},"https://unhead.unjs.io/",[2010],"Unhead",[1143,5761,5762],{},"Thinking about what I wanted to build exactly, I found that the real issue wasn't just how to load \"optimized\" third-party scripts but how to make working with third-party scripts a better experience overall.",[1147,5764,5766],{"id":5765},"why-build-a-third-party-script-module","Why Build a Third-Party Script Module?",[1143,5768,5769,5774,5775,2281],{},[2006,5770,5773],{"href":5771,"rel":5772},"https://almanac.httparchive.org/en/2022/third-parties#prevalence",[2010],"94% of sites use at least one third-party provider",", with the average site having ",[2006,5776,5779],{"href":5777,"rel":5778},"https://docs.google.com/spreadsheets/d/1YqoRRsyiNsrEabVLu2nRU98JIG_0zLLuoQhC2nX8xbM/edit?gid=1428106498#gid=1428106498",[2010],"five third-party providers",[1143,5781,5782,5783,5788],{},"We know that third-party scripts aren't perfect; they ",[2006,5784,5787],{"href":5785,"rel":5786},"https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript#",[2010],"slow down the web",", cause privacy and security issues, and are a pain to work with.",[1143,5790,5791],{},"However, they are fundamentally useful and aren't going anywhere soon.",[1143,5793,5794],{},"By exploring the issues with third-party scripts, we can see where improvements can be made.",[1155,5796,5798],{"id":5797},"developer-experience-a-full-stack-headache","😒 Developer Experience: A Full-Stack Headache",[1143,5800,5801,5802,5805,5806,5809],{},"Let's walk through adding a third-party script to your Nuxt app using a fictional ",[1220,5803,5804],{},"tracker.js"," script that adds a ",[1220,5807,5808],{},"track"," function to the window.",[1143,5811,5812,5813,2281],{},"We start by loading the script using ",[1220,5814,448],{},[1213,5816,5818],{"className":1669,"code":5817,"language":1672,"meta":1218,"style":1218},"useHead({ script: [{ src: '/tracker.js', defer: true }] })\n",[1220,5819,5820],{"__ignoreMap":1218},[1223,5821,5822,5824,5826,5829,5832,5834,5836,5838,5841,5843,5845,5848,5850,5852,5855,5857,5859,5861,5864,5866],{"class":1225,"line":1226},[1223,5823,448],{"class":1751},[1223,5825,1754],{"class":1285},[1223,5827,5828],{"class":1236},"{",[1223,5830,5831],{"class":1240}," script",[1223,5833,1765],{"class":1236},[1223,5835,2848],{"class":1285},[1223,5837,5828],{"class":1236},[1223,5839,5840],{"class":1240}," src",[1223,5842,1765],{"class":1236},[1223,5844,1695],{"class":1236},[1223,5846,5847],{"class":1254},"/tracker.js",[1223,5849,1957],{"class":1236},[1223,5851,2333],{"class":1236},[1223,5853,5854],{"class":1240}," defer",[1223,5856,1765],{"class":1236},[1223,5858,2929],{"class":2928},[1223,5860,1689],{"class":1236},[1223,5862,5863],{"class":1285},"] ",[1223,5865,1801],{"class":1236},[1223,5867,1804],{"class":1285},[1143,5869,5870],{},"However, let's now try to get the script functionality working in our app.",[1143,5872,5873],{},"The following steps are common when working with third-party scripts in Nuxt:",[1852,5875,5876,5879,5882],{},[1855,5877,5878],{},"Everything has to be wrapped for SSR safety.",[1855,5880,5881],{},"Flaky checks for if the script has loaded.",[1855,5883,5884],{},"Augmenting the window object for types.",[2054,5886,5887,5958,6052,6185],{},[1213,5888,5891],{"className":2595,"code":5889,"filename":5890,"language":2597,"meta":1218,"style":1218},"\u003Cscript setup>\n// ❌ Oops, window is not defined! \n// 💡 The window can't be directly accessed if we use SSR in Nuxt.\n// 👉 We need to make this SSR safe\nwindow.track('page_view', useRoute().path)\n\u003C/script>\n","1: SSR Safety",[1220,5892,5893,5905,5910,5915,5920,5950],{"__ignoreMap":1218},[1223,5894,5895,5897,5900,5903],{"class":1225,"line":1226},[1223,5896,1237],{"class":1236},[1223,5898,5899],{"class":1240},"script",[1223,5901,5902],{"class":1244}," setup",[1223,5904,1260],{"class":1236},[1223,5906,5907],{"class":1225,"line":1233},[1223,5908,5909],{"class":1229},"// ❌ Oops, window is not defined! \n",[1223,5911,5912],{"class":1225,"line":1263},[1223,5913,5914],{"class":1229},"// 💡 The window can't be directly accessed if we use SSR in Nuxt.\n",[1223,5916,5917],{"class":1225,"line":1296},[1223,5918,5919],{"class":1229},"// 👉 We need to make this SSR safe\n",[1223,5921,5922,5925,5927,5929,5931,5933,5936,5938,5940,5943,5945,5947],{"class":1225,"line":1325},[1223,5923,5924],{"class":1285},"window",[1223,5926,2281],{"class":1236},[1223,5928,5808],{"class":1751},[1223,5930,1754],{"class":1285},[1223,5932,1957],{"class":1236},[1223,5934,5935],{"class":1254},"page_view",[1223,5937,1957],{"class":1236},[1223,5939,2333],{"class":1236},[1223,5941,5942],{"class":1751}," useRoute",[1223,5944,1777],{"class":1285},[1223,5946,2281],{"class":1236},[1223,5948,5949],{"class":1285},"path)\n",[1223,5951,5952,5954,5956],{"class":1225,"line":1355},[1223,5953,1289],{"class":1236},[1223,5955,5899],{"class":1240},[1223,5957,1260],{"class":1236},[1213,5959,5962],{"className":2595,"code":5960,"filename":5961,"language":2597,"meta":1218,"style":1218},"\u003Cscript setup>\nif (import.meta.client) {\n  // ❌ Oops, the script hasn't finished loading yet!\n  // 💡 A `defer` script may not be available while our Nuxt app hydrates.\n  // 👉 We need to wait for the script to be loaded\n  window.track('page_view', useRoute().path)\n}\n\u003C/script>\n","2: Script Timing",[1220,5963,5964,5974,5995,6000,6005,6010,6040,6044],{"__ignoreMap":1218},[1223,5965,5966,5968,5970,5972],{"class":1225,"line":1226},[1223,5967,1237],{"class":1236},[1223,5969,5899],{"class":1240},[1223,5971,5902],{"class":1244},[1223,5973,1260],{"class":1236},[1223,5975,5976,5979,5981,5983,5985,5988,5990,5993],{"class":1225,"line":1233},[1223,5977,5978],{"class":1679},"if",[1223,5980,3114],{"class":1285},[1223,5982,1680],{"class":1679},[1223,5984,2281],{"class":1236},[1223,5986,5987],{"class":1285},"meta",[1223,5989,2281],{"class":1236},[1223,5991,5992],{"class":1285},"client) ",[1223,5994,1757],{"class":1236},[1223,5996,5997],{"class":1225,"line":1263},[1223,5998,5999],{"class":1229},"  // ❌ Oops, the script hasn't finished loading yet!\n",[1223,6001,6002],{"class":1225,"line":1296},[1223,6003,6004],{"class":1229},"  // 💡 A `defer` script may not be available while our Nuxt app hydrates.\n",[1223,6006,6007],{"class":1225,"line":1325},[1223,6008,6009],{"class":1229},"  // 👉 We need to wait for the script to be loaded\n",[1223,6011,6012,6015,6017,6019,6021,6023,6025,6027,6029,6031,6033,6035,6038],{"class":1225,"line":1355},[1223,6013,6014],{"class":1285},"  window",[1223,6016,2281],{"class":1236},[1223,6018,5808],{"class":1751},[1223,6020,1754],{"class":1240},[1223,6022,1957],{"class":1236},[1223,6024,5935],{"class":1254},[1223,6026,1957],{"class":1236},[1223,6028,2333],{"class":1236},[1223,6030,5942],{"class":1751},[1223,6032,1777],{"class":1240},[1223,6034,2281],{"class":1236},[1223,6036,6037],{"class":1285},"path",[1223,6039,1804],{"class":1240},[1223,6041,6042],{"class":1225,"line":1771},[1223,6043,2407],{"class":1236},[1223,6045,6046,6048,6050],{"class":1225,"line":1783},[1223,6047,1289],{"class":1236},[1223,6049,5899],{"class":1240},[1223,6051,1260],{"class":1236},[1213,6053,6056],{"className":2595,"code":6054,"filename":6055,"language":2597,"meta":1218,"style":1218},"\u003Cscript lang=\"ts\" setup>\nif (import.meta.client) {\n  useTimeoutFn(() => {\n    // ✅ It's working!\n    // ❌ Oops, types are broken.\n    // 💡 The `window` has strict types and nothing is defined yet.\n    // 👉 We need to manually augment the window\n    window.track('page_view', useRoute().path)\n  }, 1000 /* should be loaded in 1 second!? */)\n}\n\u003C/script>\n","3: Broken types",[1220,6057,6058,6079,6097,6110,6115,6120,6125,6130,6159,6173,6177],{"__ignoreMap":1218},[1223,6059,6060,6062,6064,6067,6069,6071,6073,6075,6077],{"class":1225,"line":1226},[1223,6061,1237],{"class":1236},[1223,6063,5899],{"class":1240},[1223,6065,6066],{"class":1244}," lang",[1223,6068,1248],{"class":1236},[1223,6070,1251],{"class":1236},[1223,6072,1672],{"class":1254},[1223,6074,1251],{"class":1236},[1223,6076,5902],{"class":1244},[1223,6078,1260],{"class":1236},[1223,6080,6081,6083,6085,6087,6089,6091,6093,6095],{"class":1225,"line":1233},[1223,6082,5978],{"class":1679},[1223,6084,3114],{"class":1285},[1223,6086,1680],{"class":1679},[1223,6088,2281],{"class":1236},[1223,6090,5987],{"class":1285},[1223,6092,2281],{"class":1236},[1223,6094,5992],{"class":1285},[1223,6096,1757],{"class":1236},[1223,6098,6099,6102,6104,6106,6108],{"class":1225,"line":1263},[1223,6100,6101],{"class":1751},"  useTimeoutFn",[1223,6103,1754],{"class":1240},[1223,6105,1777],{"class":1236},[1223,6107,3125],{"class":1244},[1223,6109,1891],{"class":1236},[1223,6111,6112],{"class":1225,"line":1296},[1223,6113,6114],{"class":1229},"    // ✅ It's working!\n",[1223,6116,6117],{"class":1225,"line":1325},[1223,6118,6119],{"class":1229},"    // ❌ Oops, types are broken.\n",[1223,6121,6122],{"class":1225,"line":1355},[1223,6123,6124],{"class":1229},"    // 💡 The `window` has strict types and nothing is defined yet.\n",[1223,6126,6127],{"class":1225,"line":1771},[1223,6128,6129],{"class":1229},"    // 👉 We need to manually augment the window\n",[1223,6131,6132,6135,6137,6139,6141,6143,6145,6147,6149,6151,6153,6155,6157],{"class":1225,"line":1783},[1223,6133,6134],{"class":1285},"    window",[1223,6136,2281],{"class":1236},[1223,6138,5808],{"class":1751},[1223,6140,1754],{"class":1240},[1223,6142,1957],{"class":1236},[1223,6144,5935],{"class":1254},[1223,6146,1957],{"class":1236},[1223,6148,2333],{"class":1236},[1223,6150,5942],{"class":1751},[1223,6152,1777],{"class":1240},[1223,6154,2281],{"class":1236},[1223,6156,6037],{"class":1285},[1223,6158,1804],{"class":1240},[1223,6160,6161,6164,6168,6171],{"class":1225,"line":1792},[1223,6162,6163],{"class":1236},"  },",[1223,6165,6167],{"class":6166},"sV9sa"," 1000",[1223,6169,6170],{"class":1229}," /* should be loaded in 1 second!? */",[1223,6172,1804],{"class":1240},[1223,6174,6175],{"class":1225,"line":1798},[1223,6176,2407],{"class":1236},[1223,6178,6179,6181,6183],{"class":1225,"line":1975},[1223,6180,1289],{"class":1236},[1223,6182,5899],{"class":1240},[1223,6184,1260],{"class":1236},[1213,6186,6189],{"className":2595,"code":6187,"filename":6188,"language":2597,"meta":1218,"style":1218},"\u003Cscript lang=\"ts\" setup>\ndeclare global {\n  interface Window {\n    track: (e: string, p: string) => void\n  }\n}\nif (import.meta.client) {\n  useTimeoutFn(() => {\n    // ✅ It's working and types are valid! \n    // ❌ Oops, ad-blockers, GDPR and duplicate scripts\n    // 💡 There's a lot of hidden complexity in third-party scripts\n    // 👉 We need a better API\n    window.track('page_view', useRoute().path)\n  }, 1000)\n}\n\u003C/script>\n","4: It works?",[1220,6190,6191,6211,6220,6229,6262,6266,6270,6288,6300,6305,6310,6315,6320,6348,6356,6360],{"__ignoreMap":1218},[1223,6192,6193,6195,6197,6199,6201,6203,6205,6207,6209],{"class":1225,"line":1226},[1223,6194,1237],{"class":1236},[1223,6196,5899],{"class":1240},[1223,6198,6066],{"class":1244},[1223,6200,1248],{"class":1236},[1223,6202,1251],{"class":1236},[1223,6204,1672],{"class":1254},[1223,6206,1251],{"class":1236},[1223,6208,5902],{"class":1244},[1223,6210,1260],{"class":1236},[1223,6212,6213,6215,6218],{"class":1225,"line":1233},[1223,6214,5588],{"class":1244},[1223,6216,6217],{"class":1285}," global ",[1223,6219,1757],{"class":1236},[1223,6221,6222,6224,6227],{"class":1225,"line":1263},[1223,6223,5603],{"class":1244},[1223,6225,6226],{"class":2036}," Window",[1223,6228,1891],{"class":1236},[1223,6230,6231,6234,6236,6238,6241,6243,6246,6248,6251,6253,6255,6257,6259],{"class":1225,"line":1296},[1223,6232,6233],{"class":1240},"    track",[1223,6235,1765],{"class":1236},[1223,6237,3114],{"class":1236},[1223,6239,6240],{"class":2329},"e",[1223,6242,1765],{"class":1236},[1223,6244,6245],{"class":2036}," string",[1223,6247,2333],{"class":1236},[1223,6249,6250],{"class":2329}," p",[1223,6252,1765],{"class":1236},[1223,6254,6245],{"class":2036},[1223,6256,2541],{"class":1236},[1223,6258,3125],{"class":1244},[1223,6260,6261],{"class":2036}," void\n",[1223,6263,6264],{"class":1225,"line":1325},[1223,6265,1990],{"class":1236},[1223,6267,6268],{"class":1225,"line":1355},[1223,6269,2407],{"class":1236},[1223,6271,6272,6274,6276,6278,6280,6282,6284,6286],{"class":1225,"line":1771},[1223,6273,5978],{"class":1679},[1223,6275,3114],{"class":1285},[1223,6277,1680],{"class":1679},[1223,6279,2281],{"class":1236},[1223,6281,5987],{"class":1285},[1223,6283,2281],{"class":1236},[1223,6285,5992],{"class":1285},[1223,6287,1757],{"class":1236},[1223,6289,6290,6292,6294,6296,6298],{"class":1225,"line":1783},[1223,6291,6101],{"class":1751},[1223,6293,1754],{"class":1240},[1223,6295,1777],{"class":1236},[1223,6297,3125],{"class":1244},[1223,6299,1891],{"class":1236},[1223,6301,6302],{"class":1225,"line":1792},[1223,6303,6304],{"class":1229},"    // ✅ It's working and types are valid! \n",[1223,6306,6307],{"class":1225,"line":1798},[1223,6308,6309],{"class":1229},"    // ❌ Oops, ad-blockers, GDPR and duplicate scripts\n",[1223,6311,6312],{"class":1225,"line":1975},[1223,6313,6314],{"class":1229},"    // 💡 There's a lot of hidden complexity in third-party scripts\n",[1223,6316,6317],{"class":1225,"line":1981},[1223,6318,6319],{"class":1229},"    // 👉 We need a better API\n",[1223,6321,6322,6324,6326,6328,6330,6332,6334,6336,6338,6340,6342,6344,6346],{"class":1225,"line":1987},[1223,6323,6134],{"class":1285},[1223,6325,2281],{"class":1236},[1223,6327,5808],{"class":1751},[1223,6329,1754],{"class":1240},[1223,6331,1957],{"class":1236},[1223,6333,5935],{"class":1254},[1223,6335,1957],{"class":1236},[1223,6337,2333],{"class":1236},[1223,6339,5942],{"class":1751},[1223,6341,1777],{"class":1240},[1223,6343,2281],{"class":1236},[1223,6345,6037],{"class":1285},[1223,6347,1804],{"class":1240},[1223,6349,6350,6352,6354],{"class":1225,"line":1993},[1223,6351,6163],{"class":1236},[1223,6353,6167],{"class":6166},[1223,6355,1804],{"class":1240},[1223,6357,6358],{"class":1225,"line":2720},[1223,6359,2407],{"class":1236},[1223,6361,6362,6364,6366],{"class":1225,"line":2742},[1223,6363,1289],{"class":1236},[1223,6365,5899],{"class":1240},[1223,6367,1260],{"class":1236},[1155,6369,6371],{"id":6370},"performance-why-cant-i-get-100-on-lighthouse","🐌 Performance: \"Why can't I get 100 on Lighthouse?\"",[1143,6373,6374],{},"For a visitor to start interacting with your Nuxt site, the app bundle needs to be downloaded and Vue needs to hydrate the app instance.",[1143,6376,6377,6378,6381,6382,6385,6386,2281],{},"Loading third-party scripts can interfere with this hydration process, even when using ",[1220,6379,6380],{},"async"," or ",[1220,6383,6384],{},"defer",". This slows down the network and blocks the main thread, leading to a degraded user experience and poor ",[2006,6387,6390],{"href":6388,"rel":6389},"https://web.dev/vitals/",[2010],"Core Web Vitals",[1143,6392,6393,6394,6399,6400,4363,6405,6410],{},"The ",[2006,6395,6398],{"href":6396,"rel":6397},"https://developer.chrome.com/docs/crux",[2010],"Chrome User Experience Report"," shows Nuxt sites with numerous third-party resources typically have poorer ",[2006,6401,6404],{"href":6402,"rel":6403},"https://web.dev/articles/inp",[2010],"Interaction to Next Paint (INP)",[2006,6406,6409],{"href":6407,"rel":6408},"https://web.dev/articles/lcp",[2010],"Largest Contentful Paint (LCP)"," scores.",[1143,6412,6413,6414,6419,6420,2281],{},"To see how third-party scripts degrade performance, we can look at the ",[2006,6415,6418],{"href":6416,"rel":6417},"https://almanac.httparchive.org/en/2022/third-parties#impact-on-performance",[2010],"Web Almanac 2022",". The report shows that the top 10 third-party scripts ",[1159,6421,6422],{},"average median blocking time is 1.4 seconds",[1155,6424,6426,6427,6430],{"id":6425},"️-privacy-security-do-no-evil","🛡️ Privacy & Security: Do ",[3746,6428,6429],{},"no"," evil?",[1143,6432,6433,6434,6439],{},"Of the top 10,000 sites, 58% of them have third-party scripts that ",[2006,6435,6438],{"href":6436,"rel":6437},"https://www3.cs.stonybrook.edu/~mikepo/papers/firstparty.www21.pdf",[2010],"exchange tracking IDs stored in external cookies",", meaning they can track users across sites even with third-party cookies disabled.",[1143,6441,6442],{},"While in many cases our hands are tied with the providers we use, we should try to minimize the amount of our end-users' data that we're leaking where possible.",[1143,6444,6445],{},"When we do take on the privacy implications, it can then be difficult to accurately convey these in our privacy policies and build the consent management required to comply with regulations such as GDPR.",[1143,6447,6448,6449,6452],{},"Security when using third-party scripts is also a concern. Third-party scripts are common attack vectors for malicious actors, most do not provide ",[1220,6450,6451],{},"integrity"," hashes for their scripts, meaning they can be compromised and inject malicious code into your app at any time.",[1147,6454,6456],{"id":6455},"what-does-nuxt-scripts-do-about-these-issues","What does Nuxt Scripts do about these issues?",[1155,6458,6460],{"id":6459},"composable-usescript","Composable: useScript",[1143,6462,6463,6464,6467,6468,2281],{},"This composable sits between the ",[1220,6465,6466],{},"\u003Cscript>"," tag and the functionality added to ",[1220,6469,6470],{},"window.{thirdPartyKey}",[1143,6472,6473,6474,6476],{},"For the ",[1220,6475,6466],{}," tag, the composable:",[1852,6478,6479,6482,6485,6495],{},[1855,6480,6481],{},"Gives full visibility into the script's loading and error states",[1855,6483,6484],{},"Loads scripts as Nuxt is hydrating the app by default, for slightly better performance.",[1855,6486,6487,6488,4363,6491,6494],{},"Restricts ",[1220,6489,6490],{},"crossorigin",[1220,6492,6493],{},"referrerpolicy"," to improve privacy and security.",[1855,6496,6497,6498,6503],{},"Provides a way to ",[2006,6499,6502],{"href":6500,"rel":6501},"https://scripts.nuxt.com/docs/guides/script-triggers",[2010],"delay loading the script"," until you need it.",[1143,6505,6506],{},"For the scripts API, it:",[1852,6508,6509,6512],{},[1855,6510,6511],{},"Provides full type-safety around the script's functions",[1855,6513,6514],{},"Adds a proxy layer allowing your app to run when the script functions in unsafe contexts (SSR, before the script is loaded, the script is blocked)",[2054,6516,6517,6727],{},[1213,6518,6521],{"className":1669,"code":6519,"filename":6520,"language":1672,"meta":1218,"style":1218},"const { proxy, onLoaded } = useScript('/hello.js', {\n  trigger: 'onNuxtReady',\n  use() {\n    return window.helloWorld\n  }\n})\n\nonLoaded(({ greeting }) => {\n  // ✅ script is loaded! Hooks into Vue lifecycle\n})\n\n// ✅ OR use the proxy API - SSR friendly, called when script is loaded\nproxy.greeting() // Hello, World!\n\ndeclare global {\n  interface Window {\n    helloWorld: {\n      greeting: () => 'Hello World!'\n    }\n  }\n}\n","hello.ts",[1220,6522,6523,6557,6572,6581,6593,6597,6603,6607,6627,6632,6638,6642,6647,6663,6667,6675,6683,6693,6712,6717,6722],{"__ignoreMap":1218},[1223,6524,6525,6527,6529,6532,6534,6537,6539,6541,6544,6546,6548,6551,6553,6555],{"class":1225,"line":1226},[1223,6526,3214],{"class":1244},[1223,6528,1683],{"class":1236},[1223,6530,6531],{"class":1285}," proxy",[1223,6533,2333],{"class":1236},[1223,6535,6536],{"class":1285}," onLoaded ",[1223,6538,1801],{"class":1236},[1223,6540,2339],{"class":1236},[1223,6542,6543],{"class":1751}," useScript",[1223,6545,1754],{"class":1285},[1223,6547,1957],{"class":1236},[1223,6549,6550],{"class":1254},"/hello.js",[1223,6552,1957],{"class":1236},[1223,6554,2333],{"class":1236},[1223,6556,1891],{"class":1236},[1223,6558,6559,6562,6564,6566,6568,6570],{"class":1225,"line":1233},[1223,6560,6561],{"class":1240},"  trigger",[1223,6563,1765],{"class":1236},[1223,6565,1695],{"class":1236},[1223,6567,607],{"class":1254},[1223,6569,1957],{"class":1236},[1223,6571,1780],{"class":1236},[1223,6573,6574,6577,6579],{"class":1225,"line":1263},[1223,6575,6576],{"class":1240},"  use",[1223,6578,1777],{"class":1236},[1223,6580,1891],{"class":1236},[1223,6582,6583,6585,6588,6590],{"class":1225,"line":1296},[1223,6584,3190],{"class":1679},[1223,6586,6587],{"class":1285}," window",[1223,6589,2281],{"class":1236},[1223,6591,6592],{"class":1285},"helloWorld\n",[1223,6594,6595],{"class":1225,"line":1325},[1223,6596,1990],{"class":1236},[1223,6598,6599,6601],{"class":1225,"line":1355},[1223,6600,1801],{"class":1236},[1223,6602,1804],{"class":1285},[1223,6604,6605],{"class":1225,"line":1771},[1223,6606,1740],{"emptyLinePlaceholder":1739},[1223,6608,6609,6612,6614,6617,6620,6623,6625],{"class":1225,"line":1783},[1223,6610,6611],{"class":1751},"onLoaded",[1223,6613,1754],{"class":1285},[1223,6615,6616],{"class":1236},"({",[1223,6618,6619],{"class":2329}," greeting",[1223,6621,6622],{"class":1236}," })",[1223,6624,3125],{"class":1244},[1223,6626,1891],{"class":1236},[1223,6628,6629],{"class":1225,"line":1792},[1223,6630,6631],{"class":1229},"  // ✅ script is loaded! Hooks into Vue lifecycle\n",[1223,6633,6634,6636],{"class":1225,"line":1798},[1223,6635,1801],{"class":1236},[1223,6637,1804],{"class":1285},[1223,6639,6640],{"class":1225,"line":1975},[1223,6641,1740],{"emptyLinePlaceholder":1739},[1223,6643,6644],{"class":1225,"line":1981},[1223,6645,6646],{"class":1229},"// ✅ OR use the proxy API - SSR friendly, called when script is loaded\n",[1223,6648,6649,6652,6654,6657,6660],{"class":1225,"line":1987},[1223,6650,6651],{"class":1285},"proxy",[1223,6653,2281],{"class":1236},[1223,6655,6656],{"class":1751},"greeting",[1223,6658,6659],{"class":1285},"() ",[1223,6661,6662],{"class":1229},"// Hello, World!\n",[1223,6664,6665],{"class":1225,"line":1993},[1223,6666,1740],{"emptyLinePlaceholder":1739},[1223,6668,6669,6671,6673],{"class":1225,"line":2720},[1223,6670,5588],{"class":1244},[1223,6672,6217],{"class":1285},[1223,6674,1757],{"class":1236},[1223,6676,6677,6679,6681],{"class":1225,"line":2742},[1223,6678,5603],{"class":1244},[1223,6680,6226],{"class":2036},[1223,6682,1891],{"class":1236},[1223,6684,6686,6689,6691],{"class":1225,"line":6685},17,[1223,6687,6688],{"class":1240},"    helloWorld",[1223,6690,1765],{"class":1236},[1223,6692,1891],{"class":1236},[1223,6694,6696,6699,6701,6703,6705,6707,6710],{"class":1225,"line":6695},18,[1223,6697,6698],{"class":1240},"      greeting",[1223,6700,1765],{"class":1236},[1223,6702,3122],{"class":1236},[1223,6704,3125],{"class":1244},[1223,6706,1695],{"class":1236},[1223,6708,6709],{"class":1254},"Hello World!",[1223,6711,1701],{"class":1236},[1223,6713,6715],{"class":1225,"line":6714},19,[1223,6716,1984],{"class":1236},[1223,6718,6720],{"class":1225,"line":6719},20,[1223,6721,1990],{"class":1236},[1223,6723,6725],{"class":1225,"line":6724},21,[1223,6726,2407],{"class":1236},[1213,6728,6731],{"className":1669,"code":6729,"filename":6730,"language":1672,"meta":1218,"style":1218},"window.helloWorld = {\n  greeting() {\n    console.log('Hello, World!')\n  }\n}\n","hello.js",[1220,6732,6733,6746,6755,6776,6780],{"__ignoreMap":1218},[1223,6734,6735,6737,6739,6742,6744],{"class":1225,"line":1226},[1223,6736,5924],{"class":1285},[1223,6738,2281],{"class":1236},[1223,6740,6741],{"class":1285},"helloWorld ",[1223,6743,1248],{"class":1236},[1223,6745,1891],{"class":1236},[1223,6747,6748,6751,6753],{"class":1225,"line":1233},[1223,6749,6750],{"class":1240},"  greeting",[1223,6752,1777],{"class":1236},[1223,6754,1891],{"class":1236},[1223,6756,6757,6760,6762,6765,6767,6769,6772,6774],{"class":1225,"line":1263},[1223,6758,6759],{"class":1285},"    console",[1223,6761,2281],{"class":1236},[1223,6763,6764],{"class":1751},"log",[1223,6766,1754],{"class":1240},[1223,6768,1957],{"class":1236},[1223,6770,6771],{"class":1254},"Hello, World!",[1223,6773,1957],{"class":1236},[1223,6775,1804],{"class":1240},[1223,6777,6778],{"class":1225,"line":1296},[1223,6779,1990],{"class":1236},[1223,6781,6782],{"class":1225,"line":1325},[1223,6783,2407],{"class":1236},[1155,6785,6787],{"id":6786},"script-registry","Script Registry",[1143,6789,6393,6790,6795],{},[2006,6791,6794],{"href":6792,"rel":6793},"https://scripts.nuxt.com/scripts",[2010],"script registry"," is a collection of first-party integrations for common third-party scripts. As of release, we support 21 scripts, with more to come.",[1143,6797,6798],{},[2243,6799],{"alt":6800,"className":6801,"src":6802},"Nuxt Scripts Registry",[2247,2248,2249,2250],"/assets/blog/nuxt-scripts/registry.png",[1143,6804,6805,6806,6809],{},"These registry scripts are fine-tuned wrappers around ",[1220,6807,6808],{},"useScript"," with full type-safety, runtime validation of the script options (dev only) and environment variable support",[1143,6811,6812,6813,6818],{},"For example, we can look at the ",[2006,6814,6817],{"href":6815,"rel":6816},"https://scripts.nuxt.com/scripts/analytics/fathom-analytics",[2010],"Fathom Analytics"," script.",[1213,6820,6822],{"className":1669,"code":6821,"language":1672,"meta":1218,"style":1218},"const { proxy } = useScriptFathomAnalytics({\n  // ✅ options are validated at runtime\n  site: undefined\n})\n// ✅ typed\nproxy.trackPageview()\n",[1220,6823,6824,6844,6849,6859,6865,6870],{"__ignoreMap":1218},[1223,6825,6826,6828,6830,6833,6835,6837,6840,6842],{"class":1225,"line":1226},[1223,6827,3214],{"class":1244},[1223,6829,1683],{"class":1236},[1223,6831,6832],{"class":1285}," proxy ",[1223,6834,1801],{"class":1236},[1223,6836,2339],{"class":1236},[1223,6838,6839],{"class":1751}," useScriptFathomAnalytics",[1223,6841,1754],{"class":1285},[1223,6843,1757],{"class":1236},[1223,6845,6846],{"class":1225,"line":1233},[1223,6847,6848],{"class":1229},"  // ✅ options are validated at runtime\n",[1223,6850,6851,6854,6856],{"class":1225,"line":1263},[1223,6852,6853],{"class":1240},"  site",[1223,6855,1765],{"class":1236},[1223,6857,6858],{"class":1236}," undefined\n",[1223,6860,6861,6863],{"class":1225,"line":1296},[1223,6862,1801],{"class":1236},[1223,6864,1804],{"class":1285},[1223,6866,6867],{"class":1225,"line":1325},[1223,6868,6869],{"class":1229},"// ✅ typed\n",[1223,6871,6872,6874,6876,6879],{"class":1225,"line":1355},[1223,6873,6651],{"class":1285},[1223,6875,2281],{"class":1236},[1223,6877,6878],{"class":1751},"trackPageview",[1223,6880,1789],{"class":1285},[1155,6882,6884],{"id":6883},"facade-components","Facade Components",[1143,6886,6887,6888,6893,6894,5062,6899,4363,6904,2281],{},"The registry includes several ",[2006,6889,6892],{"href":6890,"rel":6891},"https://scripts.nuxt.com/docs/guides/facade-components",[2010],"facade components",", such as\n",[2006,6895,6898],{"href":6896,"rel":6897},"https://scripts.nuxt.com/scripts/content/google-maps",[2010],"Google Maps",[2006,6900,6903],{"href":6901,"rel":6902},"https://scripts.nuxt.com/scripts/content/youtube-player",[2010],"YouTube",[2006,6905,6908],{"href":6906,"rel":6907},"https://scripts.nuxt.com/scripts/support/intercom",[2010],"Intercom",[1143,6910,6911,6912,6917],{},"Facade components are \"fake\" components that get hydrated when the third-party script loads. Facade components\nhave trade-offs but can drastically improve your performance. See the ",[2006,6913,6916],{"href":6914,"rel":6915},"https://scripts.nuxt.com/docs/guides/facade-components#what-are-facade-components",[2010],"What are Facade Components?","\nguide for more information.",[1143,6919,6920],{},"Nuxt Scripts provides facade components as accessible but headless, meaning they are not styled by default but add the necessary\na16y data.",[2054,6922,6923,6927],{},[6924,6925],"youtube-demo",{"label":6926},"Output",[1213,6928,6931],{"className":2595,"code":6929,"filename":6930,"language":2597,"meta":1218,"style":1218},"\u003Cscript setup lang=\"ts\">\nconst isLoaded = ref(false)\nconst isPlaying = ref(false)\nconst video = ref()\nfunction play() {\n  video.value?.player.playVideo()\n}\nfunction stateChange(state) {\n  isPlaying.value = state.data === 1\n}\n\u003C/script>\n\n\u003Ctemplate>\n  \u003CScriptYouTubePlayer ref=\"video\" video-id=\"d_IFKP1Ofq0\" @ready=\"isLoaded = true\" @state-change=\"stateChange\">\n    \u003Ctemplate #awaitingLoad>\n      \u003Cdiv class=\"absolute left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 h-[48px] w-[68px]\">\n        \u003Csvg height=\"100%\" version=\"1.1\" viewBox=\"0 0 68 48\" width=\"100%\">\u003Cpath d=\"M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z\" fill=\"#f00\" />\u003Cpath d=\"M 45,24 27,14 27,34\" fill=\"#fff\" />\u003C/svg>\n      \u003C/div>\n    \u003C/template>\n  \u003C/ScriptYouTubePlayer>\n\u003C/template>\n","Input",[1220,6932,6933,6953,6972,6989,7002,7013,7035,7039,7055,7080,7084,7092,7096,7104,7160,7174,7194,7312,7321,7329,7337],{"__ignoreMap":1218},[1223,6934,6935,6937,6939,6941,6943,6945,6947,6949,6951],{"class":1225,"line":1226},[1223,6936,1237],{"class":1236},[1223,6938,5899],{"class":1240},[1223,6940,5902],{"class":1244},[1223,6942,6066],{"class":1244},[1223,6944,1248],{"class":1236},[1223,6946,1251],{"class":1236},[1223,6948,1672],{"class":1254},[1223,6950,1251],{"class":1236},[1223,6952,1260],{"class":1236},[1223,6954,6955,6957,6960,6962,6965,6967,6970],{"class":1225,"line":1233},[1223,6956,3214],{"class":1244},[1223,6958,6959],{"class":1285}," isLoaded ",[1223,6961,1248],{"class":1236},[1223,6963,6964],{"class":1751}," ref",[1223,6966,1754],{"class":1285},[1223,6968,6969],{"class":2928},"false",[1223,6971,1804],{"class":1285},[1223,6973,6974,6976,6979,6981,6983,6985,6987],{"class":1225,"line":1263},[1223,6975,3214],{"class":1244},[1223,6977,6978],{"class":1285}," isPlaying ",[1223,6980,1248],{"class":1236},[1223,6982,6964],{"class":1751},[1223,6984,1754],{"class":1285},[1223,6986,6969],{"class":2928},[1223,6988,1804],{"class":1285},[1223,6990,6991,6993,6996,6998,7000],{"class":1225,"line":1296},[1223,6992,3214],{"class":1244},[1223,6994,6995],{"class":1285}," video ",[1223,6997,1248],{"class":1236},[1223,6999,6964],{"class":1751},[1223,7001,1789],{"class":1285},[1223,7003,7004,7006,7009,7011],{"class":1225,"line":1325},[1223,7005,3108],{"class":1244},[1223,7007,7008],{"class":1751}," play",[1223,7010,1777],{"class":1236},[1223,7012,1891],{"class":1236},[1223,7014,7015,7018,7020,7022,7025,7028,7030,7033],{"class":1225,"line":1355},[1223,7016,7017],{"class":1285},"  video",[1223,7019,2281],{"class":1236},[1223,7021,3790],{"class":1285},[1223,7023,7024],{"class":1236},"?.",[1223,7026,7027],{"class":1285},"player",[1223,7029,2281],{"class":1236},[1223,7031,7032],{"class":1751},"playVideo",[1223,7034,1789],{"class":1240},[1223,7036,7037],{"class":1225,"line":1771},[1223,7038,2407],{"class":1236},[1223,7040,7041,7043,7046,7048,7051,7053],{"class":1225,"line":1783},[1223,7042,3108],{"class":1244},[1223,7044,7045],{"class":1751}," stateChange",[1223,7047,1754],{"class":1236},[1223,7049,7050],{"class":2329},"state",[1223,7052,2541],{"class":1236},[1223,7054,1891],{"class":1236},[1223,7056,7057,7060,7062,7064,7066,7069,7071,7074,7077],{"class":1225,"line":1792},[1223,7058,7059],{"class":1285},"  isPlaying",[1223,7061,2281],{"class":1236},[1223,7063,3790],{"class":1285},[1223,7065,2339],{"class":1236},[1223,7067,7068],{"class":1285}," state",[1223,7070,2281],{"class":1236},[1223,7072,7073],{"class":1285},"data",[1223,7075,7076],{"class":1236}," ===",[1223,7078,7079],{"class":6166}," 1\n",[1223,7081,7082],{"class":1225,"line":1798},[1223,7083,2407],{"class":1236},[1223,7085,7086,7088,7090],{"class":1225,"line":1975},[1223,7087,1289],{"class":1236},[1223,7089,5899],{"class":1240},[1223,7091,1260],{"class":1236},[1223,7093,7094],{"class":1225,"line":1981},[1223,7095,1740],{"emptyLinePlaceholder":1739},[1223,7097,7098,7100,7102],{"class":1225,"line":1987},[1223,7099,1237],{"class":1236},[1223,7101,2606],{"class":1240},[1223,7103,1260],{"class":1236},[1223,7105,7106,7108,7111,7113,7115,7117,7120,7122,7125,7127,7129,7132,7134,7137,7139,7141,7144,7146,7149,7151,7153,7156,7158],{"class":1225,"line":1993},[1223,7107,1266],{"class":1236},[1223,7109,7110],{"class":1240},"ScriptYouTubePlayer",[1223,7112,6964],{"class":1244},[1223,7114,1248],{"class":1236},[1223,7116,1251],{"class":1236},[1223,7118,7119],{"class":1254},"video",[1223,7121,1251],{"class":1236},[1223,7123,7124],{"class":1244}," video-id",[1223,7126,1248],{"class":1236},[1223,7128,1251],{"class":1236},[1223,7130,7131],{"class":1254},"d_IFKP1Ofq0",[1223,7133,1251],{"class":1236},[1223,7135,7136],{"class":1244}," @ready",[1223,7138,1248],{"class":1236},[1223,7140,1251],{"class":1236},[1223,7142,7143],{"class":1254},"isLoaded = true",[1223,7145,1251],{"class":1236},[1223,7147,7148],{"class":1244}," @state-change",[1223,7150,1248],{"class":1236},[1223,7152,1251],{"class":1236},[1223,7154,7155],{"class":1254},"stateChange",[1223,7157,1251],{"class":1236},[1223,7159,1260],{"class":1236},[1223,7161,7162,7164,7166,7169,7172],{"class":1225,"line":2720},[1223,7163,5138],{"class":1236},[1223,7165,2606],{"class":1240},[1223,7167,7168],{"class":1236}," #",[1223,7170,7171],{"class":1244},"awaitingLoad",[1223,7173,1260],{"class":1236},[1223,7175,7176,7179,7181,7183,7185,7187,7190,7192],{"class":1225,"line":2742},[1223,7177,7178],{"class":1236},"      \u003C",[1223,7180,1241],{"class":1240},[1223,7182,1245],{"class":1244},[1223,7184,1248],{"class":1236},[1223,7186,1251],{"class":1236},[1223,7188,7189],{"class":1254},"absolute left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 h-[48px] w-[68px]",[1223,7191,1251],{"class":1236},[1223,7193,1260],{"class":1236},[1223,7195,7196,7199,7202,7205,7207,7209,7212,7214,7217,7219,7221,7224,7226,7229,7231,7233,7236,7238,7241,7243,7245,7247,7249,7252,7254,7257,7259,7261,7264,7266,7269,7271,7273,7276,7278,7281,7283,7285,7287,7289,7292,7294,7296,7298,7300,7303,7305,7308,7310],{"class":1225,"line":6685},[1223,7197,7198],{"class":1236},"        \u003C",[1223,7200,7201],{"class":1240},"svg",[1223,7203,7204],{"class":1244}," height",[1223,7206,1248],{"class":1236},[1223,7208,1251],{"class":1236},[1223,7210,7211],{"class":1254},"100%",[1223,7213,1251],{"class":1236},[1223,7215,7216],{"class":1244}," version",[1223,7218,1248],{"class":1236},[1223,7220,1251],{"class":1236},[1223,7222,7223],{"class":1254},"1.1",[1223,7225,1251],{"class":1236},[1223,7227,7228],{"class":1244}," viewBox",[1223,7230,1248],{"class":1236},[1223,7232,1251],{"class":1236},[1223,7234,7235],{"class":1254},"0 0 68 48",[1223,7237,1251],{"class":1236},[1223,7239,7240],{"class":1244}," width",[1223,7242,1248],{"class":1236},[1223,7244,1251],{"class":1236},[1223,7246,7211],{"class":1254},[1223,7248,1251],{"class":1236},[1223,7250,7251],{"class":1236},">\u003C",[1223,7253,6037],{"class":1240},[1223,7255,7256],{"class":1244}," d",[1223,7258,1248],{"class":1236},[1223,7260,1251],{"class":1236},[1223,7262,7263],{"class":1254},"M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z",[1223,7265,1251],{"class":1236},[1223,7267,7268],{"class":1244}," fill",[1223,7270,1248],{"class":1236},[1223,7272,1251],{"class":1236},[1223,7274,7275],{"class":1254},"#f00",[1223,7277,1251],{"class":1236},[1223,7279,7280],{"class":1236}," />\u003C",[1223,7282,6037],{"class":1240},[1223,7284,7256],{"class":1244},[1223,7286,1248],{"class":1236},[1223,7288,1251],{"class":1236},[1223,7290,7291],{"class":1254},"M 45,24 27,14 27,34",[1223,7293,1251],{"class":1236},[1223,7295,7268],{"class":1244},[1223,7297,1248],{"class":1236},[1223,7299,1251],{"class":1236},[1223,7301,7302],{"class":1254},"#fff",[1223,7304,1251],{"class":1236},[1223,7306,7307],{"class":1236}," />\u003C/",[1223,7309,7201],{"class":1240},[1223,7311,1260],{"class":1236},[1223,7313,7314,7317,7319],{"class":1225,"line":6695},[1223,7315,7316],{"class":1236},"      \u003C/",[1223,7318,1241],{"class":1240},[1223,7320,1260],{"class":1236},[1223,7322,7323,7325,7327],{"class":1225,"line":6714},[1223,7324,5164],{"class":1236},[1223,7326,2606],{"class":1240},[1223,7328,1260],{"class":1236},[1223,7330,7331,7333,7335],{"class":1225,"line":6719},[1223,7332,5211],{"class":1236},[1223,7334,7110],{"class":1240},[1223,7336,1260],{"class":1236},[1223,7338,7339,7341,7343],{"class":1225,"line":6724},[1223,7340,1289],{"class":1236},[1223,7342,2606],{"class":1240},[1223,7344,1260],{"class":1236},[1155,7346,7348],{"id":7347},"consent-management-element-event-triggers","Consent Management & Element Event Triggers",[1143,7350,6393,7351,7353,7354,7357,7358,7361],{},[1220,7352,6808],{}," composable gives you full control over how and when your scripts are loaded, by either providing a custom ",[1220,7355,7356],{},"trigger"," or manually calling the ",[1220,7359,7360],{},"load()"," function.",[1143,7363,7364],{},"Building on top of this, Nuxt Scripts provides advanced triggers to make it even easier.",[1852,7366,7367,7375],{},[1855,7368,7369,7374],{},[2006,7370,7373],{"href":7371,"rel":7372},"https://scripts.nuxt.com/docs/guides/consent",[2010],"Consent Management"," - Load scripts only after the user has given consent such as with a cookie banner.",[1855,7376,7377,7382],{},[2006,7378,7381],{"href":7379,"rel":7380},"https://scripts.nuxt.com/docs/guides/script-triggers#element-event-triggers",[2010],"Element Event Triggers"," - Load scripts based on user interactions such as scrolling, clicking, or form submissions.",[1213,7384,7386],{"className":1669,"code":7385,"language":1672,"meta":1218,"style":1218},"const cookieConsentTrigger = useScriptTriggerConsent()\nconst { proxy } = useScript\u003C{ greeting: () => void }>('/hello.js', {\n  // script will only be loaded once the consent has been accepted\n  trigger: cookieConsentTrigger\n})\n// ...\nfunction acceptCookies() {\n  cookieConsentTrigger.accept()\n}\n// greeting() is queued until the user accepts cookies\nproxy.greeting()\n",[1220,7387,7388,7402,7445,7450,7459,7465,7470,7481,7493,7497,7502],{"__ignoreMap":1218},[1223,7389,7390,7392,7395,7397,7400],{"class":1225,"line":1226},[1223,7391,3214],{"class":1244},[1223,7393,7394],{"class":1285}," cookieConsentTrigger ",[1223,7396,1248],{"class":1236},[1223,7398,7399],{"class":1751}," useScriptTriggerConsent",[1223,7401,1789],{"class":1285},[1223,7403,7404,7406,7408,7410,7412,7414,7416,7419,7421,7423,7425,7427,7430,7433,7435,7437,7439,7441,7443],{"class":1225,"line":1233},[1223,7405,3214],{"class":1244},[1223,7407,1683],{"class":1236},[1223,7409,6832],{"class":1285},[1223,7411,1801],{"class":1236},[1223,7413,2339],{"class":1236},[1223,7415,6543],{"class":1751},[1223,7417,7418],{"class":1236},"\u003C{",[1223,7420,6619],{"class":1240},[1223,7422,1765],{"class":1236},[1223,7424,3122],{"class":1236},[1223,7426,3125],{"class":1244},[1223,7428,7429],{"class":2036}," void",[1223,7431,7432],{"class":1236}," }>",[1223,7434,1754],{"class":1285},[1223,7436,1957],{"class":1236},[1223,7438,6550],{"class":1254},[1223,7440,1957],{"class":1236},[1223,7442,2333],{"class":1236},[1223,7444,1891],{"class":1236},[1223,7446,7447],{"class":1225,"line":1263},[1223,7448,7449],{"class":1229},"  // script will only be loaded once the consent has been accepted\n",[1223,7451,7452,7454,7456],{"class":1225,"line":1296},[1223,7453,6561],{"class":1240},[1223,7455,1765],{"class":1236},[1223,7457,7458],{"class":1285}," cookieConsentTrigger\n",[1223,7460,7461,7463],{"class":1225,"line":1325},[1223,7462,1801],{"class":1236},[1223,7464,1804],{"class":1285},[1223,7466,7467],{"class":1225,"line":1355},[1223,7468,7469],{"class":1229},"// ...\n",[1223,7471,7472,7474,7477,7479],{"class":1225,"line":1771},[1223,7473,3108],{"class":1244},[1223,7475,7476],{"class":1751}," acceptCookies",[1223,7478,1777],{"class":1236},[1223,7480,1891],{"class":1236},[1223,7482,7483,7486,7488,7491],{"class":1225,"line":1783},[1223,7484,7485],{"class":1285},"  cookieConsentTrigger",[1223,7487,2281],{"class":1236},[1223,7489,7490],{"class":1751},"accept",[1223,7492,1789],{"class":1240},[1223,7494,7495],{"class":1225,"line":1792},[1223,7496,2407],{"class":1236},[1223,7498,7499],{"class":1225,"line":1798},[1223,7500,7501],{"class":1229},"// greeting() is queued until the user accepts cookies\n",[1223,7503,7504,7506,7508,7510],{"class":1225,"line":1975},[1223,7505,6651],{"class":1285},[1223,7507,2281],{"class":1236},[1223,7509,6656],{"class":1751},[1223,7511,1789],{"class":1285},[1155,7513,7515],{"id":7514},"bundling-scripts","Bundling Scripts",[1143,7517,7518],{},"In many cases, we're loading third-party scripts from a domain that we don't control. This can lead to a number of issues:",[1852,7520,7521,7524,7527,7530],{},[1855,7522,7523],{},"Privacy: The third-party script can track users across sites.",[1855,7525,7526],{},"Security: The third-party script can be compromised and inject malicious code.",[1855,7528,7529],{},"Performance: Extra DNS lookups will slow down the page load.",[1855,7531,7532],{},"Developer Experience: Consented scripts may be blocked by ad blockers.",[1143,7534,7535],{},"To mitigate this, Nuxt Scripts provides a way to bundle third-party scripts into your public directory without any extra work.",[1213,7537,7539],{"className":1669,"code":7538,"language":1672,"meta":1218,"style":1218},"useScript('https://cdn.jsdelivr.net/npm/js-confetti@latest/dist/js-confetti.browser.js', {\n  bundle: true,\n})\n",[1220,7540,7541,7558,7569],{"__ignoreMap":1218},[1223,7542,7543,7545,7547,7549,7552,7554,7556],{"class":1225,"line":1226},[1223,7544,6808],{"class":1751},[1223,7546,1754],{"class":1285},[1223,7548,1957],{"class":1236},[1223,7550,7551],{"class":1254},"https://cdn.jsdelivr.net/npm/js-confetti@latest/dist/js-confetti.browser.js",[1223,7553,1957],{"class":1236},[1223,7555,2333],{"class":1236},[1223,7557,1891],{"class":1236},[1223,7559,7560,7563,7565,7567],{"class":1225,"line":1233},[1223,7561,7562],{"class":1240},"  bundle",[1223,7564,1765],{"class":1236},[1223,7566,2929],{"class":2928},[1223,7568,1780],{"class":1236},[1223,7570,7571,7573],{"class":1225,"line":1263},[1223,7572,1801],{"class":1236},[1223,7574,1804],{"class":1285},[1143,7576,7577,7578,7581],{},"The script will now be served from ",[1220,7579,7580],{},"/_scripts/{hash}"," on your own domain.",[1147,7583,7585],{"id":7584},"to-be-continued","To be continued",[1143,7587,7588],{},"As we saw, there are many opportunities to improve third-party scripts for developers and end-users.",[1143,7590,7591,7592,7595],{},"The initial release of Nuxt Scripts has solved ",[3746,7593,7594],{},"some"," of these issues, but there's still a lot of work ahead of us.",[1143,7597,7598],{},"The next items on the roadmap are:",[1852,7600,7601,7608,7615,7622],{},[1855,7602,7603],{},[2006,7604,7607],{"href":7605,"rel":7606},"https://github.com/nuxt/scripts/issues/182",[2010],"Add web worker support (Partytown)",[1855,7609,7610],{},[2006,7611,7614],{"href":7612,"rel":7613},"https://github.com/nuxt/scripts/issues/44",[2010],"More Live Chat Facade Components",[1855,7616,7617],{},[2006,7618,7621],{"href":7619,"rel":7620},"https://github.com/nuxt/scripts/issues/87",[2010],"Offload Scripts To Nuxt Server Proxy",[1855,7623,7624],{},[2006,7625,7628],{"href":7626,"rel":7627},"https://github.com/nuxt/scripts/issues/131",[2010],"Iframe Script Sandboxing",[1143,7630,7631],{},"We'd love to have your contribution and support.",[1147,7633,7634],{"id":2015},"Getting started",[1143,7636,7637,7638,7643],{},"To get started with Nuxt Scripts, we've created a ",[2006,7639,7642],{"href":7640,"rel":7641},"https://scripts.nuxt.com/docs/getting-started/confetti-tutorial",[2010],"tutorial"," to help you get up and running.",[1147,7645,7647],{"id":7646},"credits","Credits",[1852,7649,7650,7657,7665,7672],{},[1855,7651,7652,7656],{},[2006,7653,7655],{"href":5696,"rel":7654},[2010],"Harlan Wilton - Nuxt"," (author)",[1855,7658,7659,7664],{},[2006,7660,7663],{"href":7661,"rel":7662},"https://github.com/huang-julien",[2010],"Julien Huang - Nuxt"," (contributor)",[1855,7666,7667,7664],{},[2006,7668,7671],{"href":7669,"rel":7670},"https://github.com/danielroe",[2010],"Daniel Roe - Nuxt",[1855,7673,7674,7664],{},[2006,7675,7677],{"href":5705,"rel":7676},[2010],"Chrome Aurora - Google",[1143,7679,7680],{},"And a big thank you to the early contributors.",[1143,7682,7683],{},[2243,7684],{"alt":7685,"className":7686,"src":7687},"Nuxt Scripts Contributors",[2247,2248,2249,2250],"/assets/blog/nuxt-scripts/contributors.png",[2160,7689,7690],{},"html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}html pre.shiki code .sagxc, html code.shiki .sagxc{--shiki-light:#FF5370;--shiki-default:#FF5370;--shiki-dark:#FF9CAC}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 .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .svXlt, html code.shiki .svXlt{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sV9sa, html code.shiki .sV9sa{--shiki-light:#F76D47;--shiki-default:#F76D47;--shiki-dark:#F78C6C}html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}html pre.shiki code .ssYd4, html code.shiki .ssYd4{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":1218,"searchDepth":1233,"depth":1233,"links":7692},[7693,7694,7700,7707,7708,7709],{"id":5726,"depth":1233,"text":5727},{"id":5765,"depth":1233,"text":5766,"children":7695},[7696,7697,7698],{"id":5797,"depth":1263,"text":5798},{"id":6370,"depth":1263,"text":6371},{"id":6425,"depth":1263,"text":7699},"🛡️ Privacy & Security: Do no evil?",{"id":6455,"depth":1233,"text":6456,"children":7701},[7702,7703,7704,7705,7706],{"id":6459,"depth":1263,"text":6460},{"id":6786,"depth":1263,"text":6787},{"id":6883,"depth":1263,"text":6884},{"id":7347,"depth":1263,"text":7348},{"id":7514,"depth":1263,"text":7515},{"id":7584,"depth":1233,"text":7585},{"id":2015,"depth":1233,"text":7634},{"id":7646,"depth":1233,"text":7647},"2024-08-20","Nuxt Scripts provides better performance, privacy, security, and developer experience for third-party scripts.",{},{"title":1064,"description":7711},"2kSybZrWSL",{"id":7716,"title":1080,"authors":7717,"body":7724,"category":7880,"date":7881,"description":7882,"draft":108,"extension":1954,"image":7883,"meta":7884,"navigation":1739,"path":1081,"seo":7885,"stem":1082,"tags":6,"__hash__":7886},"blog/blog/4.nuxt2-eol.md",[7718,7722],{"name":1130,"avatar":7719,"to":1133,"twitter":7721},{"src":7720},"https://github.com/Atinux.png","atinux",{"name":2190,"avatar":7723,"to":2193},{"src":2192},{"type":1140,"value":7725,"toc":7870},[7726,7729,7732,7739,7743,7746,7752,7756,7759,7762,7785,7788,7794,7800,7804,7807,7811,7814,7819,7823,7830,7833,7838,7842,7845,7848,7863,7867],[1143,7727,7728],{},"Released in 2018, Nuxt 2.0 marked a major milestone, establishing it as a mainstream framework. Over the past six years, many developers adopted Nuxt 2, leading to the creation of numerous impressive projects across the web.",[1143,7730,7731],{},"However, looking forward, maintaining Nuxt 2 is no longer sustainable. With the recent end-of-life of Vue 2 and the maturity of Nuxt 3 and its ecosystem, it's time for our team to concentrate our efforts on the latest major version and upcoming versions.",[7733,7734,7736],"tip",{"target":3615,"to":7735},"https://www.herodevs.com/support/nuxt-nes?utm_source=nuxt&utm_medium=nuxt-eol-article",[1143,7737,7738],{},"Jump over HeroDevs' Nuxt Never-Ending Support (NES)",[1147,7740,7742],{"id":7741},"what-happens-on-june-30th-2024","What happens on June 30th, 2024?",[1143,7744,7745],{},"After this date, Nuxt 2 will continue to be available on the NPM package manager, but will no longer receive updates, such as security and browser compatibility fixes. In other words, your applications will continue to work, but you may get deprecation warnings from your package manager reminding you that Nuxt 2 is no longer a supported version.",[7747,7748,7749],"note",{},[1143,7750,7751],{},"Vue 2 reached its end-of-life date on December 31st, 2023.",[1147,7753,7755],{"id":7754},"whats-next","What’s Next?",[1143,7757,7758],{},"Nuxt 3 has been the default version of Nuxt since November 16th, 2022.",[1143,7760,7761],{},"On top of using Vue 3 and the composition API, it is shipped with features and innovations:",[1852,7763,7764,7767,7770,7773,7776,7779,7782],{},[1855,7765,7766],{},"Universal & Hybrid Rendering: Benefits of both SPA and SSR, with fine-grained control over route rendering",[1855,7768,7769],{},"Support for serverless environments (AWS Lambda, Deno, Cloudflare Workers) with minimal cold-start.",[1855,7771,7772],{},"First-Class TypeScript Support: Full typing across all components and configurations.",[1855,7774,7775],{},"Vite integration for a faster developer experience",[1855,7777,7778],{},"Server & API routes with end-to-end typing powered by Nitro",[1855,7780,7781],{},"Auto import of composables & utils",[1855,7783,7784],{},"Layers feature for domain driven development",[1143,7786,7787],{},"When and if you can, consider migrating to Nuxt 3 to take advantage of these powerful features.",[3611,7789,7791],{"to":7790},"/docs/getting-started/upgrade#nuxt-2-vs-nuxt-3",[1143,7792,7793],{},"See a full comparison table between Nuxt 2 and Nuxt 3, as well as detailed upgrade guides to Nuxt 3 and Nuxt Bridge (as a part of upgrading to Nuxt 3).",[3611,7795,7797],{"to":7796,"icon":908},"/enterprise/support",[1143,7798,7799],{},"If you need support, including upgrading to Nuxt 3, NuxtLabs provides professional support and consultancy in a wide range of areas.",[1147,7801,7803],{"id":7802},"still-on-nuxt-2-here-are-your-options","Still on Nuxt 2? Here Are Your Options.",[1143,7805,7806],{},"Recognizing the various situations that arise during transitions, we are fully aware that users may need other options until they can migrate, or maybe migration simply isn't a feasible path. Here are some other options to consider:",[1155,7808,7810],{"id":7809},"update-to-the-nuxt-2-latest-release","Update to the Nuxt 2 latest release",[1143,7812,7813],{},"We expect to release 2.18.0 at the end of June 2024, which will include a few final fixes.",[7747,7815,7816],{},[1143,7817,7818],{},"We strongly encourage you to update to 2.18.0 once it's out. This will be the starting point for extended support mentioned below.",[1155,7820,7822],{"id":7821},"purchase-extended-support-for-nuxt-2","Purchase Extended Support for Nuxt 2",[1143,7824,7825,7826,7829],{},"If you have to stay on Nuxt 2 post-EOL, we have partnered with HeroDevs to offer Nuxt 2 Never-Ending Support (NES). Nuxt 2 NES provides ongoing security and compatibility patches for Nuxt 2 and all official Nuxt Modules (modules released by the Nuxt team, labeled ",[1220,7827,7828],{},"@nuxt/..."," in the marketplace) even after EOL so that applications with strict compliance requirements remain secure and compliant. It also guarantees that Nuxt 2 applications will continue to operate effectively in modern browsers and maintain compatibility with essential libraries like Vue 2. Moreover, Nuxt 2 NES has continuous security monitoring and an enterprise level SLA with respect to support and fixes.",[1143,7831,7832],{},"Nuxt 2 NES is the continuation of the flavor of security support you’ve enjoyed during the Nuxt 2 LTS period — but indefinitely.",[7733,7834,7835],{"target":3615,"to":7735},[1143,7836,7837],{},"Read more about HeroDevs' Nuxt Never-Ending Support (NES)",[1155,7839,7841],{"id":7840},"notify-your-users-of-your-nuxt-2-post-eol-plan","Notify Your Users of Your Nuxt 2 Post-EOL Plan",[1143,7843,7844],{},"If migrating to Nuxt 3 or using Nuxt 2 NES isn't feasible right now, but you're still on Nuxt 2, it's essential to plan how you'll communicate your security strategy to your customers.",[1143,7846,7847],{},"This doesn't affect all Nuxt users, but many teams face restrictions against deploying unsupported software due to SLAs, contracts, or other obligations to clients and partners. These requirements might come from customers, regulatory bodies, or internal company policies. Increasingly, regulatory bodies are setting higher standards for software accountability.",[1143,7849,7850,7851,7856,7857,7862],{},"For those with such responsibilities, informing your customers, managers, CISO, or other stakeholders about your plans to handle support and manage potential CVEs is crucial. While Nuxt 2 has only had few vulnerabilities, CVEs can emerge even in well-maintained EOL projects through direct vulnerabilities or compromised dependencies. Staying updated with CVE notifications from organizations like ",[2006,7852,7855],{"href":7853,"rel":7854},"https://www.opencve.io",[2010],"OpenCVE",", and ",[2006,7858,7861],{"href":7859,"rel":7860},"https://snyk.io",[2010],"Snyk"," can help you identify issues as they arise. Additionally, browsers occasionally update in ways that can affect legacy libraries—though rare, it’s a possibility to be aware of.",[1147,7864,7866],{"id":7865},"looking-forward","Looking Forward",[1143,7868,7869],{},"It is with a heavy heart that I am saying goodbye to Nuxt 2. After many years of working on it and seeing so many websites made with it, this famous loading bar at the top of each Nuxt 2 website will be something I’ll miss a lot! It is with excitement and energy that I will keep working with the core team on the future of Nuxt to keep innovating like we've been doing over these past 8 years.",{"title":1218,"searchDepth":1233,"depth":1233,"links":7871},[7872,7873,7874,7879],{"id":7741,"depth":1233,"text":7742},{"id":7754,"depth":1233,"text":7755},{"id":7802,"depth":1233,"text":7803,"children":7875},[7876,7877,7878],{"id":7809,"depth":1263,"text":7810},{"id":7821,"depth":1263,"text":7822},{"id":7840,"depth":1263,"text":7841},{"id":7865,"depth":1233,"text":7866},"Announcement","2024-06-14","Nuxt 2 will reach End of Life (EOL) on June 30th, 2024. We've partnered with HeroDevs on offering Never-Ending Support (NES).","/assets/blog/nuxt2-eol.png",{},{"title":1080,"description":7882},"jwtmnJPQzw",{"id":7888,"title":7889,"authors":7890,"body":7893,"category":2176,"date":8409,"description":8410,"draft":108,"extension":1954,"image":8411,"meta":8412,"navigation":108,"path":8413,"seo":8414,"stem":8415,"tags":6,"__hash__":8416},"blog/blog/25.v3-12.md","Nuxt 3.12",[7891],{"name":2190,"avatar":7892,"to":2193},{"src":2192},{"type":1140,"value":7894,"toc":8394},[7895,7898,7902,7914,7962,7965,7971,7974,7978,7990,7993,7997,8013,8021,8025,8038,8048,8055,8057,8063,8072,8080,8092,8106,8110,8128,8137,8141,8156,8164,8168,8171,8206,8226,8229,8233,8245,8271,8275,8278,8328,8332,8351,8353,8355,8369,8371,8373,8381,8384,8387,8391],[1143,7896,7897],{},"We're on the road to the release of Nuxt 4, but we've not held back in Nuxt v3.12.",[1147,7899,7901],{"id":7900},"testing-nuxt-4-changes","🚀 Testing Nuxt 4 changes",[1143,7903,7904,7905,7910,7911,7913],{},"Nuxt 4 is on the horizon, and it's now possible to test out the behaviour changes that will be coming in the next major release (",[2006,7906,7909],{"href":7907,"rel":7908},"https://github.com/nuxt/nuxt/pull/26925",[2010],"#26925",") by setting an option in your ",[1220,7912,5357],{}," file:",[1213,7915,7917],{"className":1669,"code":7916,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  future: {\n    compatibilityVersion: 4,\n  },\n})\n",[1220,7918,7919,7931,7940,7952,7956],{"__ignoreMap":1218},[1223,7920,7921,7923,7925,7927,7929],{"class":1225,"line":1226},[1223,7922,1745],{"class":1679},[1223,7924,1748],{"class":1679},[1223,7926,2820],{"class":1751},[1223,7928,1754],{"class":1285},[1223,7930,1757],{"class":1236},[1223,7932,7933,7936,7938],{"class":1225,"line":1233},[1223,7934,7935],{"class":1240},"  future",[1223,7937,1765],{"class":1236},[1223,7939,1891],{"class":1236},[1223,7941,7942,7945,7947,7950],{"class":1225,"line":1263},[1223,7943,7944],{"class":1240},"    compatibilityVersion",[1223,7946,1765],{"class":1236},[1223,7948,7949],{"class":6166}," 4",[1223,7951,1780],{"class":1236},[1223,7953,7954],{"class":1225,"line":1296},[1223,7955,3312],{"class":1236},[1223,7957,7958,7960],{"class":1225,"line":1325},[1223,7959,1801],{"class":1236},[1223,7961,1804],{"class":1285},[1143,7963,7964],{},"As we've been merging PRs for Nuxt 4, we've been enabling them behind this flag. As much as possible we're aiming for backwards compatibility - our test matrix is running the same fixtures in both v3 and v4 compatibility mode.",[1143,7966,7967,7968,2281],{},"There is a lot to say here, with 10+ different PRs and behaviour changes documented and testable, but for full details, including migration steps, see ",[2006,7969,7970],{"href":4833},"the v4 upgrade documentation",[1143,7972,7973],{},"We'd be very grateful for early testing of what's coming in Nuxt 4! 🙏",[1147,7975,7977],{"id":7976},"nuxt-scripts-auto-install","📜 Nuxt Scripts auto-install",[1143,7979,7980,7981,7985,7986,7989],{},"We've been gradually working to release ",[2006,7982,5713],{"href":7983,"rel":7984},"https://scripts.nuxt.com/",[2010],". It's currently in public preview, but we're near a public release, so we've added some stubs for composables that (when used) will prompt installing the ",[1220,7987,7988],{},"@nuxt/scripts"," module.",[1143,7991,7992],{},"👉 Watch out for the launch - and an article explaining more!",[1147,7994,7996],{"id":7995},"layer-auto-registration-and-bugfixes","🌈 Layer auto-registration and bugfixes",[1143,7998,7999,8000,8003,8004,8007,8008,3681],{},"Just like ",[1220,8001,8002],{},"~/modules",", any layers within your project in the ",[1220,8005,8006],{},"~/layers"," directory will now be automatically registered as layers in your project (",[2006,8009,8012],{"href":8010,"rel":8011},"https://github.com/nuxt/nuxt/pull/27221",[2010],"#27221",[1143,8014,8015,8016,3681],{},"We also now correctly load layer dependencies, which should resolve a range of issues with monorepos and git installations (",[2006,8017,8020],{"href":8018,"rel":8019},"https://github.com/nuxt/nuxt/pull/27338",[2010],"#27338",[1147,8022,8024],{"id":8023},"built-in-accessibility-improvements","🌐 Built-in accessibility improvements",[1143,8026,8027,8028,8032,8033,8037],{},"We now have a built-in ",[2006,8029,8030],{"href":381},[1220,8031,380],{}," component and corresponding ",[2006,8034,8035],{"href":513},[1220,8036,512],{}," composable, which will be added by default to new Nuxt templates going forward.",[1143,8039,8040,8041,4363,8046,2281],{},"For full details, see ",[2006,8042,8045],{"href":8043,"rel":8044},"https://github.com/nuxt/nuxt/pull/25741",[2010],"the original PR (#25741)",[2006,8047,2147],{"href":381},[1143,8049,8050,8051,8054],{},"We're continuing to work on ",[1220,8052,8053],{},"nuxt/a11y"," - expect to hear more on that in future!",[1147,8056,3968],{"id":3967},[1143,8058,8059,8060,8062],{},"We've landed some performance improvements as well, many of which are behind the ",[1220,8061,2438],{}," flag, such as a move away from deeply reactive asyncData payloads.",[1143,8064,8065,8066,8071],{},"Significant improvements include deduplicating modules (",[2006,8067,8070],{"href":8068,"rel":8069},"https://github.com/nuxt/nuxt/pull/27475",[2010],"#27475",") - which will apply mostly to layer users who specify modules in their layers. In one project, we saw 30s+ improvement in starting Nuxt.",[1143,8073,8074,8075,3681],{},"We've also improved Vite dev server start up time by excluding common ESM dependencies from pre-bundling, and would suggest module authors consider doing the same (",[2006,8076,8079],{"href":8077,"rel":8078},"https://github.com/nuxt/nuxt/pull/27372",[2010],"#27372",[1143,8081,8082,8083,8086,8087,3681],{},"We improved chunk determinism, so sequential builds should be less likely to have ",[3746,8084,8085],{},"completely"," different chunk hashes (",[2006,8088,8091],{"href":8089,"rel":8090},"https://github.com/nuxt/nuxt/pull/27258",[2010],"#27258",[1143,8093,8094,8095,8100,8101,3681],{},"And we tree shake more client-only composables from your server builds (",[2006,8096,8099],{"href":8097,"rel":8098},"https://github.com/nuxt/nuxt/pull/27044",[2010],"#27044","), and have reduced the size of server component payloads (",[2006,8102,8105],{"href":8103,"rel":8104},"https://github.com/nuxt/nuxt/pull/26863",[2010],"#26863",[1147,8107,8109],{"id":8108},"multi-app-support","👨‍👩‍👧‍👦 Multi-app support",[1143,8111,8112,8113,8116,8117,8122,8123,3681],{},"We've landed a couple of changes that take us toward a place of supporting multi-app natively in Nuxt, including a ",[1220,8114,8115],{},"multiApp"," experimental flag (",[2006,8118,8121],{"href":8119,"rel":8120},"https://github.com/nuxt/nuxt/pull/27291",[2010],"#27291",") and the ability to have multiple Nuxt app instances running in parallel at runtime (",[2006,8124,8127],{"href":8125,"rel":8126},"https://github.com/nuxt/nuxt/pull/27068",[2010],"#27068",[1143,8129,8130,8131,8136],{},"While it's not yet ready, please do follow along on ",[2006,8132,8135],{"href":8133,"rel":8134},"https://github.com/nuxt/nuxt/issues/21635",[2010],"the tracker issue",", and feel free to pitch in if this is interesting to you.",[1147,8138,8140],{"id":8139},"️-dx-wins","⛑️ DX wins",[1143,8142,8143,8144,8149,8150,8155],{},"We now serialise more things in your dev server logs, including VNodes (",[2006,8145,8148],{"href":8146,"rel":8147},"https://github.com/nuxt/nuxt/pull/27309",[2010],"#27309",") and ",[2006,8151,8154],{"href":8152,"rel":8153},"https://github.com/nuxt/nuxt/commit/a549b46e9",[2010],"URLs",". We also addressed a bug that could lead to a frozen dev server.",[1143,8157,8158,8159,3681],{},"When accessing private runtime config in the browser, we now let you know with a more informative error message (",[2006,8160,8163],{"href":8161,"rel":8162},"https://github.com/nuxt/nuxt/pull/26441",[2010],"#26441",[1147,8165,8167],{"id":8166},"stabilising-features","🪨 Stabilising features",[1143,8169,8170],{},"We've removed some experimental options that have been stabilised and which we feel no longer need to be configurable:",[1852,8172,8173,8179,8185,8196],{},[1855,8174,8175,8178],{},[1220,8176,8177],{},"experimental.treeshakeClientOnly"," (enabled by default since v3.0.0)",[1855,8180,8181,8184],{},[1220,8182,8183],{},"experimental.configSchema"," (enabled by default since v3.3.0)",[1855,8186,8187,8190,8191],{},[1220,8188,8189],{},"experimental.polyfillVueUseHead"," (disabled since v3.4.0) - implementable in user-land with ",[2006,8192,8195],{"href":8193,"rel":8194},"https://github.com/nuxt/nuxt/blob/f209158352b09d1986aa320e29ff36353b91c358/packages/nuxt/src/head/runtime/plugins/vueuse-head-polyfill.ts#L10-L11",[2010],"plugin",[1855,8197,8198,8190,8201],{},[1220,8199,8200],{},"experimental.respectNoSSRHeader",[2006,8202,8205],{"href":8203,"rel":8204},"https://github.com/nuxt/nuxt/blob/c660b39447f0d5b8790c0826092638d321cd6821/packages/nuxt/src/core/runtime/nitro/no-ssr.ts#L8-L9",[2010],"server middleware",[1143,8207,8208,8209,8212,8213,8218,8219,8221,8222,8225],{},"We've also enabled ",[1220,8210,8211],{},"scanPageMeta"," by default (",[2006,8214,8217],{"href":8215,"rel":8216},"https://github.com/nuxt/nuxt/pull/27134",[2010],"#27134","). This pulls out any page metadata in your ",[1220,8220,587],{}," macro, and makes it available to modules (like ",[1220,8223,8224],{},"@nuxtjs/i18n",") so they can augment it.",[1143,8227,8228],{},"This unlocks much better module/typed routing integration, but has a potential performance cost - so please file an issue if you experience any problems.",[1147,8230,8232],{"id":8231},"type-improvements","💪 Type improvements",[1143,8234,8235,8236,8239,8240,3681],{},"We now have support for typed ",[1220,8237,8238],{},"#fallback"," slots in server components (",[2006,8241,8244],{"href":8242,"rel":8243},"https://github.com/nuxt/nuxt/pull/27097",[2010],"#27097",[1143,8246,8247,8248,8250,8251,8254,8255,8260,8261,5062,8266,2281],{},"We've also improved some defaults in your generated ",[1220,8249,268],{},", including setting ",[1220,8252,8253],{},"module: 'preserve'"," if you have a locally installed TypeScript v5.4 version (",[2006,8256,8259],{"href":8257,"rel":8258},"https://www.typescriptlang.org/tsconfig/#preserve",[2010],"see docs",") - see ",[2006,8262,8265],{"href":8263,"rel":8264},"https://github.com/nuxt/nuxt/pull/26667",[2010],"#26667",[2006,8267,8270],{"href":8268,"rel":8269},"https://github.com/nuxt/nuxt/pull/27485",[2010],"#27485",[1147,8272,8274],{"id":8273},"module-authorpower-user-improvements","📦 Module author/power user improvements",[1143,8276,8277],{},"We have shipped a range of type improvements for module authors, including:",[1852,8279,8280,8291,8299,8310],{},[1855,8281,8282,8283,3114,8286,2541],{},"support for typed module options in ",[1220,8284,8285],{},"installModule",[2006,8287,8290],{"href":8288,"rel":8289},"https://github.com/nuxt/nuxt/pull/26744",[2010],"#26744",[1855,8292,8293,8294,2541],{},"the option to specify compatibility with certain builders (vite/webpack) in module options (",[2006,8295,8298],{"href":8296,"rel":8297},"https://github.com/nuxt/nuxt/pull/27022",[2010],"#27022",[1855,8300,8301,8302,8304,8305,2541],{},"a new ",[1220,8303,424],{}," hook for hooking into the browser hydration cycle (",[2006,8306,8309],{"href":8307,"rel":8308},"https://github.com/nuxt/nuxt/pull/27037",[2010],"#27037",[1855,8311,8312,8313,8316,8317,4363,8319,8322,8323,2541],{},"the ability to access and update ",[3746,8314,8315],{},"resolved"," runtime configuration within modules, with new build-time ",[1220,8318,520],{},[1220,8320,8321],{},"updateRuntimeConfig"," utils (",[2006,8324,8327],{"href":8325,"rel":8326},"https://github.com/nuxt/nuxt/pull/27117",[2010],"#27117",[1147,8329,8331],{"id":8330},"inlined-ui-templates","🎨 Inlined UI templates",[1143,8333,8334,8335,8338,8339,8344,8345,8350],{},"If you previously used ",[1220,8336,8337],{},"@nuxt/ui-templates"," then it may be worth knowing that we have moved them from ",[2006,8340,8343],{"href":8341,"rel":8342},"https://github.com/nuxt/ui-templates",[2010],"a separate repository"," into the ",[2006,8346,8349],{"href":8347,"rel":8348},"https://github.com/nuxt/nuxt",[2010],"nuxt/nuxt"," monorepo. (This is purely a refactor rather than a change, although you can expect some new designs for Nuxt v4.)",[1147,8352,3580],{"id":3579},[1143,8354,3583],{},[1213,8356,8357],{"className":3586,"code":4006,"language":3588,"meta":1218,"style":1218},[1220,8358,8359],{"__ignoreMap":1218},[1223,8360,8361,8363,8365,8367],{"class":1225,"line":1226},[1223,8362,2037],{"class":2036},[1223,8364,2040],{"class":1254},[1223,8366,3599],{"class":1254},[1223,8368,4019],{"class":1254},[1143,8370,4022],{},[1147,8372,4938],{"id":3608},[3611,8374,8376],{"color":3613,"icon":3614,"target":3615,"to":8375},"https://github.com/nuxt/nuxt/releases/tag/v3.12.0",[1143,8377,3619,8378,2281],{},[1220,8379,8380],{},"v3.12.0",[1143,8382,8383],{},"A huge thank you to the 75+ Nuxt contributors and community members who have been part of this release. ❤️",[1143,8385,8386],{},"Finally, thank you for reading this far! We hope you enjoy v3.12, and please do let us know if you have any feedback or issues. 🙏",[1143,8388,8389],{},[1159,8390,4631],{},[2160,8392,8393],{},"html pre.shiki code .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .sV9sa, html code.shiki .sV9sa{--shiki-light:#F76D47;--shiki-default:#F76D47;--shiki-dark:#F78C6C}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 .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}",{"title":1218,"searchDepth":1233,"depth":1233,"links":8395},[8396,8397,8398,8399,8400,8401,8402,8403,8404,8405,8406,8407,8408],{"id":7900,"depth":1233,"text":7901},{"id":7976,"depth":1233,"text":7977},{"id":7995,"depth":1233,"text":7996},{"id":8023,"depth":1233,"text":8024},{"id":3967,"depth":1233,"text":3968},{"id":8108,"depth":1233,"text":8109},{"id":8139,"depth":1233,"text":8140},{"id":8166,"depth":1233,"text":8167},{"id":8231,"depth":1233,"text":8232},{"id":8273,"depth":1233,"text":8274},{"id":8330,"depth":1233,"text":8331},{"id":3579,"depth":1233,"text":3580},{"id":3608,"depth":1233,"text":4938},"2024-06-10T10:00:00.000Z","Nuxt 3.12 is out - full of improvements and preparing the way for Nuxt 4!","/assets/blog/v3.12.png",{},"/blog/v3-12",{"title":7889,"description":8410},"blog/25.v3-12","4vzb5WjIdB",{"id":8418,"title":1060,"authors":8419,"body":8422,"category":9834,"date":9835,"description":9836,"draft":108,"extension":1954,"image":9837,"meta":9838,"navigation":1739,"path":1061,"seo":9839,"stem":1062,"tags":6,"__hash__":9840},"blog/blog/24.eslint-module.md",[8420],{"name":4066,"avatar":8421,"to":4069,"twitter":4070},{"src":4068},{"type":1140,"value":8423,"toc":9816},[8424,8428,8431,8442,8461,8468,8472,8480,8489,8504,8508,8524,8533,8536,8567,8571,8578,8588,8591,8621,8625,8641,8700,8703,8707,8718,8757,8768,8780,8847,8855,8971,8984,9050,9053,9056,9081,9255,9258,9262,9271,9275,9312,9315,9479,9496,9512,9530,9533,9549,9553,9565,9571,9574,9589,9593,9596,9611,9617,9623,9627,9641,9646,9657,9729,9736,9740,9750,9761,9764,9768,9771,9798,9801,9805,9810,9813],[1147,8425,8427],{"id":8426},"tldr","TL;DR",[1143,8429,8430],{},"We revamped our ESLint integrations to support ESLint v9 with the new flat config. Along the way, we have explored many new possibilities to make it more personalized, powerful, and with better developer experience.",[1143,8432,8433,8434,8441],{},"You can run the following command to install the new ",[2006,8435,8438],{"href":8436,"rel":8437},"https://eslint.nuxt.com/packages/module",[2010],[1220,8439,8440],{},"@nuxt/eslint"," module:",[1213,8443,8446],{"className":2022,"code":8444,"filename":8445,"language":2024,"meta":1218,"style":1218},"npx nuxi module add eslint\n","Terminal",[1220,8447,8448],{"__ignoreMap":1218},[1223,8449,8450,8452,8454,8456,8458],{"class":1225,"line":1226},[1223,8451,2037],{"class":2036},[1223,8453,4554],{"class":1254},[1223,8455,4557],{"class":1254},[1223,8457,2069],{"class":1254},[1223,8459,8460],{"class":1254}," eslint\n",[1143,8462,8463,8464,2281],{},"Continue reading the story or learn more with ",[2006,8465,8467],{"href":8436,"rel":8466},[2010],"the documentation",[1147,8469,8471],{"id":8470},"background","Background",[1143,8473,8474,8479],{},[2006,8475,8478],{"href":8476,"rel":8477},"https://eslint.org/",[2010],"ESLint"," has become an essential tool for today's web development. It helps you to catch errors and enforce a consistent coding style in your project. At Nuxt, we do our best to provide an out-of-the-box experience for ESLint, making it easy to use, configure and follow the best practices we recommend.",[1143,8481,8482,8483,8488],{},"Since, both Nuxt and ESLint have evolved a lot. Historically, we ended up with ",[2006,8484,8487],{"href":8485,"rel":8486},"https://eslint.nuxt.com/guide/faq#package-disambiguation",[2010],"a few different packages and integrations for ESLint in Nuxt",", and it wasn't always obvious which one to use for what purpose. We have received a lot of feedback from our community.",[1143,8490,8491,8492,8497,8498,8503],{},"To improve the situation and also make it future-proof, we recently refreshed our ESLint integrations to support ",[2006,8493,8496],{"href":8494,"rel":8495},"https://eslint.org/blog/2024/04/eslint-v9.0.0-released/",[2010],"ESLint v9"," with the ",[2006,8499,8502],{"href":8500,"rel":8501},"https://eslint.org/docs/latest/use/configure/configuration-files",[2010],"flat config",". It opens up many more capabilities for customizing your ESLint setup, providing a more straightforward and unified experience.",[1147,8505,8507],{"id":8506},"nuxt-eslint-monorepo","Nuxt ESLint Monorepo",[1143,8509,8510,8511,8518,8519,2281],{},"We moved ESLint-related packages scattered across different repositories into a single monorepo: ",[2006,8512,8515],{"href":8513,"rel":8514},"https://github.com/nuxt/eslint",[2010],[1220,8516,8517],{},"nuxt/eslint",", with a dedicated new documentation site: ",[2006,8520,8523],{"href":8521,"rel":8522},"https://eslint.nuxt.com/",[2010],"eslint.nuxt.com",[1143,8525,8526,8527,8532],{},"To help understand the differences between each package and what to use, we also have a ",[2006,8528,8531],{"href":8529,"rel":8530},"https://eslint.nuxt.com/guide/faq",[2010],"FAQ"," page comparing them and explaining their scopes.",[1143,8534,8535],{},"This monorepo now includes:",[1852,8537,8538,8543,8558,8564],{},[1855,8539,8540,8542],{},[1220,8541,8440],{}," - The new, all-in-one ESLint module for Nuxt 3, supporting project-aware ESLint flat config and more.",[1855,8544,8545,8548,8549,4363,8553,2281],{},[1220,8546,8547],{},"@nuxt/eslint-config"," - The unopinionated but customizable shared ESLint config for Nuxt 3. Supports both ",[2006,8550,8552],{"href":8500,"rel":8551},[2010],"the flat config format",[2006,8554,8557],{"href":8555,"rel":8556},"https://eslint.org/docs/latest/use/configure/configuration-files-deprecated",[2010],"the legacy format",[1855,8559,8560,8563],{},[1220,8561,8562],{},"@nuxt/eslint-plugin"," - The ESLint plugin for Nuxt 3 provides Nuxt-specific rules and configurations.",[1855,8565,8566],{},"Two packages for Nuxt 2 in maintenance mode.",[1147,8568,8570],{"id":8569},"eslint-flat-config","ESLint Flat Config",[1143,8572,8573,8574,2281],{},"Before diving into new Nuxt integrations, let me introduce you to the concept of ",[2006,8575,8577],{"href":8500,"rel":8576},[2010],"ESLint flat config",[1143,8579,8580,8581,8584,8585,2281],{},"Flat config is a configuration format introduced in ESLint ",[1220,8582,8583],{},"v8.21.0"," as experimental, and became the default format in ",[2006,8586,8496],{"href":8494,"rel":8587},[2010],[1143,8589,8590],{},"A quick reference to differentiate:",[1852,8592,8593,8607],{},[1855,8594,8595,8598,8599,8602,8603,8606],{},[1159,8596,8597],{},"Flat config",": ",[1220,8600,8601],{},"eslint.config.js"," ",[1220,8604,8605],{},"eslint.config.mjs"," etc.",[1855,8608,8609,8598,8612,8602,8615,8602,8618,8606],{},[1159,8610,8611],{},"Legacy config",[1220,8613,8614],{},".eslintrc",[1220,8616,8617],{},".eslintrc.json",[1220,8619,8620],{},".eslintrc.js",[1155,8622,8624],{"id":8623},"why-flat-config","Why Flat Config?",[1143,8626,8627,8632,8633,8636,8637,8640],{},[2006,8628,8631],{"href":8629,"rel":8630},"https://eslint.org/blog/2022/08/new-config-system-part-1/",[2010],"This blog post from ESLint"," explains the motivation behind the flat config system in detail. In short, the legacy ",[1220,8634,8635],{},"eslintrc"," format was designed in the early time of JavaScript, when ES modules and modern JavaScript features were not yet standardized. Many implicit conventions involved, and the ",[1220,8638,8639],{},"extends"," feature makes the final config result hard to understand and predict. Which also makes shared configs hard to maintain and debug.",[1213,8642,8646],{"className":8643,"code":8644,"filename":8614,"language":8645,"meta":1218,"style":1218},"language-jsonc shiki shiki-themes material-theme-lighter material-theme-lighter material-theme-palenight","{\n  \"extends\": [\n    // Solve from `import(\"@nuxtjs/eslint-config\").then(mod => mod.default)`\n    \"@nuxtjs\",\n    // Solve from `import(\"eslint-config-vue\").then(mod => mod.default.configs[\"vue3-recommended\"])`\n    \"plugin:vue/vue3-recommended\",\n  ],\n  \"rules\": {\n    // ...\n  }\n}\n","jsonc",[1220,8647,8648,8652,8657,8662,8667,8672,8677,8682,8687,8692,8696],{"__ignoreMap":1218},[1223,8649,8650],{"class":1225,"line":1226},[1223,8651,1757],{},[1223,8653,8654],{"class":1225,"line":1233},[1223,8655,8656],{},"  \"extends\": [\n",[1223,8658,8659],{"class":1225,"line":1263},[1223,8660,8661],{},"    // Solve from `import(\"@nuxtjs/eslint-config\").then(mod => mod.default)`\n",[1223,8663,8664],{"class":1225,"line":1296},[1223,8665,8666],{},"    \"@nuxtjs\",\n",[1223,8668,8669],{"class":1225,"line":1325},[1223,8670,8671],{},"    // Solve from `import(\"eslint-config-vue\").then(mod => mod.default.configs[\"vue3-recommended\"])`\n",[1223,8673,8674],{"class":1225,"line":1355},[1223,8675,8676],{},"    \"plugin:vue/vue3-recommended\",\n",[1223,8678,8679],{"class":1225,"line":1771},[1223,8680,8681],{},"  ],\n",[1223,8683,8684],{"class":1225,"line":1783},[1223,8685,8686],{},"  \"rules\": {\n",[1223,8688,8689],{"class":1225,"line":1792},[1223,8690,8691],{},"    // ...\n",[1223,8693,8694],{"class":1225,"line":1798},[1223,8695,1990],{},[1223,8697,8698],{"class":1225,"line":1975},[1223,8699,2407],{},[1143,8701,8702],{},"The new flat config moves the plugins and configs resolution from ESLint's internal convention to the native ES module resolution. This in turn makes it more explicit and transparent, allowing you to even import it from other modules. Since the flat config is just a JavaScript module, it also opens the door for much more customization.",[1147,8704,8706],{"id":8705},"nuxt-presets-for-flat-config","Nuxt Presets for Flat Config",[1143,8708,8709,8710,8717],{},"In the latest ",[2006,8711,8714,8716],{"href":8712,"rel":8713},"https://eslint.nuxt.com/packages/config#flat-config-format",[2010],[1220,8715,8547],{}," package",", we leverage the flexibility we have to provide a factory function that allows you to customize the config presets easily in a more high-level way. Here is an example of how you can use it:",[1213,8719,8721],{"className":1669,"code":8720,"filename":8601,"language":1672,"meta":1218,"style":1218},"import { createConfigForNuxt } from '@nuxt/eslint-config/flat'\n\nexport default createConfigForNuxt()\n",[1220,8722,8723,8743,8747],{"__ignoreMap":1218},[1223,8724,8725,8727,8729,8732,8734,8736,8738,8741],{"class":1225,"line":1226},[1223,8726,1680],{"class":1679},[1223,8728,1683],{"class":1236},[1223,8730,8731],{"class":1285}," createConfigForNuxt",[1223,8733,1689],{"class":1236},[1223,8735,1692],{"class":1679},[1223,8737,1695],{"class":1236},[1223,8739,8740],{"class":1254},"@nuxt/eslint-config/flat",[1223,8742,1701],{"class":1236},[1223,8744,8745],{"class":1225,"line":1233},[1223,8746,1740],{"emptyLinePlaceholder":1739},[1223,8748,8749,8751,8753,8755],{"class":1225,"line":1263},[1223,8750,1745],{"class":1679},[1223,8752,1748],{"class":1679},[1223,8754,8731],{"class":1751},[1223,8756,1789],{"class":1285},[1143,8758,8759,8761,8762,8767],{},[1220,8760,8547],{}," starts with an unopinionated base config, which means we only include rules for best practices of TypeScript, Vue and Nuxt, and leave the rest like code style, formatting, etc for you to decide. You can also run ",[2006,8763,8766],{"href":8764,"rel":8765},"https://prettier.io/",[2010],"Prettier"," alongside for formatting with the defaults.",[1143,8769,8770,8771,8774,8775,2887],{},"The config also allows you to opt-in to more opinionated features as needed. For example, if you want ESLint to take care of the formatting as well, you can turn it on by passing ",[1220,8772,8773],{},"features.stylistic"," to the factory function (powered by ",[2006,8776,8779],{"href":8777,"rel":8778},"https://eslint.style/",[2010],"ESLint Stylistic",[1213,8781,8783],{"className":1669,"code":8782,"filename":8601,"language":1672,"meta":1218,"style":1218},"import { createConfigForNuxt } from '@nuxt/eslint-config/flat'\n\nexport default createConfigForNuxt({\n  features: {\n    stylistic: true\n  }\n})\n",[1220,8784,8785,8803,8807,8819,8828,8837,8841],{"__ignoreMap":1218},[1223,8786,8787,8789,8791,8793,8795,8797,8799,8801],{"class":1225,"line":1226},[1223,8788,1680],{"class":1679},[1223,8790,1683],{"class":1236},[1223,8792,8731],{"class":1285},[1223,8794,1689],{"class":1236},[1223,8796,1692],{"class":1679},[1223,8798,1695],{"class":1236},[1223,8800,8740],{"class":1254},[1223,8802,1701],{"class":1236},[1223,8804,8805],{"class":1225,"line":1233},[1223,8806,1740],{"emptyLinePlaceholder":1739},[1223,8808,8809,8811,8813,8815,8817],{"class":1225,"line":1263},[1223,8810,1745],{"class":1679},[1223,8812,1748],{"class":1679},[1223,8814,8731],{"class":1751},[1223,8816,1754],{"class":1285},[1223,8818,1757],{"class":1236},[1223,8820,8821,8824,8826],{"class":1225,"line":1296},[1223,8822,8823],{"class":1240},"  features",[1223,8825,1765],{"class":1236},[1223,8827,1891],{"class":1236},[1223,8829,8830,8833,8835],{"class":1225,"line":1325},[1223,8831,8832],{"class":1240},"    stylistic",[1223,8834,1765],{"class":1236},[1223,8836,3088],{"class":2928},[1223,8838,8839],{"class":1225,"line":1355},[1223,8840,1990],{"class":1236},[1223,8842,8843,8845],{"class":1225,"line":1771},[1223,8844,1801],{"class":1236},[1223,8846,1804],{"class":1285},[1143,8848,8849,8850,2887],{},"Or tweak your preferences with an options object (",[2006,8851,8854],{"href":8852,"rel":8853},"https://eslint.style/guide/config-presets#configuration-factory",[2010],"learn more with the options here",[1213,8856,8858],{"className":1669,"code":8857,"filename":8601,"language":1672,"meta":1218,"style":1218},"import { createConfigForNuxt } from '@nuxt/eslint-config/flat'\n\nexport default createConfigForNuxt({\n  features: {\n    stylistic: {\n      semi: false,\n      indent: 2, // 4 or 'tab'\n      quotes: 'single',\n      // ... and more\n    }\n  }\n})\n",[1220,8859,8860,8878,8882,8894,8902,8910,8921,8936,8952,8957,8961,8965],{"__ignoreMap":1218},[1223,8861,8862,8864,8866,8868,8870,8872,8874,8876],{"class":1225,"line":1226},[1223,8863,1680],{"class":1679},[1223,8865,1683],{"class":1236},[1223,8867,8731],{"class":1285},[1223,8869,1689],{"class":1236},[1223,8871,1692],{"class":1679},[1223,8873,1695],{"class":1236},[1223,8875,8740],{"class":1254},[1223,8877,1701],{"class":1236},[1223,8879,8880],{"class":1225,"line":1233},[1223,8881,1740],{"emptyLinePlaceholder":1739},[1223,8883,8884,8886,8888,8890,8892],{"class":1225,"line":1263},[1223,8885,1745],{"class":1679},[1223,8887,1748],{"class":1679},[1223,8889,8731],{"class":1751},[1223,8891,1754],{"class":1285},[1223,8893,1757],{"class":1236},[1223,8895,8896,8898,8900],{"class":1225,"line":1296},[1223,8897,8823],{"class":1240},[1223,8899,1765],{"class":1236},[1223,8901,1891],{"class":1236},[1223,8903,8904,8906,8908],{"class":1225,"line":1325},[1223,8905,8832],{"class":1240},[1223,8907,1765],{"class":1236},[1223,8909,1891],{"class":1236},[1223,8911,8912,8915,8917,8919],{"class":1225,"line":1355},[1223,8913,8914],{"class":1240},"      semi",[1223,8916,1765],{"class":1236},[1223,8918,5299],{"class":2928},[1223,8920,1780],{"class":1236},[1223,8922,8923,8926,8928,8931,8933],{"class":1225,"line":1771},[1223,8924,8925],{"class":1240},"      indent",[1223,8927,1765],{"class":1236},[1223,8929,8930],{"class":6166}," 2",[1223,8932,2333],{"class":1236},[1223,8934,8935],{"class":1229}," // 4 or 'tab'\n",[1223,8937,8938,8941,8943,8945,8948,8950],{"class":1225,"line":1783},[1223,8939,8940],{"class":1240},"      quotes",[1223,8942,1765],{"class":1236},[1223,8944,1695],{"class":1236},[1223,8946,8947],{"class":1254},"single",[1223,8949,1957],{"class":1236},[1223,8951,1780],{"class":1236},[1223,8953,8954],{"class":1225,"line":1792},[1223,8955,8956],{"class":1229},"      // ... and more\n",[1223,8958,8959],{"class":1225,"line":1798},[1223,8960,1984],{"class":1236},[1223,8962,8963],{"class":1225,"line":1975},[1223,8964,1990],{"class":1236},[1223,8966,8967,8969],{"class":1225,"line":1981},[1223,8968,1801],{"class":1236},[1223,8970,1804],{"class":1285},[1143,8972,8973,8974,8979,8980,8983],{},"And if you are ",[2006,8975,8978],{"href":8976,"rel":8977},"https://nuxt.com/docs/guide/going-further/modules",[2010],"authoring a Nuxt Module",", you can turn on ",[1220,8981,8982],{},"features.tooling"," to enable the rules for the Nuxt module development:",[1213,8985,8987],{"className":1669,"code":8986,"filename":8601,"language":1672,"meta":1218,"style":1218},"import { createConfigForNuxt } from '@nuxt/eslint-config/flat'\n\nexport default createConfigForNuxt({\n  features: {\n    tooling: true\n  }\n})\n",[1220,8988,8989,9007,9011,9023,9031,9040,9044],{"__ignoreMap":1218},[1223,8990,8991,8993,8995,8997,8999,9001,9003,9005],{"class":1225,"line":1226},[1223,8992,1680],{"class":1679},[1223,8994,1683],{"class":1236},[1223,8996,8731],{"class":1285},[1223,8998,1689],{"class":1236},[1223,9000,1692],{"class":1679},[1223,9002,1695],{"class":1236},[1223,9004,8740],{"class":1254},[1223,9006,1701],{"class":1236},[1223,9008,9009],{"class":1225,"line":1233},[1223,9010,1740],{"emptyLinePlaceholder":1739},[1223,9012,9013,9015,9017,9019,9021],{"class":1225,"line":1263},[1223,9014,1745],{"class":1679},[1223,9016,1748],{"class":1679},[1223,9018,8731],{"class":1751},[1223,9020,1754],{"class":1285},[1223,9022,1757],{"class":1236},[1223,9024,9025,9027,9029],{"class":1225,"line":1296},[1223,9026,8823],{"class":1240},[1223,9028,1765],{"class":1236},[1223,9030,1891],{"class":1236},[1223,9032,9033,9036,9038],{"class":1225,"line":1325},[1223,9034,9035],{"class":1240},"    tooling",[1223,9037,1765],{"class":1236},[1223,9039,3088],{"class":2928},[1223,9041,9042],{"class":1225,"line":1355},[1223,9043,1990],{"class":1236},[1223,9045,9046,9048],{"class":1225,"line":1771},[1223,9047,1801],{"class":1236},[1223,9049,1804],{"class":1285},[1143,9051,9052],{},"...and so on. The factory function in flat config allows the presets to cover the complexity of the underlying ESLint configuration, and provide high-level and user-friendly abstractions for end users to customize. All this without requiring users to worry about the internal details.",[1143,9054,9055],{},"While this approach offers you a Prettier-like experience with minimal configurations (because it's powered by ESLint), you still get the full flexibility to customize and override fine-grained rules and plugins as needed.",[1143,9057,9058,9059,9066,9067,9074,9075,9077,9078,9080],{},"We also made a ",[2006,9060,9063],{"href":9061,"rel":9062},"https://github.com/antfu/eslint-flat-config-utils#composer",[2010],[1220,9064,9065],{},"FlatConfigComposer"," utility from ",[2006,9068,9071],{"href":9069,"rel":9070},"https://github.com/antfu/eslint-flat-config-utils",[2010],[1220,9072,9073],{},"eslint-flat-config-utils"," to make it even easier to override and extend the flat config. The factory function in ",[1220,9076,8740],{}," returns a ",[1220,9079,9065],{}," instance:",[1213,9082,9084],{"className":1669,"code":9083,"filename":8601,"language":1672,"meta":1218,"style":1218},"import { createConfigForNuxt } from '@nuxt/eslint-config/flat'\n\nexport default createConfigForNuxt({\n  // ...options for Nuxt integration\n})\n  .append(\n    // ...append other flat config items\n  )\n  .prepend(\n    // ...prepend other flat config items before the base config\n  )\n  // override a specific config item based on their name\n  .override(\n    'nuxt/typescript', // specify the name of the target config, or index\n    {\n      rules: {\n        // ...override the rules\n        '@typescript-eslint/no-unsafe-assignment': 'off'\n      }\n    }\n  )\n  // an so on, operations are chainable\n",[1220,9085,9086,9104,9108,9120,9125,9131,9142,9147,9152,9161,9166,9170,9175,9184,9199,9204,9213,9218,9237,9241,9245,9249],{"__ignoreMap":1218},[1223,9087,9088,9090,9092,9094,9096,9098,9100,9102],{"class":1225,"line":1226},[1223,9089,1680],{"class":1679},[1223,9091,1683],{"class":1236},[1223,9093,8731],{"class":1285},[1223,9095,1689],{"class":1236},[1223,9097,1692],{"class":1679},[1223,9099,1695],{"class":1236},[1223,9101,8740],{"class":1254},[1223,9103,1701],{"class":1236},[1223,9105,9106],{"class":1225,"line":1233},[1223,9107,1740],{"emptyLinePlaceholder":1739},[1223,9109,9110,9112,9114,9116,9118],{"class":1225,"line":1263},[1223,9111,1745],{"class":1679},[1223,9113,1748],{"class":1679},[1223,9115,8731],{"class":1751},[1223,9117,1754],{"class":1285},[1223,9119,1757],{"class":1236},[1223,9121,9122],{"class":1225,"line":1296},[1223,9123,9124],{"class":1229},"  // ...options for Nuxt integration\n",[1223,9126,9127,9129],{"class":1225,"line":1325},[1223,9128,1801],{"class":1236},[1223,9130,1804],{"class":1285},[1223,9132,9133,9136,9139],{"class":1225,"line":1355},[1223,9134,9135],{"class":1236},"  .",[1223,9137,9138],{"class":1751},"append",[1223,9140,9141],{"class":1285},"(\n",[1223,9143,9144],{"class":1225,"line":1771},[1223,9145,9146],{"class":1229},"    // ...append other flat config items\n",[1223,9148,9149],{"class":1225,"line":1783},[1223,9150,9151],{"class":1285},"  )\n",[1223,9153,9154,9156,9159],{"class":1225,"line":1792},[1223,9155,9135],{"class":1236},[1223,9157,9158],{"class":1751},"prepend",[1223,9160,9141],{"class":1285},[1223,9162,9163],{"class":1225,"line":1798},[1223,9164,9165],{"class":1229},"    // ...prepend other flat config items before the base config\n",[1223,9167,9168],{"class":1225,"line":1975},[1223,9169,9151],{"class":1285},[1223,9171,9172],{"class":1225,"line":1981},[1223,9173,9174],{"class":1229},"  // override a specific config item based on their name\n",[1223,9176,9177,9179,9182],{"class":1225,"line":1987},[1223,9178,9135],{"class":1236},[1223,9180,9181],{"class":1751},"override",[1223,9183,9141],{"class":1285},[1223,9185,9186,9189,9192,9194,9196],{"class":1225,"line":1993},[1223,9187,9188],{"class":1236},"    '",[1223,9190,9191],{"class":1254},"nuxt/typescript",[1223,9193,1957],{"class":1236},[1223,9195,2333],{"class":1236},[1223,9197,9198],{"class":1229}," // specify the name of the target config, or index\n",[1223,9200,9201],{"class":1225,"line":2720},[1223,9202,9203],{"class":1236},"    {\n",[1223,9205,9206,9209,9211],{"class":1225,"line":2742},[1223,9207,9208],{"class":1240},"      rules",[1223,9210,1765],{"class":1236},[1223,9212,1891],{"class":1236},[1223,9214,9215],{"class":1225,"line":6685},[1223,9216,9217],{"class":1229},"        // ...override the rules\n",[1223,9219,9220,9223,9226,9228,9230,9232,9235],{"class":1225,"line":6695},[1223,9221,9222],{"class":1236},"        '",[1223,9224,9225],{"class":1240},"@typescript-eslint/no-unsafe-assignment",[1223,9227,1957],{"class":1236},[1223,9229,1765],{"class":1236},[1223,9231,1695],{"class":1236},[1223,9233,9234],{"class":1254},"off",[1223,9236,1701],{"class":1236},[1223,9238,9239],{"class":1225,"line":6714},[1223,9240,1978],{"class":1236},[1223,9242,9243],{"class":1225,"line":6719},[1223,9244,1984],{"class":1236},[1223,9246,9247],{"class":1225,"line":6724},[1223,9248,9151],{"class":1285},[1223,9250,9252],{"class":1225,"line":9251},22,[1223,9253,9254],{"class":1229},"  // an so on, operations are chainable\n",[1143,9256,9257],{},"With this approach, we get the best of both worlds: the simplicity and high-level abstraction for easy to use, and the power for customization and fine-tuning.",[1147,9259,9261],{"id":9260},"nuxt-eslint-module","Nuxt ESLint Module",[1143,9263,9264,9265,9270],{},"Taking this even further, we made the new, all-in-one ",[2006,9266,9268,4557],{"href":8436,"rel":9267},[2010],[1220,9269,8440],{}," for Nuxt 3. It leverages Nuxt's context to generate project-aware and type-safe ESLint configurations for your project.",[1155,9272,9274],{"id":9273},"project-aware-rules","Project-aware Rules",[1143,9276,9277,9278,9283,9284,9291,9292,9299,9300,9303,9304,5062,9306,5062,9308,9311],{},"We know that Vue's Style Guide suggests the use of ",[2006,9279,9282],{"href":9280,"rel":9281},"https://vuejs.org/style-guide/rules-essential.html#use-multi-word-component-names",[2010],"multi-word names for components"," to avoid conflicts with existing and future HTML elements. Thus, in ",[2006,9285,9288],{"href":9286,"rel":9287},"https://github.com/vuejs/eslint-plugin-vue",[2010],[1220,9289,9290],{},"eslint-plugin-vue",", we have the rule ",[2006,9293,9296],{"href":9294,"rel":9295},"https://eslint.vuejs.org/rules/multi-word-component-names.html",[2010],[1220,9297,9298],{},"vue/multi-word-component-names"," enabled by default. It's a good practice to follow, but we know that in a Nuxt project, not all ",[1220,9301,9302],{},".vue"," files are registered as components. Files like ",[1220,9305,248],{},[1220,9307,5115],{},[1220,9309,9310],{},"layouts/default.vue",", etc. are not available as components in other Vue files, and the rule will be irrelevant to them.",[1143,9313,9314],{},"Usually, we could turn off the rule for those files like:",[1213,9316,9320],{"className":9317,"code":9318,"filename":8601,"language":9319,"meta":1218,"style":1218},"language-js shiki shiki-themes material-theme-lighter material-theme-lighter material-theme-palenight","export default [\n  {\n    files: ['*.vue'],\n    rules: {\n      'vue/multi-word-component-names': 'error'\n    }\n  },\n  {\n    files: ['app.vue', 'error.vue', 'pages/**/*.vue', 'layouts/**/*.vue'],\n    rules: {\n      // disable the rule for these files\n      'vue/multi-word-component-names': 'off'\n    }\n  }\n]\n","js",[1220,9321,9322,9330,9335,9355,9364,9381,9385,9389,9393,9437,9445,9450,9466,9470,9474],{"__ignoreMap":1218},[1223,9323,9324,9326,9328],{"class":1225,"line":1226},[1223,9325,1745],{"class":1679},[1223,9327,1748],{"class":1679},[1223,9329,1768],{"class":1285},[1223,9331,9332],{"class":1225,"line":1233},[1223,9333,9334],{"class":1236},"  {\n",[1223,9336,9337,9340,9342,9344,9346,9349,9351,9353],{"class":1225,"line":1263},[1223,9338,9339],{"class":1240},"    files",[1223,9341,1765],{"class":1236},[1223,9343,2848],{"class":1285},[1223,9345,1957],{"class":1236},[1223,9347,9348],{"class":1254},"*.vue",[1223,9350,1957],{"class":1236},[1223,9352,2858],{"class":1285},[1223,9354,1780],{"class":1236},[1223,9356,9357,9360,9362],{"class":1225,"line":1296},[1223,9358,9359],{"class":1240},"    rules",[1223,9361,1765],{"class":1236},[1223,9363,1891],{"class":1236},[1223,9365,9366,9369,9371,9373,9375,9377,9379],{"class":1225,"line":1325},[1223,9367,9368],{"class":1236},"      '",[1223,9370,9298],{"class":1240},[1223,9372,1957],{"class":1236},[1223,9374,1765],{"class":1236},[1223,9376,1695],{"class":1236},[1223,9378,1621],{"class":1254},[1223,9380,1701],{"class":1236},[1223,9382,9383],{"class":1225,"line":1355},[1223,9384,1984],{"class":1236},[1223,9386,9387],{"class":1225,"line":1771},[1223,9388,3312],{"class":1236},[1223,9390,9391],{"class":1225,"line":1783},[1223,9392,9334],{"class":1236},[1223,9394,9395,9397,9399,9401,9403,9405,9407,9409,9411,9413,9415,9417,9419,9422,9424,9426,9428,9431,9433,9435],{"class":1225,"line":1792},[1223,9396,9339],{"class":1240},[1223,9398,1765],{"class":1236},[1223,9400,2848],{"class":1285},[1223,9402,1957],{"class":1236},[1223,9404,248],{"class":1254},[1223,9406,1957],{"class":1236},[1223,9408,2333],{"class":1236},[1223,9410,1695],{"class":1236},[1223,9412,256],{"class":1254},[1223,9414,1957],{"class":1236},[1223,9416,2333],{"class":1236},[1223,9418,1695],{"class":1236},[1223,9420,9421],{"class":1254},"pages/**/*.vue",[1223,9423,1957],{"class":1236},[1223,9425,2333],{"class":1236},[1223,9427,1695],{"class":1236},[1223,9429,9430],{"class":1254},"layouts/**/*.vue",[1223,9432,1957],{"class":1236},[1223,9434,2858],{"class":1285},[1223,9436,1780],{"class":1236},[1223,9438,9439,9441,9443],{"class":1225,"line":1798},[1223,9440,9359],{"class":1240},[1223,9442,1765],{"class":1236},[1223,9444,1891],{"class":1236},[1223,9446,9447],{"class":1225,"line":1975},[1223,9448,9449],{"class":1229},"      // disable the rule for these files\n",[1223,9451,9452,9454,9456,9458,9460,9462,9464],{"class":1225,"line":1981},[1223,9453,9368],{"class":1236},[1223,9455,9298],{"class":1240},[1223,9457,1957],{"class":1236},[1223,9459,1765],{"class":1236},[1223,9461,1695],{"class":1236},[1223,9463,9234],{"class":1254},[1223,9465,1701],{"class":1236},[1223,9467,9468],{"class":1225,"line":1987},[1223,9469,1984],{"class":1236},[1223,9471,9472],{"class":1225,"line":1993},[1223,9473,1990],{"class":1236},[1223,9475,9476],{"class":1225,"line":2720},[1223,9477,9478],{"class":1285},"]\n",[1143,9480,9481,9482,7856,9487,9492,9493,2281],{},"It should work for the majority of the cases. However, we know that in Nuxt you can ",[2006,9483,9486],{"href":9484,"rel":9485},"https://nuxt.com/docs/api/nuxt-config#dir",[2010],"customize the path for each directory",[2006,9488,9491],{"href":9489,"rel":9490},"https://nuxt.com/docs/getting-started/layers",[2010],"layers"," allow you to have multiple sources for each directory. This means the linter rules will be less accurate and potentially cause users extra effort to keep them aligned ",[1159,9494,9495],{},"manually",[1143,9497,9498,9499,9506,9507,4363,9509,9511],{},"Similarly, we want to have ",[2006,9500,9503],{"href":9501,"rel":9502},"https://eslint.vuejs.org/rules/no-multiple-template-root.html",[2010],[1220,9504,9505],{},"vue/no-multiple-template-root"," enabled only for ",[1220,9508,207],{},[1220,9510,191],{},", etc. As the cases grow, it becomes unrealistic to ask users to maintain the rules manually.",[1143,9513,9514,9515,9517,9518,9525,9526,9529],{},"That's where the magic of ",[1220,9516,8440],{}," comes in! It leverages Nuxt's context to generate the configurations and rules specific to your project structure. Very similar to the ",[2006,9519,9522],{"href":9520,"rel":9521},"http://nuxt.com/docs/guide/concepts/typescript#auto-generated-types",[2010],[1220,9523,9524],{},".nuxt/tsconfig.json"," Nuxt provides, you now also have the project-aware ",[1220,9527,9528],{},".nuxt/eslint.config.mjs"," to extend from.",[1143,9531,9532],{},"To use it, you can add the module to your Nuxt project:",[1213,9534,9535],{"className":2022,"code":8444,"filename":8445,"language":2024,"meta":1218,"style":1218},[1220,9536,9537],{"__ignoreMap":1218},[1223,9538,9539,9541,9543,9545,9547],{"class":1225,"line":1226},[1223,9540,2037],{"class":2036},[1223,9542,4554],{"class":1254},[1223,9544,4557],{"class":1254},[1223,9546,2069],{"class":1254},[1223,9548,8460],{"class":1254},[1155,9550,9552],{"id":9551},"config-inspector-devtools-integrations","Config Inspector DevTools Integrations",[1143,9554,9555,9556,9561,9562,9564],{},"During the migrations and research for the new flat config, I came up with the idea to make an interactive UI inspector for the flat config and make the configurations more transparent and easier to understand. We have integrated it into ",[2006,9557,9560],{"href":9558,"rel":9559},"https://github.com/nuxt/devtools",[2010],"Nuxt DevTools"," when you have the ",[1220,9563,8440],{}," module installed so you easily access it whenever you need it.",[1143,9566,9567],{},[2243,9568],{"alt":9569,"src":9570},"Screenshot of ESLint Config Inspector running as a tab in Nuxt DevTools","/assets/blog/nuxt-eslint-inspector.png",[1143,9572,9573],{},"The inspector allows you to see the final resolved configurations, rules and plugins that have been enabled, and do quick matches to see how rules and configurations have applied to specific files. It's great for debugging and learning how ESLint works in your project.",[1143,9575,9576,9577,9582,9583,9588],{},"We are delighted that the ESLint team also finds it useful and is interested in having it for the broader ESLint community. We later joined the effort and made it ",[2006,9578,9581],{"href":9579,"rel":9580},"https://github.com/eslint/config-inspector",[2010],"the official ESLint Config Inspector"," (it's built with Nuxt, by the way). You can read ",[2006,9584,9587],{"href":9585,"rel":9586},"https://eslint.org/blog/2024/04/eslint-config-inspector/",[2010],"this announcement post"," for more details.",[1155,9590,9592],{"id":9591},"type-generation-for-rules","Type Generation for Rules",[1143,9594,9595],{},"One of the main pain points of configuring ESLint was the leak of type information for the rules and configurations. It's hard to know what options are available for a specific rule, and it would require you to jump around the documentation for every rule to figure that out.",[1143,9597,9598,9599,9606,9607,9610],{},"Thanks again for the new flat config being dynamic with so many possibilities. We figured out a new tool, ",[2006,9600,9603],{"href":9601,"rel":9602},"https://github.com/antfu/eslint-typegen",[2010],[1220,9604,9605],{},"eslint-typegen",", that we could generate the corresponding types from rules configuration schema for each rule ",[1159,9608,9609],{},"based on the actual plugins you are using",". This means it's a universal solution that works for any ESLint plugins, and the types are always accurate and up-to-date.",[1143,9612,9613,9614,9616],{},"In the ",[1220,9615,8440],{}," module, this feature is integrated out-of-box, so that you will get this awesome experience right away:",[1143,9618,9619],{},[2243,9620],{"alt":9621,"src":9622},"Screenshot of VS Code that showcases the type check and autocomplete with ESLint rules config","/assets/blog/nuxt-eslint-typegen.png",[1155,9624,9626],{"id":9625},"dev-server-checker","Dev Server Checker",[1143,9628,9629,9630,9637,9638,9640],{},"With the new module, we took the chance to merge the ",[2006,9631,9634],{"href":9632,"rel":9633},"https://github.com/nuxt-modules/eslint",[2010],[1220,9635,9636],{},"@nuxtjs/eslint-module"," and the dev server checker for ESLint into the new ",[1220,9639,8440],{}," module as an opt-in feature.",[7747,9642,9643],{},[1143,9644,9645],{},"You might not need this feature most of the time, as your editor integration should already provide ESLint diagnostics right in your editor. However, for some teams that work with different editors and want to ensure ESLint is always running, being able to run ESLint within the dev server might be helpful in some cases.",[1143,9647,9648,9649,9652,9653,9656],{},"To enable it, you can set the ",[1220,9650,9651],{},"checker"," option to ",[1220,9654,9655],{},"true"," in the module options:",[1213,9658,9660],{"className":1669,"code":9659,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  modules: [\n    '@nuxt/eslint'\n  ],\n  eslint: {\n    checker: true // \u003C---\n  }\n})\n",[1220,9661,9662,9674,9683,9691,9698,9707,9719,9723],{"__ignoreMap":1218},[1223,9663,9664,9666,9668,9670,9672],{"class":1225,"line":1226},[1223,9665,1745],{"class":1679},[1223,9667,1748],{"class":1679},[1223,9669,2820],{"class":1751},[1223,9671,1754],{"class":1285},[1223,9673,1757],{"class":1236},[1223,9675,9676,9679,9681],{"class":1225,"line":1233},[1223,9677,9678],{"class":1240},"  modules",[1223,9680,1765],{"class":1236},[1223,9682,1768],{"class":1285},[1223,9684,9685,9687,9689],{"class":1225,"line":1263},[1223,9686,9188],{"class":1236},[1223,9688,8440],{"class":1254},[1223,9690,1701],{"class":1236},[1223,9692,9693,9696],{"class":1225,"line":1296},[1223,9694,9695],{"class":1285},"  ]",[1223,9697,1780],{"class":1236},[1223,9699,9700,9703,9705],{"class":1225,"line":1325},[1223,9701,9702],{"class":1240},"  eslint",[1223,9704,1765],{"class":1236},[1223,9706,1891],{"class":1236},[1223,9708,9709,9712,9714,9716],{"class":1225,"line":1355},[1223,9710,9711],{"class":1240},"    checker",[1223,9713,1765],{"class":1236},[1223,9715,2929],{"class":2928},[1223,9717,9718],{"class":1229}," // \u003C---\n",[1223,9720,9721],{"class":1225,"line":1771},[1223,9722,1990],{"class":1236},[1223,9724,9725,9727],{"class":1225,"line":1783},[1223,9726,1801],{"class":1236},[1223,9728,1804],{"class":1285},[1143,9730,9731,9732,2281],{},"Whenever you get some ESLint errors, you will see a warning in the console and the browser. To learn more about this feature, you can check the ",[2006,9733,2147],{"href":9734,"rel":9735},"https://eslint.nuxt.com/packages/module#dev-server-checker",[2010],[1155,9737,9739],{"id":9738},"module-hooks","Module Hooks",[1143,9741,9742,9743,9745,9746,9749],{},"Since we are now in the Nuxt module with the codegen capabilities and the project-aware configurations, we can actually do a lot more interesting things with this. One is that we can allow modules to contribute to the ESLint configurations as well. Imagine that in the future, when you install a Nuxt module like ",[1220,9744,8224],{}," it can automatically enable specific ESLint rules for i18n-related files, or when you install something like ",[1220,9747,9748],{},"@pinia/nuxt"," it can install the Pinia ESLint plugin to enforce the best practices for Pinia, etc.",[1143,9751,9752,9753,9760],{},"As an experiment, we made a module ",[2006,9754,9757],{"href":9755,"rel":9756},"https://github.com/antfu/nuxt-eslint-auto-explicit-import",[2010],[1220,9758,9759],{},"nuxt-eslint-auto-explicit-import"," that can do auto inserts for the auto-imports registered in your Nuxt project with a preconfigured ESLint preset. So that you can get the same nice developer experience with auto-imports on using APIs, but still have the auto-inserted explicit imports in your codebase.",[1143,9762,9763],{},"This is still in the early stages, and we are still exploring the possibilities and best practices. But we are very excited about the potential and the opportunities it opens up. We will collaborate with the community to see how we can make the most out of it. If you have any ideas or feedback, please do not hesitate to share them with us!",[1147,9765,9767],{"id":9766},"ecosystem","Ecosystem",[1143,9769,9770],{},"At Nuxt, we care a lot about the ecosystem and the community as always. During our explorations to adopt the new flat config and improve the developer experience, we made quite a few tools to reach that goal. All of them are general-purposed and can be used outside of Nuxt:",[1852,9772,9773,9782,9790],{},[1855,9774,9775,9781],{},[2006,9776,9778],{"href":9579,"rel":9777},[2010],[1220,9779,9780],{},"@eslint/config-inspector"," - The official ESLint Config Inspector, provides interactive UI for your configs.",[1855,9783,9784,9789],{},[2006,9785,9787],{"href":9601,"rel":9786},[2010],[1220,9788,9605],{}," - Generate TypeScript types for ESLint rules based on the actual plugins you are using.",[1855,9791,9792,9797],{},[2006,9793,9795],{"href":9069,"rel":9794},[2010],[1220,9796,9073],{}," - Utilities for managing and composing ESLint flat configs.",[1143,9799,9800],{},"We are committed to supporting the broader community and collaborating with developers to improve these tools and expand their possibilities. We are excited to see how these tools can benefit the ESLint ecosystem and contribute to the overall developer experience.",[1147,9802,9804],{"id":9803},"the-future","The Future",[7733,9806,9807],{},[1143,9808,9809],{},"The flat config format is still fairly new, and ESLint v9 was just released a couple of weeks ago. Plugins and the community are gradually catching up to the new format. It's still in the phase of exploration and experimentation.",[1143,9811,9812],{},"Looking ahead, we are eager to see how the ESLint ecosystem will continue to evolve and how we can leverage new capabilities and possibilities to further enhance Nuxt's developer experience. We are dedicated to providing a seamless and powerful development environment for Nuxt users, and we will continue to explore new ideas and collaborate with the community to achieve this goal.",[2160,9814,9815],{},"html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}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 .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .sagxc, html code.shiki .sagxc{--shiki-light:#FF5370;--shiki-default:#FF5370;--shiki-dark:#FF9CAC}html pre.shiki code .sV9sa, html code.shiki .sV9sa{--shiki-light:#F76D47;--shiki-default:#F76D47;--shiki-dark:#F78C6C}html pre.shiki code .svXlt, html code.shiki .svXlt{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":1218,"searchDepth":1233,"depth":1233,"links":9817},[9818,9819,9820,9821,9824,9825,9832,9833],{"id":8426,"depth":1233,"text":8427},{"id":8470,"depth":1233,"text":8471},{"id":8506,"depth":1233,"text":8507},{"id":8569,"depth":1233,"text":8570,"children":9822},[9823],{"id":8623,"depth":1263,"text":8624},{"id":8705,"depth":1233,"text":8706},{"id":9260,"depth":1233,"text":9261,"children":9826},[9827,9828,9829,9830,9831],{"id":9273,"depth":1263,"text":9274},{"id":9551,"depth":1263,"text":9552},{"id":9591,"depth":1263,"text":9592},{"id":9625,"depth":1263,"text":9626},{"id":9738,"depth":1263,"text":9739},{"id":9766,"depth":1233,"text":9767},{"id":9803,"depth":1233,"text":9804},"Article","2024-04-10T00:00:00.000Z","We revamped our ESLint integrations to support ESLint v9 with the flat config, as well as a new module with many more capabilities.","/assets/blog/nuxt-eslint-refreshed.png",{},{"title":1060,"description":9836},"xSlrT5lujZ",{"id":9842,"title":9843,"authors":9844,"body":9849,"category":2176,"date":10411,"description":10412,"draft":108,"extension":1954,"image":10413,"meta":10414,"navigation":108,"path":10415,"seo":10416,"stem":10417,"tags":6,"__hash__":10418},"blog/blog/23.looking-forward-2024.md","Nuxt: Looking forward",[9845,9847],{"name":2190,"avatar":9846,"to":2193},{"src":2192},{"name":1130,"avatar":9848,"to":1133},{"src":1132},{"type":1140,"value":9850,"toc":10401},[9851,9855,9863,9870,9873,9952,9961,9979,10011,10025,10044,10048,10051,10054,10058,10061,10075,10078,10113,10116,10119,10166,10170,10173,10181,10223,10226,10229,10233,10240,10253,10259,10269,10272,10276,10279,10297,10301,10304,10307,10327,10330,10337,10340,10355,10360,10363,10372,10379,10383,10390,10393,10395,10398],[1147,9852,9854],{"id":9853},"a-review-of-2023-sébastien","A Review of 2023 - Sébastien",[1143,9856,9857,9858,9862],{},"In January 2023, Daniel set out ",[2006,9859,9860],{"href":1053},[1159,9861,1052],{},". We achieved most of the goals we set out to accomplish. Some of them are missing and we will tackle them this year!",[1143,9864,9865,9866,9869],{},"It was a productive year and the team shipped ",[1159,9867,9868],{},"9 minor releases",": from v3.1 to v3.9.",[1143,9871,9872],{},"In the first 365 days, Nuxt 3 reached new milestones:",[1852,9874,9875,9889,9899,9912,9924,9931,9938],{},[1855,9876,9877,8602,9880,9883,9884,9888],{},[9878,9879],"icon",{"name":274},[1159,9881,9882],{},"49,5K stars"," on GitHub (",[2006,9885,9887],{"href":8347,"rel":9886},[2010],"add yours"," 😊)",[1855,9890,9891,9894,9895,9898],{},[9878,9892],{"name":9893},"i-lucide-download","  ",[1159,9896,9897],{},"27M downloads"," on npm",[1855,9900,9901,8602,9904,9907,9908],{},[9878,9902],{"name":9903},"i-lucide-user-plus",[1159,9905,9906],{},"612 contributors"," on the ",[2006,9909,9911],{"href":8347,"rel":9910},[2010],"nuxt repository",[1855,9913,9914,8602,9917,9920,9921],{},[9878,9915],{"name":9916},"i-lucide-puzzle",[1159,9918,9919],{},"184 modules"," created by ",[1159,9922,9923],{},"142 maintainers",[1855,9925,9926,8602,9928],{},[9878,9927],{"name":102},[1159,9929,9930],{},"2,423 closed issues",[1855,9932,9933,8602,9935],{},[9878,9934],{"name":918},[1159,9936,9937],{},"1,728 merged pull request",[1855,9939,9940,8602,9943,9946,9947],{},[9878,9941],{"name":9942},"i-simple-icons-discord",[1159,9944,9945],{},"26,300 members"," on ",[2006,9948,9951],{"href":9949,"rel":9950},"https://chat.nuxt.dev",[2010],"Discord",[1143,9953,9954,9955,9960],{},"End of October, Nuxt 3 downloads ",[2006,9956,9959],{"href":9957,"rel":9958},"https://x.com/Atinux/status/1731980841142669379",[2010],"surpassed Nuxt 2 downloads"," 🚀.",[1143,9962,9963,9964,9969,9970,6381,9974,9978],{},"The same month, we released ",[2006,9965,9968],{"href":9966,"rel":9967},"https://image.nuxt.com",[2010],"Nuxt Image 1.0"," with Nuxt 3 support and new features to make sure your website stays performant when using Images. Nuxt now auto-installs it as soon as you start using the ",[2006,9971,9972],{"href":414},[1220,9973,413],{},[2006,9975,9976],{"href":373},[1220,9977,372],{}," component.",[1143,9980,9981,9982,9984,9985,5062,9990,5062,9995,5062,10000,5062,10005,10010],{},"We shipped ",[2006,9983,9560],{"href":1049},", leveling up the Developer Experience we can expect from a Web framework. I am happy to see that we inspired other frameworks to adopt a similar approach: ",[2006,9986,9989],{"href":9987,"rel":9988},"https://x.com/vuejs/status/1741032977919053865",[2010],"Vue DevTools",[2006,9991,9994],{"href":9992,"rel":9993},"https://x.com/xinyao27/status/1741447261132145133",[2010],"Next DevTools",[2006,9996,9999],{"href":9997,"rel":9998},"https://x.com/AlemTuzlak59192/status/1741903214860009539",[2010],"Remix DevTools",[2006,10001,10004],{"href":10002,"rel":10003},"https://github.com/pheno-agency/vite-plugin-devtools",[2010],"Vite Plugin DevTools",[2006,10006,10009],{"href":10007,"rel":10008},"https://x.com/n_moore/status/1732164645778071888",[2010],"Astro Dev Toolbar"," and more.",[1143,10012,10013,10014,10018,10019,10024],{},"After many months of building our UI library internally, ",[2006,10015,1125],{"href":10016,"rel":10017},"https://github.com/benjamincanac",[2010]," open sourced ",[2006,10020,10023],{"href":10021,"rel":10022},"https://ui.nuxt.com",[2010],"Nuxt UI"," to let you create websites at a faster pace with highly customizable components built with TailwindCSS.",[1143,10026,10027,10031,10032,10037,10038,10043],{},[2006,10028,4387],{"href":10029,"rel":10030},"http://content.nuxt.com",[2010]," has had 10 minor releases with various improvements: from performance to the MDC syntax. We have some ongoing work to better support ",[2006,10033,10036],{"href":10034,"rel":10035},"https://nuxt.com/blog/nuxt-on-the-edge",[2010],"edge rendering"," in the future. At the same time, the NuxtLabs team is working on ",[2006,10039,10042],{"href":10040,"rel":10041},"https://nuxt.studio",[2010],"Nuxt Studio"," to let users edit Markdown files with a Notion-like editor while keeping your content inside your git repository.",[1147,10045,10047],{"id":10046},"looking-forward-into-2024-daniel","Looking forward into 2024 - Daniel",[1143,10049,10050],{},"We are well into 2024, and this update is definitely overdue!",[1143,10052,10053],{},"Here are a few thoughts on the direction that I'll be seeking to lead Nuxt in over the next year.",[1155,10055,10057],{"id":10056},"continued-development-and-reimagination","Continued development and reimagination",[1143,10059,10060],{},"I would love to see us continuing to adapt our best practices to the changing needs of the ecosystem, expand the boundaries of what good DX could be, and improve Nuxt.",[1143,10062,10063,10064,10069,10070,3681],{},"I am really pleased at what we currently offer in Nuxt. But I would never want to rest on our laurels. We need to keep pursuing new possibilities that appear as the web platform develops. We've committed to ",[2006,10065,10068],{"href":10066,"rel":10067},"https://developer.mozilla.org/en-US/docs/Glossary/Baseline/Compatibility",[2010],"Baseline Compatibility"," going forward (and are included in conversations about it with the ",[2006,10071,10074],{"href":10072,"rel":10073},"https://github.com/web-platform-dx/web-features",[2010],"W3C WebDX Community Group",[1143,10076,10077],{},"We have some strategies to enable us to do this while also prioritising stability for our existing users, and recognising the scope of the Nuxt ecosystem.",[2412,10079,10080,10087,10099,10106],{},[1855,10081,10082,10083,10086],{},"In general we follow a pattern of ",[1159,10084,10085],{},"introducing a module or experimental feature"," that can be disabled in testing while we gather feedback and confirm the direction and API of new features.",[1855,10088,10089,10090,10093,10094,2281],{},"We have adopted the ",[1159,10091,10092],{},"ecosystem-ci pattern"," of validating that our code changes in Nuxt don't break downstream projects unintentionally. If you maintain a well-tested module or library that depends on Nuxt, I'd welcome a PR adding your project to ",[2006,10095,10098],{"href":10096,"rel":10097},"https://github.com/nuxt/ecosystem-ci",[2010],"nuxt/ecosystem-ci",[1855,10100,10101,10102,10105],{},"We plan to release a ",[1159,10103,10104],{},"pull-based test"," that will allow you to configure your CI to test itself against the latest nightly version of Nuxt to provide early feedback on new Nuxt releases, rather than facing an issue when upgrading.",[1855,10107,10108,10109,10112],{},"Finally, we have adopted a ",[1159,10110,10111],{},"push-based approach to updating existing projects",". When we identify breaking changes or improvements that can be rolled out to the ecosystem, we will proactively raise PRs to Nuxt modules (and, to a lesser extent, other open-source projects using Nuxt).",[1143,10114,10115],{},"I hope this will allow us to continue to innovate and experiment with new features without sacrificing the stability and maintainability.",[1143,10117,10118],{},"In particular, look for active development on the following:",[1852,10120,10121,10130,10135,10144,10152,10159],{},[1855,10122,10123,10124,10129],{},"✅ ",[2006,10125,10128],{"href":10126,"rel":10127},"https://github.com/nuxt/fonts",[2010],"nuxt/fonts"," - working up to v1.0.0",[1855,10131,10123,10132,10129],{},[2006,10133,8517],{"href":8513,"rel":10134},[2010],[1855,10136,10137,10138,10143],{},"🔥 ",[2006,10139,10142],{"href":10140,"rel":10141},"https://github.com/nuxt/scripts",[2010],"nuxt/scripts"," - soon to be released",[1855,10145,10146,10147,10151],{},"🚧 ",[2006,10148,8053],{"href":10149,"rel":10150},"https://github.com/nuxt/a11y",[2010]," - coming soon!",[1855,10153,10146,10154,10151],{},[2006,10155,10158],{"href":10156,"rel":10157},"https://github.com/nuxt/auth",[2010],"nuxt/auth",[1855,10160,10146,10161,10151],{},[2006,10162,10165],{"href":10163,"rel":10164},"https://github.com/nuxt/hints",[2010],"nuxt/hints",[1155,10167,10169],{"id":10168},"sustainable-open-source","Sustainable open source",[1143,10171,10172],{},"I want Nuxt to continue to be an independent, community-driven framework for the long term.",[1143,10174,10175,10176,10180],{},"I'm really delighted to see successful businesses founded on Nuxt, and initiatives springing up around Nuxt that become ",[2006,10177,10179],{"href":10178},"/enterprise/sponsors","sponsors"," or otherwise giving back to the core framework, enabling ongoing Nuxt development.",[1143,10182,10183,10184,10189,10190,5062,10195,10198,10199,5062,10204,5062,10207,4363,10211,10216,10217,10222],{},"Obviously, ",[2006,10185,10188],{"href":10186,"rel":10187},"https://nuxtlabs.com",[2010],"NuxtLabs"," is the preeminent example of that. ",[2006,10191,10194],{"href":10192,"rel":10193},"https://github.com/pi0",[2010],"Pooya Parsa",[2006,10196,4066],{"href":4069,"rel":10197},[2010]," and I are all able to work full-time on open source thanks to their paid services around Nuxt: ",[2006,10200,10203],{"href":10201,"rel":10202},"https://ui.nuxt.com/pro/getting-started",[2010],"Nuxt UI Pro",[2006,10205,10206],{"href":7796},"Nuxt Experts",[2006,10208,10042],{"href":10209,"rel":10210},"https://nuxt.studio/",[2010],[2006,10212,10215],{"href":10213,"rel":10214},"https://hub.nuxt.com/",[2010],"NuxtHub"," (soon). They also ",[2006,10218,10221],{"href":10219,"rel":10220},"https://github.com/orgs/nuxtlabs/sponsoring",[2010],"sponsor community members"," from Vue, Vite, UnJS, and Nuxt.",[1143,10224,10225],{},"For me, keeping Nuxt independent and sustainable for the future requires an active and growing team and community. In the weeks ahead, I'll be announcing a broader 'Nuxt team' alongside the core team. This is about recognising the tireless work of the many people whose contributions are already making Nuxt what it is.",[1143,10227,10228],{},"I would also love to see more of those team members or the wider community sponsored to work in the Nuxt ecosystem in the years ahead. If your company has benefited from Nuxt, please do consider sponsoring some of the developers working on Nuxt, whether they are team or wider community members.",[1155,10230,10232],{"id":10231},"friendly-collaboration","Friendly collaboration",[1143,10234,10235,10236,10239],{},"From the beginning of our work on Nuxt 3, we have sought to extract out utilities, libraries and even frameworks that we benefit from so they can ",[3746,10237,10238],{},"also"," benefit a much broader audience.",[1143,10241,10242,10243,10248,10249,10252],{},"That's the origin of ",[2006,10244,10247],{"href":10245,"rel":10246},"https://unjs.io/",[2010],"UnJS",", of course, and it continues to thrive under the leadership of ",[2006,10250,10194],{"href":10192,"rel":10251},[2010]," (who is also a key member of the Nuxt core team).",[1143,10254,10255,10256,2281],{},"We'd like to continue that attitude of friendly collaboration. Although building things ourselves or keeping them to ourselves might to be 'success', I don't have any time for zero-sum games. We will go further, both as a framework and as a web community, if we build ",[3746,10257,10258],{},"together",[1143,10260,10261,10262,10265,10266,10268],{},"Equally, one of our core values is platform-independence (alongside deep platform ",[3746,10263,10264],{},"integration","). We support 90+ providers across deployment, testing, stories, KV and cache, databases, image CDNs and font hosts. That breadth of ecosystem is one that bears rich rewards and frees people up to make choices about which providers they use based on the value they bring. But it ",[3746,10267,10238],{}," means we are dependent on our community who use these different providers to help us keep these integrations up-to-date.",[1143,10270,10271],{},"Nuxt isn't going anywhere, but we hope that the work we do collaboratively will last long beyond us.",[1155,10273,10275],{"id":10274},"a-welcoming-community","A welcoming community",[1143,10277,10278],{},"Although it is easy to focus on technical excellence or the quality of developer experience, I am more encouraged to see the continued growth of the Nuxt ecosystem as a welcoming and friendly community.",[1143,10280,10281,10282,10286,10287,10292,10293,2281],{},"I am incredibly grateful for the kind tone that prevails across ",[2006,10283,10285],{"href":9949,"rel":10284},[2010],"our community Discord",", on ",[2006,10288,10291],{"href":10289,"rel":10290},"https://x.com/nuxt_js",[2010],"Twitter",", and on ",[2006,10294,10296],{"href":8347,"rel":10295},[2010],"GitHub",[1155,10298,10300],{"id":10299},"what-about-nuxt-4","What about Nuxt 4?",[1143,10302,10303],{},"The JavaScript space is known for producing a new framework every week, which means there is a natural hype cycle.",[1143,10305,10306],{},"But we are not aiming for hype with the continued development of Nuxt, which is part of why we have committed to regular release cycles:",[1852,10308,10309,10315,10321],{},[1855,10310,10311,10314],{},[1159,10312,10313],{},"major"," framework releases every year",[1855,10316,10317,10320],{},[1159,10318,10319],{},"minor"," releases every month or so",[1855,10322,10323,10326],{},[1159,10324,10325],{},"patch"," releases every week or so",[1143,10328,10329],{},"You can expect to see breaking changes shipped in major releases, with features shipped in our minor releases. That means we aren't holding features back for Nuxt 4; we'll ship those as regularly as we can in our 6-weekly minor release cycle.",[1143,10331,10332,10333,10336],{},"Our aim is that Nuxt 4 is an opportunity for ",[3746,10334,10335],{},"thoughtful"," breaking changes with either a straightforward migration path (ideally with automated processes) or the ability to opt-in to previous behaviour.",[1143,10338,10339],{},"There are definitely lessons we as a team have learned form the transition from Nuxt 2 to 3, and I see Nuxt 4 as an opportunity for us to prove that major releases can be a good experience for users.",[1143,10341,10342,10343,10348,10349,10354],{},"You can preview the changes we have in mind by browsing ",[2006,10344,10347],{"href":10345,"rel":10346},"https://github.com/orgs/nuxt/projects/8/views/4",[2010],"our roadmap"," or checking through ",[2006,10350,10353],{"href":10351,"rel":10352},"https://github.com/nuxt/nuxt/issues?q=is:issue+label:4.x",[2010],"the issues we've tagged for v4",". Feedback and wishes are very welcome as always!",[10356,10357,10359],"h4",{"id":10358},"timetable","Timetable",[1143,10361,10362],{},"Our roadmap for Nuxt 4 is a little complex as we are also planning on major releases across the UnJS ecosystem.",[1143,10364,10365,10366,10371],{},"Roughly speaking, we are aiming to have one more minor release for Nuxt v3 and Nitro v2, before beginning a ",[2006,10367,10370],{"href":10368,"rel":10369},"https://github.com/unjs/community/discussions/4",[2010],"raft of major releases across the UnJS ecosystem of packages"," - culminating in Nuxt v4.",[1143,10373,10374,10375,10378],{},"We are aiming to release ",[1159,10376,10377],{},"Nuxt v4 on or before June 14"," (though obviously this is dependent on having enough time after Nitro's major release to be properly tested in the community, so be aware that this is not an exact date).",[10356,10380,10382],{"id":10381},"ongoing-support","Ongoing Support",[1143,10384,10385,10386,10389],{},"After the release of Nuxt v4, we will be providing ",[1159,10387,10388],{},"six months"," of ongoing support and bug-fixes for Nuxt v3, which we expect will be more than ample to upgrade to v4 given our aim of a gentle upgrade path.",[1143,10391,10392],{},"We hope you are as excited as we are about the pending release of Nuxt v4! 🎉",[4087,10394],{},[1143,10396,10397],{},"Finally, thank you so much for all your trust and support as we've been building Nuxt. I know I speak for the whole team when I say that it's such a privilege to be doing this alongside everyone in the Nuxt community! ❤️",[1143,10399,10400],{},"Daniel (on behalf of the whole Nuxt team)",{"title":1218,"searchDepth":1233,"depth":1233,"links":10402},[10403,10404],{"id":9853,"depth":1233,"text":9854},{"id":10046,"depth":1233,"text":10047,"children":10405},[10406,10407,10408,10409,10410],{"id":10056,"depth":1263,"text":10057},{"id":10168,"depth":1263,"text":10169},{"id":10231,"depth":1263,"text":10232},{"id":10274,"depth":1263,"text":10275},{"id":10299,"depth":1263,"text":10300},"2024-03-28T00:00:00.000Z","A lot of things have happened for Nuxt over the last year. Sébastien and Daniel share their thoughts on what we've achieved, and where we're going next.","/assets/blog/vision-for-2024.png",{},"/blog/looking-forward-2024",{"title":9843,"description":10412},"blog/23.looking-forward-2024","YMrpFQLDW4",{"id":10420,"title":10421,"authors":10422,"body":10425,"category":2176,"date":11614,"description":11615,"draft":108,"extension":1954,"image":11616,"meta":11617,"navigation":108,"path":11618,"seo":11619,"stem":11620,"tags":6,"__hash__":11621},"blog/blog/22.v3-11.md","Nuxt 3.11",[10423],{"name":2190,"avatar":10424,"to":2193},{"src":2192},{"type":1140,"value":10426,"toc":11594},[10427,10430,10434,10441,10455,10458,10576,10579,10618,10621,10628,10631,10681,10685,10691,10720,10728,10730,10734,10742,10749,10757,10876,10879,10887,10924,11067,11069,11077,11088,11157,11161,11173,11186,11190,11200,11221,11233,11237,11249,11311,11323,11331,11337,11339,11354,11358,11375,11379,11395,11398,11514,11518,11525,11533,11552,11554,11557,11571,11573,11576,11584,11587,11591],[1143,10428,10429],{},"This is possibly the last minor release before Nuxt v4, and so we've packed it full of features and improvements we hope will delight you! ✨",[1147,10431,10433],{"id":10432},"better-logging","🪵 Better logging",[1143,10435,10436,10437,10440],{},"When developing a Nuxt application and using ",[1220,10438,10439],{},"console.log"," in your application, you may have noticed that these logs are not displayed in your browser console when refreshing the page (during server-side rendering). This can be frustrating, as it makes it difficult to debug your application. This is now a thing of the past!",[1143,10442,10443,10444,10449,10450,3681],{},"Now, when you have server logs associated with a request, they will be bundled up and passed to the client and displayed in your browser console. ",[2006,10445,10448],{"href":10446,"rel":10447},"https://nodejs.org/docs/latest-v20.x/api/async_context.html",[2010],"Asynchronous context"," is used to track and associate these logs with the request that triggered them. (",[2006,10451,10454],{"href":10452,"rel":10453},"https://github.com/nuxt/nuxt/pull/25936",[2010],"#25936",[1143,10456,10457],{},"For example, this code:",[1213,10459,10461],{"className":2595,"code":10460,"filename":5115,"language":2597,"meta":1218,"style":1218},"\u003Cscript setup>\nconsole.log('Log from index page')\n\nconst { data } = await useAsyncData(() => {\n  console.log('Log inside useAsyncData')\n  return $fetch('/api/test')\n})\n\u003C/script>\n",[1220,10462,10463,10473,10493,10497,10524,10544,10562,10568],{"__ignoreMap":1218},[1223,10464,10465,10467,10469,10471],{"class":1225,"line":1226},[1223,10466,1237],{"class":1236},[1223,10468,5899],{"class":1240},[1223,10470,5902],{"class":1244},[1223,10472,1260],{"class":1236},[1223,10474,10475,10478,10480,10482,10484,10486,10489,10491],{"class":1225,"line":1233},[1223,10476,10477],{"class":1285},"console",[1223,10479,2281],{"class":1236},[1223,10481,6764],{"class":1751},[1223,10483,1754],{"class":1285},[1223,10485,1957],{"class":1236},[1223,10487,10488],{"class":1254},"Log from index page",[1223,10490,1957],{"class":1236},[1223,10492,1804],{"class":1285},[1223,10494,10495],{"class":1225,"line":1263},[1223,10496,1740],{"emptyLinePlaceholder":1739},[1223,10498,10499,10501,10503,10506,10508,10510,10513,10516,10518,10520,10522],{"class":1225,"line":1296},[1223,10500,3214],{"class":1244},[1223,10502,1683],{"class":1236},[1223,10504,10505],{"class":1285}," data ",[1223,10507,1801],{"class":1236},[1223,10509,2339],{"class":1236},[1223,10511,10512],{"class":1679}," await",[1223,10514,10515],{"class":1751}," useAsyncData",[1223,10517,1754],{"class":1285},[1223,10519,1777],{"class":1236},[1223,10521,3125],{"class":1244},[1223,10523,1891],{"class":1236},[1223,10525,10526,10529,10531,10533,10535,10537,10540,10542],{"class":1225,"line":1325},[1223,10527,10528],{"class":1285},"  console",[1223,10530,2281],{"class":1236},[1223,10532,6764],{"class":1751},[1223,10534,1754],{"class":1240},[1223,10536,1957],{"class":1236},[1223,10538,10539],{"class":1254},"Log inside useAsyncData",[1223,10541,1957],{"class":1236},[1223,10543,1804],{"class":1240},[1223,10545,10546,10548,10551,10553,10555,10558,10560],{"class":1225,"line":1355},[1223,10547,2374],{"class":1679},[1223,10549,10550],{"class":1751}," $fetch",[1223,10552,1754],{"class":1240},[1223,10554,1957],{"class":1236},[1223,10556,10557],{"class":1254},"/api/test",[1223,10559,1957],{"class":1236},[1223,10561,1804],{"class":1240},[1223,10563,10564,10566],{"class":1225,"line":1771},[1223,10565,1801],{"class":1236},[1223,10567,1804],{"class":1285},[1223,10569,10570,10572,10574],{"class":1225,"line":1783},[1223,10571,1289],{"class":1236},[1223,10573,5899],{"class":1240},[1223,10575,1260],{"class":1236},[1143,10577,10578],{},"will now log to your browser console when you refresh the page:",[1213,10580,10582],{"className":2022,"code":10581,"language":2024,"meta":1218,"style":1218},"Log from index page\n[ssr] Log inside useAsyncData \n    at pages/index.vue\n",[1220,10583,10584,10597,10610],{"__ignoreMap":1218},[1223,10585,10586,10589,10591,10594],{"class":1225,"line":1226},[1223,10587,10588],{"class":2036},"Log",[1223,10590,1692],{"class":1254},[1223,10592,10593],{"class":1254}," index",[1223,10595,10596],{"class":1254}," page\n",[1223,10598,10599,10602,10605,10607],{"class":1225,"line":1233},[1223,10600,10601],{"class":1236},"[",[1223,10603,10604],{"class":1285},"ssr",[1223,10606,2858],{"class":1236},[1223,10608,10609],{"class":1285}," Log inside useAsyncData \n",[1223,10611,10612,10615],{"class":1225,"line":1263},[1223,10613,10614],{"class":2036},"    at",[1223,10616,10617],{"class":1254}," pages/index.vue\n",[1143,10619,10620],{},"👉 We also plan to support streaming of subsequent logs to the Nuxt DevTools in future.",[1143,10622,10623,10624,10627],{},"We've also added a ",[1220,10625,10626],{},"dev:ssr-logs"," hook (both in Nuxt and Nitro) which is called on server and client, allowing you to handle them yourself if you want to.",[1143,10629,10630],{},"If you encounter any issues with this, it is possible to disable them - or prevent them from logging to your browser console.",[1213,10632,10634],{"className":1669,"code":10633,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  features: {\n    devLogs: false\n    // or 'silent' to allow you to handle yourself with `dev:ssr-logs` hook\n  },\n})\n",[1220,10635,10636,10648,10656,10666,10671,10675],{"__ignoreMap":1218},[1223,10637,10638,10640,10642,10644,10646],{"class":1225,"line":1226},[1223,10639,1745],{"class":1679},[1223,10641,1748],{"class":1679},[1223,10643,2820],{"class":1751},[1223,10645,1754],{"class":1285},[1223,10647,1757],{"class":1236},[1223,10649,10650,10652,10654],{"class":1225,"line":1233},[1223,10651,8823],{"class":1240},[1223,10653,1765],{"class":1236},[1223,10655,1891],{"class":1236},[1223,10657,10658,10661,10663],{"class":1225,"line":1263},[1223,10659,10660],{"class":1240},"    devLogs",[1223,10662,1765],{"class":1236},[1223,10664,10665],{"class":2928}," false\n",[1223,10667,10668],{"class":1225,"line":1296},[1223,10669,10670],{"class":1229},"    // or 'silent' to allow you to handle yourself with `dev:ssr-logs` hook\n",[1223,10672,10673],{"class":1225,"line":1325},[1223,10674,3312],{"class":1236},[1223,10676,10677,10679],{"class":1225,"line":1355},[1223,10678,1801],{"class":1236},[1223,10680,1804],{"class":1285},[1147,10682,10684],{"id":10683},"preview-mode","🎨 Preview mode",[1143,10686,10687,10688,10690],{},"A new ",[1220,10689,480],{}," composable aims to make it simple to use preview mode in your Nuxt app.",[1213,10692,10695],{"className":1669,"code":10693,"filename":10694,"language":1672,"meta":1218,"style":1218},"const { enabled, state } = usePreviewMode()\n","plugins/test.client.ts",[1220,10696,10697],{"__ignoreMap":1218},[1223,10698,10699,10701,10703,10706,10708,10711,10713,10715,10718],{"class":1225,"line":1226},[1223,10700,3214],{"class":1244},[1223,10702,1683],{"class":1236},[1223,10704,10705],{"class":1285}," enabled",[1223,10707,2333],{"class":1236},[1223,10709,10710],{"class":1285}," state ",[1223,10712,1801],{"class":1236},[1223,10714,2339],{"class":1236},[1223,10716,10717],{"class":1751}," usePreviewMode",[1223,10719,1789],{"class":1285},[1143,10721,10722,10723,4363,10725,10727],{},"When preview mode is enabled, all your data fetching composables, like ",[1220,10724,432],{},[1220,10726,444],{}," will rerun, meaning any cached data in the payload will be bypassed.",[3611,10729],{"to":481},[1147,10731,10733],{"id":10732},"cache-busting-payloads","💰 Cache-busting payloads",[1143,10735,10736,10737,3681],{},"We now automatically cache-bust your payloads if you haven't disabled Nuxt's app manifest, meaning you shouldn't be stuck with outdated data after a deployment (",[2006,10738,10741],{"href":10739,"rel":10740},"https://github.com/nuxt/nuxt/pull/26068",[2010],"#26068",[1147,10743,10745,10746],{"id":10744},"️-middleware-routerules","👮‍♂️ Middleware ",[1220,10747,10748],{},"routeRules",[1143,10750,10751,10752,3681],{},"It's now possible to define middleware for page paths within the Vue app part of your application (that is, not your Nitro routes) (",[2006,10753,10756],{"href":10754,"rel":10755},"https://github.com/nuxt/nuxt/pull/25841",[2010],"#25841",[1213,10758,10760],{"className":1669,"code":10759,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  routeRules: {\n    '/admin/**': {\n      // or appMiddleware: 'auth'\n      appMiddleware: ['auth']\n    },\n    '/admin/login': {\n      // You can 'turn off' middleware that would otherwise run for a page\n      appMiddleware: {\n        auth: false\n      }\n    },\n  },\n})\n",[1220,10761,10762,10774,10783,10796,10801,10819,10823,10836,10841,10849,10858,10862,10866,10870],{"__ignoreMap":1218},[1223,10763,10764,10766,10768,10770,10772],{"class":1225,"line":1226},[1223,10765,1745],{"class":1679},[1223,10767,1748],{"class":1679},[1223,10769,2820],{"class":1751},[1223,10771,1754],{"class":1285},[1223,10773,1757],{"class":1236},[1223,10775,10776,10779,10781],{"class":1225,"line":1233},[1223,10777,10778],{"class":1240},"  routeRules",[1223,10780,1765],{"class":1236},[1223,10782,1891],{"class":1236},[1223,10784,10785,10787,10790,10792,10794],{"class":1225,"line":1263},[1223,10786,9188],{"class":1236},[1223,10788,10789],{"class":1240},"/admin/**",[1223,10791,1957],{"class":1236},[1223,10793,1765],{"class":1236},[1223,10795,1891],{"class":1236},[1223,10797,10798],{"class":1225,"line":1296},[1223,10799,10800],{"class":1229},"      // or appMiddleware: 'auth'\n",[1223,10802,10803,10806,10808,10810,10812,10815,10817],{"class":1225,"line":1325},[1223,10804,10805],{"class":1240},"      appMiddleware",[1223,10807,1765],{"class":1236},[1223,10809,2848],{"class":1285},[1223,10811,1957],{"class":1236},[1223,10813,10814],{"class":1254},"auth",[1223,10816,1957],{"class":1236},[1223,10818,9478],{"class":1285},[1223,10820,10821],{"class":1225,"line":1355},[1223,10822,2989],{"class":1236},[1223,10824,10825,10827,10830,10832,10834],{"class":1225,"line":1771},[1223,10826,9188],{"class":1236},[1223,10828,10829],{"class":1240},"/admin/login",[1223,10831,1957],{"class":1236},[1223,10833,1765],{"class":1236},[1223,10835,1891],{"class":1236},[1223,10837,10838],{"class":1225,"line":1783},[1223,10839,10840],{"class":1229},"      // You can 'turn off' middleware that would otherwise run for a page\n",[1223,10842,10843,10845,10847],{"class":1225,"line":1792},[1223,10844,10805],{"class":1240},[1223,10846,1765],{"class":1236},[1223,10848,1891],{"class":1236},[1223,10850,10851,10854,10856],{"class":1225,"line":1798},[1223,10852,10853],{"class":1240},"        auth",[1223,10855,1765],{"class":1236},[1223,10857,10665],{"class":2928},[1223,10859,10860],{"class":1225,"line":1975},[1223,10861,1978],{"class":1236},[1223,10863,10864],{"class":1225,"line":1981},[1223,10865,2989],{"class":1236},[1223,10867,10868],{"class":1225,"line":1987},[1223,10869,3312],{"class":1236},[1223,10871,10872,10874],{"class":1225,"line":1993},[1223,10873,1801],{"class":1236},[1223,10875,1804],{"class":1285},[3611,10877],{"to":10878},"/docs/guide/concepts/rendering#route-rules",[1147,10880,10882,10883,10886],{"id":10881},"new-clear-data-fetching-utility","⌫ New ",[1220,10884,10885],{},"clear"," data fetching utility",[1143,10888,10889,10890,4363,10892,10894,10895,10897,10898,10900,10901,4880,10903,10906,10907,4880,10910,10906,10912,4880,10915,10918,10919,2541],{},"Now, ",[1220,10891,432],{},[1220,10893,444],{}," expose a ",[1220,10896,10885],{}," utility. This is a function that can be used to set ",[1220,10899,7073],{}," to undefined, set ",[1220,10902,1621],{},[1220,10904,10905],{},"null",", set ",[1220,10908,10909],{},"pending",[1220,10911,6969],{},[1220,10913,10914],{},"status",[1220,10916,10917],{},"idle",", and mark any currently pending requests as cancelled. (",[2006,10920,10923],{"href":10921,"rel":10922},"https://github.com/nuxt/nuxt/pull/26259",[2010],"#26259",[1213,10925,10927],{"className":2595,"code":10926,"language":2597,"meta":1218,"style":1218},"\u003Cscript setup lang=\"ts\">\nconst { data, clear } = await useFetch('/api/test')\n\nconst route = useRoute()\nwatch(() => route.path, (path) => {\n  if (path === '/') clear()\n})\n\u003C/script>\n",[1220,10928,10929,10949,10982,10986,10999,11029,11053,11059],{"__ignoreMap":1218},[1223,10930,10931,10933,10935,10937,10939,10941,10943,10945,10947],{"class":1225,"line":1226},[1223,10932,1237],{"class":1236},[1223,10934,5899],{"class":1240},[1223,10936,5902],{"class":1244},[1223,10938,6066],{"class":1244},[1223,10940,1248],{"class":1236},[1223,10942,1251],{"class":1236},[1223,10944,1672],{"class":1254},[1223,10946,1251],{"class":1236},[1223,10948,1260],{"class":1236},[1223,10950,10951,10953,10955,10958,10960,10963,10965,10967,10969,10972,10974,10976,10978,10980],{"class":1225,"line":1233},[1223,10952,3214],{"class":1244},[1223,10954,1683],{"class":1236},[1223,10956,10957],{"class":1285}," data",[1223,10959,2333],{"class":1236},[1223,10961,10962],{"class":1285}," clear ",[1223,10964,1801],{"class":1236},[1223,10966,2339],{"class":1236},[1223,10968,10512],{"class":1679},[1223,10970,10971],{"class":1751}," useFetch",[1223,10973,1754],{"class":1285},[1223,10975,1957],{"class":1236},[1223,10977,10557],{"class":1254},[1223,10979,1957],{"class":1236},[1223,10981,1804],{"class":1285},[1223,10983,10984],{"class":1225,"line":1263},[1223,10985,1740],{"emptyLinePlaceholder":1739},[1223,10987,10988,10990,10993,10995,10997],{"class":1225,"line":1296},[1223,10989,3214],{"class":1244},[1223,10991,10992],{"class":1285}," route ",[1223,10994,1248],{"class":1236},[1223,10996,5942],{"class":1751},[1223,10998,1789],{"class":1285},[1223,11000,11001,11004,11006,11008,11010,11013,11015,11017,11019,11021,11023,11025,11027],{"class":1225,"line":1325},[1223,11002,11003],{"class":1751},"watch",[1223,11005,1754],{"class":1285},[1223,11007,1777],{"class":1236},[1223,11009,3125],{"class":1244},[1223,11011,11012],{"class":1285}," route",[1223,11014,2281],{"class":1236},[1223,11016,6037],{"class":1285},[1223,11018,2333],{"class":1236},[1223,11020,3114],{"class":1236},[1223,11022,6037],{"class":2329},[1223,11024,2541],{"class":1236},[1223,11026,3125],{"class":1244},[1223,11028,1891],{"class":1236},[1223,11030,11031,11034,11036,11038,11040,11042,11044,11046,11049,11051],{"class":1225,"line":1355},[1223,11032,11033],{"class":1679},"  if",[1223,11035,3114],{"class":1240},[1223,11037,6037],{"class":1285},[1223,11039,7076],{"class":1236},[1223,11041,1695],{"class":1236},[1223,11043,5061],{"class":1254},[1223,11045,1957],{"class":1236},[1223,11047,11048],{"class":1240},") ",[1223,11050,10885],{"class":1751},[1223,11052,1789],{"class":1240},[1223,11054,11055,11057],{"class":1225,"line":1771},[1223,11056,1801],{"class":1236},[1223,11058,1804],{"class":1285},[1223,11060,11061,11063,11065],{"class":1225,"line":1783},[1223,11062,1289],{"class":1236},[1223,11064,5899],{"class":1240},[1223,11066,1260],{"class":1236},[3611,11068],{"to":65},[1147,11070,11072,11073,11076],{"id":11071},"️-new-teleports-target","🕳️ New ",[1220,11074,11075],{},"#teleports"," target",[1143,11078,11079,11080,11083,11084,11087],{},"Nuxt now includes a new ",[1220,11081,11082],{},"\u003Cdiv id=\"teleports\">\u003C/div>"," element in your app within your ",[1220,11085,11086],{},"\u003Cbody>"," tag. It supports server-side teleports, meaning you can do this safely on the server:",[1213,11089,11091],{"className":2595,"code":11090,"filename":248,"language":2597,"meta":1218,"style":1218},"\u003Ctemplate>\n  \u003CTeleport to=\"#teleports\">\n    \u003Cspan>\n      Something\n    \u003C/span>\n  \u003C/Teleport>\n\u003C/template>\n",[1220,11092,11093,11101,11120,11128,11133,11141,11149],{"__ignoreMap":1218},[1223,11094,11095,11097,11099],{"class":1225,"line":1226},[1223,11096,1237],{"class":1236},[1223,11098,2606],{"class":1240},[1223,11100,1260],{"class":1236},[1223,11102,11103,11105,11107,11110,11112,11114,11116,11118],{"class":1225,"line":1233},[1223,11104,1266],{"class":1236},[1223,11106,875],{"class":1240},[1223,11108,11109],{"class":1244}," to",[1223,11111,1248],{"class":1236},[1223,11113,1251],{"class":1236},[1223,11115,11075],{"class":1254},[1223,11117,1251],{"class":1236},[1223,11119,1260],{"class":1236},[1223,11121,11122,11124,11126],{"class":1225,"line":1263},[1223,11123,5138],{"class":1236},[1223,11125,1223],{"class":1240},[1223,11127,1260],{"class":1236},[1223,11129,11130],{"class":1225,"line":1296},[1223,11131,11132],{"class":1285},"      Something\n",[1223,11134,11135,11137,11139],{"class":1225,"line":1325},[1223,11136,5164],{"class":1236},[1223,11138,1223],{"class":1240},[1223,11140,1260],{"class":1236},[1223,11142,11143,11145,11147],{"class":1225,"line":1355},[1223,11144,5211],{"class":1236},[1223,11146,875],{"class":1240},[1223,11148,1260],{"class":1236},[1223,11150,11151,11153,11155],{"class":1225,"line":1771},[1223,11152,1289],{"class":1236},[1223,11154,2606],{"class":1240},[1223,11156,1260],{"class":1236},[1147,11158,11160],{"id":11159},"loading-indicator-and-transition-controls","🚦 Loading indicator and transition controls",[1143,11162,11163,11164,11167,11168,3681],{},"It's now possible to set custom timings for hiding the loading indicator, and forcing the ",[1220,11165,11166],{},"finish()"," method if needed (",[2006,11169,11172],{"href":11170,"rel":11171},"https://github.com/nuxt/nuxt/pull/25932",[2010],"#25932",[1143,11174,11175,11176,11179,11180,11185],{},"There's also a new ",[1220,11177,11178],{},"page:view-transition:start"," hook for hooking into the View Transitions API (",[2006,11181,11184],{"href":11182,"rel":11183},"https://github.com/nuxt/nuxt/pull/26045",[2010],"#26045",") if you have that feature enabled.",[1147,11187,11189],{"id":11188},"️-server-and-client-only-pages","🛍️ Server- and client-only pages",[1143,11191,11192,11193,6381,11196,11199],{},"This release sees server- and client-only pages land in Nuxt! You can now add a ",[1220,11194,11195],{},".server.vue",[1220,11197,11198],{},".client.vue"," suffix to a page to get automatic handling of it.",[1143,11201,11202,11205,11206,11208,11209,11211,11212,11215,11216,3681],{},[1159,11203,11204],{},"Client-only pages"," will render entirely on the client-side, and skip server-rendering entirely, just as if the entire page was wrapped in ",[1220,11207,360],{},". Use this responsibly. The flash of load on the client-side can be a bad user experience so make sure you really need to avoid server-side loading. Also consider using ",[1220,11210,360],{}," with a ",[1220,11213,11214],{},"fallback"," slot to render a skeleton loader (",[2006,11217,11220],{"href":11218,"rel":11219},"https://github.com/nuxt/nuxt/pull/25037",[2010],"#25037",[1143,11222,11223,11224,11227,11228,3681],{},"⚗️ ",[1159,11225,11226],{},"Server-only pages"," are even more useful because they enable you to integrate fully-server rendered HTML within client-side navigation. They will even be prefetched when links to them are in the viewport - so you will get instantaneous loading (",[2006,11229,11232],{"href":11230,"rel":11231},"https://github.com/nuxt/nuxt/pull/24954",[2010],"#24954",[1147,11234,11236],{"id":11235},"server-component-bonanza","🤠 Server component bonanza",[1143,11238,11239,11240,11243,11244,3681],{},"When you are using server components, you can now use the ",[1220,11241,11242],{},"nuxt-client"," attribute anywhere within your tree (",[2006,11245,11248],{"href":11246,"rel":11247},"https://github.com/nuxt/nuxt/pull/25479",[2010],"#25479",[1213,11250,11252],{"className":1669,"code":11251,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  experimental: {\n    componentIslands: {\n      selectiveClient: 'deep'\n    }\n  },\n})\n",[1220,11253,11254,11266,11274,11283,11297,11301,11305],{"__ignoreMap":1218},[1223,11255,11256,11258,11260,11262,11264],{"class":1225,"line":1226},[1223,11257,1745],{"class":1679},[1223,11259,1748],{"class":1679},[1223,11261,2820],{"class":1751},[1223,11263,1754],{"class":1285},[1223,11265,1757],{"class":1236},[1223,11267,11268,11270,11272],{"class":1225,"line":1233},[1223,11269,3074],{"class":1240},[1223,11271,1765],{"class":1236},[1223,11273,1891],{"class":1236},[1223,11275,11276,11279,11281],{"class":1225,"line":1263},[1223,11277,11278],{"class":1240},"    componentIslands",[1223,11280,1765],{"class":1236},[1223,11282,1891],{"class":1236},[1223,11284,11285,11288,11290,11292,11295],{"class":1225,"line":1296},[1223,11286,11287],{"class":1240},"      selectiveClient",[1223,11289,1765],{"class":1236},[1223,11291,1695],{"class":1236},[1223,11293,11294],{"class":1254},"deep",[1223,11296,1701],{"class":1236},[1223,11298,11299],{"class":1225,"line":1325},[1223,11300,1984],{"class":1236},[1223,11302,11303],{"class":1225,"line":1355},[1223,11304,3312],{"class":1236},[1223,11306,11307,11309],{"class":1225,"line":1771},[1223,11308,1801],{"class":1236},[1223,11310,1804],{"class":1285},[1143,11312,11313,11314,11317,11318,3681],{},"You can listen to an ",[1220,11315,11316],{},"@error"," event from server components that will be triggered if there is any issue loading the component (",[2006,11319,11322],{"href":11320,"rel":11321},"https://github.com/nuxt/nuxt/pull/25798",[2010],"#25798",[1143,11324,11325,11326,3681],{},"Finally, server-only components are now smartly enabled when you have a server-only component or a server-only page within your project or any of its layers (",[2006,11327,11330],{"href":11328,"rel":11329},"https://github.com/nuxt/nuxt/pull/26223",[2010],"#26223",[11332,11333,11334],"callout",{"type":1604},[1143,11335,11336],{},"Server components remain experimental and their API may change, so be careful\nbefore depending on implementation details.",[1147,11338,3968],{"id":3967},[1143,11340,11341,11342,11347,11348,11353],{},"We've shipped a number of performance improvements, including only updating changed virtual templates (",[2006,11343,11346],{"href":11344,"rel":11345},"https://github.com/nuxt/nuxt/pull/26250",[2010],"#26250","), using a 'layered' prerender cache (",[2006,11349,11352],{"href":11350,"rel":11351},"https://github.com/nuxt/nuxt/pull/26104",[2010],"#26104",") that falls back to filesystem instead of keeping everything in memory when prerendering - and lots of other examples.",[1147,11355,11357],{"id":11356},"public-assets-handling","📂 Public assets handling",[1143,11359,11360,11361,11364,11365,11370,11371,11374],{},"We have shipped a reimplementation of Vite's public asset handling, meaning that public assets in your ",[1220,11362,11363],{},"public/"," directory or your layer directories are now resolved entirely by Nuxt (",[2006,11366,11369],{"href":11367,"rel":11368},"https://github.com/nuxt/nuxt/pull/26163",[2010],"#26163","), so if you have added ",[1220,11372,11373],{},"nitro.publicAssets"," directories with a custom prefix, these will now work.",[1147,11376,11378],{"id":11377},"chunk-naming","📦 Chunk naming",[1143,11380,11381,11382,11385,11386,11389,11390,2541],{},"We have changed the default ",[1220,11383,11384],{},"_nuxt/[name].[hash].js"," file name pattern for your JS chunks. Now, we default to ",[1220,11387,11388],{},"_nuxt/[hash].js",". This is to avoid false positives by ad blockers triggering off your component or chunk names, which can be a very difficult issue to debug. (",[2006,11391,11394],{"href":11392,"rel":11393},"https://github.com/nuxt/nuxt/pull/26203",[2010],"#26203",[1143,11396,11397],{},"You can easily configure this to revert to previous behaviour if you wish:",[1213,11399,11401],{"className":1669,"code":11400,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  vite: {\n    $client: {\n      build: {\n        rollupOptions: {\n          output: {\n            chunkFileNames: '_nuxt/[name].[hash].js',\n            entryFileNames: '_nuxt/[name].[hash].js'\n          }\n        }\n      }\n    }\n  },\n})\n",[1220,11402,11403,11415,11424,11433,11442,11451,11460,11475,11488,11492,11496,11500,11504,11508],{"__ignoreMap":1218},[1223,11404,11405,11407,11409,11411,11413],{"class":1225,"line":1226},[1223,11406,1745],{"class":1679},[1223,11408,1748],{"class":1679},[1223,11410,2820],{"class":1751},[1223,11412,1754],{"class":1285},[1223,11414,1757],{"class":1236},[1223,11416,11417,11420,11422],{"class":1225,"line":1233},[1223,11418,11419],{"class":1240},"  vite",[1223,11421,1765],{"class":1236},[1223,11423,1891],{"class":1236},[1223,11425,11426,11429,11431],{"class":1225,"line":1263},[1223,11427,11428],{"class":1240},"    $client",[1223,11430,1765],{"class":1236},[1223,11432,1891],{"class":1236},[1223,11434,11435,11438,11440],{"class":1225,"line":1296},[1223,11436,11437],{"class":1240},"      build",[1223,11439,1765],{"class":1236},[1223,11441,1891],{"class":1236},[1223,11443,11444,11447,11449],{"class":1225,"line":1325},[1223,11445,11446],{"class":1240},"        rollupOptions",[1223,11448,1765],{"class":1236},[1223,11450,1891],{"class":1236},[1223,11452,11453,11456,11458],{"class":1225,"line":1355},[1223,11454,11455],{"class":1240},"          output",[1223,11457,1765],{"class":1236},[1223,11459,1891],{"class":1236},[1223,11461,11462,11465,11467,11469,11471,11473],{"class":1225,"line":1771},[1223,11463,11464],{"class":1240},"            chunkFileNames",[1223,11466,1765],{"class":1236},[1223,11468,1695],{"class":1236},[1223,11470,11384],{"class":1254},[1223,11472,1957],{"class":1236},[1223,11474,1780],{"class":1236},[1223,11476,11477,11480,11482,11484,11486],{"class":1225,"line":1783},[1223,11478,11479],{"class":1240},"            entryFileNames",[1223,11481,1765],{"class":1236},[1223,11483,1695],{"class":1236},[1223,11485,11384],{"class":1254},[1223,11487,1701],{"class":1236},[1223,11489,11490],{"class":1225,"line":1792},[1223,11491,3480],{"class":1236},[1223,11493,11494],{"class":1225,"line":1798},[1223,11495,3485],{"class":1236},[1223,11497,11498],{"class":1225,"line":1975},[1223,11499,1978],{"class":1236},[1223,11501,11502],{"class":1225,"line":1981},[1223,11503,1984],{"class":1236},[1223,11505,11506],{"class":1225,"line":1987},[1223,11507,3312],{"class":1236},[1223,11509,11510,11512],{"class":1225,"line":1993},[1223,11511,1801],{"class":1236},[1223,11513,1804],{"class":1285},[1147,11515,11517],{"id":11516},"type-fixes","💪 Type fixes",[1143,11519,11520,11521,11524],{},"Previously users with ",[1220,11522,11523],{},"shamefully-hoist=false"," may have encountered issues with types not being resolved or working correctly. You may also have encountered problems with excessive type instantiation.",[1143,11526,11527,11528,3681],{},"We now try to tell TypeScript about certain key types so they can be resolved even if deeply nested (",[2006,11529,11532],{"href":11530,"rel":11531},"https://github.com/nuxt/nuxt/pull/26158",[2010],"#26158",[1143,11534,11535,11536,4363,11541,11546,11547,3681],{},"There are a whole raft of other type fixes, including some regarding import types (",[2006,11537,11540],{"href":11538,"rel":11539},"https://github.com/nuxt/nuxt/pull/26218",[2010],"#26218",[2006,11542,11545],{"href":11543,"rel":11544},"https://github.com/nuxt/nuxt/pull/25965",[2010],"#25965",") and module typings (",[2006,11548,11551],{"href":11549,"rel":11550},"https://github.com/nuxt/nuxt/pull/25548",[2010],"#25548",[1147,11553,3580],{"id":3579},[1143,11555,11556],{},"As usual, our recommendation for upgrading Nuxt is to run:",[1213,11558,11560],{"className":2022,"code":11559,"language":2024,"meta":1218,"style":1218},"nuxi upgrade --force\n",[1220,11561,11562],{"__ignoreMap":1218},[1223,11563,11564,11567,11569],{"class":1225,"line":1226},[1223,11565,11566],{"class":2036},"nuxi",[1223,11568,3599],{"class":1254},[1223,11570,4019],{"class":1254},[1143,11572,4022],{},[1147,11574,11575],{"id":3608},"👉 Full release notes",[3611,11577,11579],{"to":11578,"color":3613,"icon":3614,"target":3615},"https://github.com/nuxt/nuxt/releases/tag/v3.11.0",[1143,11580,3619,11581,2281],{},[1220,11582,11583],{},"v3.11.0",[1143,11585,11586],{},"Thank you for reading this far! We hope you enjoy the new release. Please do let us know if you have any feedback or issues.",[1143,11588,11589],{},[1159,11590,4631],{},[2160,11592,11593],{},"html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}html pre.shiki code .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}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 .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}html pre.shiki code .sagxc, html code.shiki .sagxc{--shiki-light:#FF5370;--shiki-default:#FF5370;--shiki-dark:#FF9CAC}html pre.shiki code .svXlt, html code.shiki .svXlt{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .ssYd4, html code.shiki .ssYd4{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":1218,"searchDepth":1233,"depth":1233,"links":11595},[11596,11597,11598,11599,11601,11603,11605,11606,11607,11608,11609,11610,11611,11612,11613],{"id":10432,"depth":1233,"text":10433},{"id":10683,"depth":1233,"text":10684},{"id":10732,"depth":1233,"text":10733},{"id":10744,"depth":1233,"text":11600},"👮‍♂️ Middleware routeRules",{"id":10881,"depth":1233,"text":11602},"⌫ New clear data fetching utility",{"id":11071,"depth":1233,"text":11604},"🕳️ New #teleports target",{"id":11159,"depth":1233,"text":11160},{"id":11188,"depth":1233,"text":11189},{"id":11235,"depth":1233,"text":11236},{"id":3967,"depth":1233,"text":3968},{"id":11356,"depth":1233,"text":11357},{"id":11377,"depth":1233,"text":11378},{"id":11516,"depth":1233,"text":11517},{"id":3579,"depth":1233,"text":3580},{"id":3608,"depth":1233,"text":11575},"2024-03-16T10:00:00.000Z","Nuxt 3.11 is out - with better logging, preview mode, server pages and much more!","/assets/blog/v3.11.png",{},"/blog/v3-11",{"title":10421,"description":11615},"blog/22.v3-11","5k8gY1ALNl",{"id":11623,"title":1056,"authors":11624,"body":11627,"category":9834,"date":13238,"description":13239,"draft":108,"extension":1954,"image":13240,"meta":13241,"navigation":1739,"path":1057,"seo":13242,"stem":1058,"tags":6,"__hash__":13243},"blog/blog/21.shiki-v1.md",[11625],{"name":4066,"avatar":11626,"to":4069,"twitter":4070},{"src":4068},{"type":1140,"value":11628,"toc":13230},[11629,11655,11677,12283,12286,12305,12308,12312,12325,12339,12348,12369,12445,12495,12532,12535,12538,12542,12555,12615,12624,12641,12667,12679,12720,12737,12741,12755,12758,12771,12778,12785,12794,12798,12844,12859,12869,12892,12911,13058,13092,13096,13099,13200,13207,13211,13227],[1143,11630,11631,11636,11637,11642,11643,11648,11649,11654],{},[2006,11632,11635],{"href":11633,"rel":11634},"https://github.com/shikijs/shiki",[2010],"Shiki"," is a syntax highlighter that uses ",[2006,11638,11641],{"href":11639,"rel":11640},"https://code.visualstudio.com/api/language-extensions/syntax-highlight-guide#textmate-grammars",[2010],"TextMate grammars and themes",", the same engine that powers VS Code. It provides one of the most accurate and beautiful syntax highlighting for your code snippets. It was created by ",[2006,11644,11647],{"href":11645,"rel":11646},"https://github.com/octref",[2010],"Pine Wu"," back in 2018, when he was part of the VS Code team. It started as an experiment to use ",[2006,11650,11653],{"href":11651,"rel":11652},"https://github.com/microsoft/vscode-oniguruma",[2010],"Oniguruma"," to do syntax highlighting.",[1143,11656,11657,11658,4363,11663,11668,11669,11672,11673,11676],{},"Different from existing syntax highlighters like ",[2006,11659,11662],{"href":11660,"rel":11661},"https://prismjs.com/",[2010],"Prism",[2006,11664,11667],{"href":11665,"rel":11666},"https://highlightjs.org/",[2010],"Highlight.js"," that designed to run in the browser, Shiki took a different approach by ",[1159,11670,11671],{},"highlighting ahead of time",". It ships the highlighted HTML to the client, producing accurate and beautiful syntax highlighting with ",[1159,11674,11675],{},"zero JavaScript",". It soon took off and became a very popular choice, especially for static site generators and documentation sites.",[11678,11679,11681,11684,11732,11735,12276],"collapsible",{"name":11680},"Shiki Example",[1143,11682,11683],{},"For example, with the code snippet below:",[1213,11685,11687],{"className":1669,"code":11686,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  modules: [\n    '@nuxt/content',\n  ],\n})\n",[1220,11688,11689,11701,11709,11720,11726],{"__ignoreMap":1218},[1223,11690,11691,11693,11695,11697,11699],{"class":1225,"line":1226},[1223,11692,1745],{"class":1679},[1223,11694,1748],{"class":1679},[1223,11696,2820],{"class":1751},[1223,11698,1754],{"class":1285},[1223,11700,1757],{"class":1236},[1223,11702,11703,11705,11707],{"class":1225,"line":1233},[1223,11704,9678],{"class":1240},[1223,11706,1765],{"class":1236},[1223,11708,1768],{"class":1285},[1223,11710,11711,11713,11716,11718],{"class":1225,"line":1263},[1223,11712,9188],{"class":1236},[1223,11714,11715],{"class":1254},"@nuxt/content",[1223,11717,1957],{"class":1236},[1223,11719,1780],{"class":1236},[1223,11721,11722,11724],{"class":1225,"line":1296},[1223,11723,9695],{"class":1285},[1223,11725,1780],{"class":1236},[1223,11727,11728,11730],{"class":1225,"line":1325},[1223,11729,1801],{"class":1236},[1223,11731,1804],{"class":1285},[1143,11733,11734],{},"Shiki will generate the following HTML:",[1213,11736,11738],{"className":1215,"code":11737,"language":1217,"meta":1218,"style":1218},"\u003Cpre class=\"shiki material-theme-palenight\" style=\"background-color:#292D3E;color:#babed8\" tabindex=\"0\">\n  \u003Ccode>\n    \u003Cspan class=\"line\">\u003Cspan style=\"color:#89DDFF;font-style:italic\">export\u003C/span>\u003Cspan style=\"color:#89DDFF;font-style:italic\"> default\u003C/span>\u003Cspan style=\"color:#82AAFF\"> defineNuxtConfig\u003C/span>\u003Cspan style=\"color:#BABED8\">(\u003C/span>\u003Cspan style=\"color:#89DDFF\">{\u003C/span>\u003C/span>\n    \u003Cspan class=\"line\">\u003Cspan style=\"color:#F07178\">  modules\u003C/span>\u003Cspan style=\"color:#89DDFF\">:\u003C/span>\u003Cspan style=\"color:#BABED8\"> [\u003C/span>\u003C/span>\n    \u003Cspan class=\"line\">\u003Cspan style=\"color:#89DDFF\">    '\u003C/span>\u003Cspan style=\"color:#C3E88D\">@nuxt/content\u003C/span>\u003Cspan style=\"color:#89DDFF\">'\u003C/span>\u003Cspan style=\"color:#89DDFF\">,\u003C/span>\u003C/span>\n    \u003Cspan class=\"line\">\u003Cspan style=\"color:#BABED8\">  ]\u003C/span>\u003Cspan style=\"color:#89DDFF\">,\u003C/span>\u003C/span>\n    \u003Cspan class=\"line\">\u003Cspan style=\"color:#89DDFF\">}\u003C/span>\u003Cspan style=\"color:#BABED8\">)\u003C/span>\u003C/span>\n  \u003C/code>\n\u003C/pre>\n",[1220,11739,11740,11783,11791,11928,12017,12128,12194,12260,12268],{"__ignoreMap":1218},[1223,11741,11742,11744,11746,11748,11750,11752,11755,11757,11760,11762,11764,11767,11769,11772,11774,11776,11779,11781],{"class":1225,"line":1226},[1223,11743,1237],{"class":1236},[1223,11745,1213],{"class":1240},[1223,11747,1245],{"class":1244},[1223,11749,1248],{"class":1236},[1223,11751,1251],{"class":1236},[1223,11753,11754],{"class":1254},"shiki material-theme-palenight",[1223,11756,1251],{"class":1236},[1223,11758,11759],{"class":1244}," style",[1223,11761,1248],{"class":1236},[1223,11763,1251],{"class":1236},[1223,11765,11766],{"class":1254},"background-color:#292D3E;color:#babed8",[1223,11768,1251],{"class":1236},[1223,11770,11771],{"class":1244}," tabindex",[1223,11773,1248],{"class":1236},[1223,11775,1251],{"class":1236},[1223,11777,11778],{"class":1254},"0",[1223,11780,1251],{"class":1236},[1223,11782,1260],{"class":1236},[1223,11784,11785,11787,11789],{"class":1225,"line":1233},[1223,11786,1266],{"class":1236},[1223,11788,1220],{"class":1240},[1223,11790,1260],{"class":1236},[1223,11792,11793,11795,11797,11799,11801,11803,11805,11807,11809,11811,11813,11815,11817,11820,11822,11824,11826,11828,11830,11832,11834,11836,11838,11840,11842,11844,11846,11848,11850,11852,11854,11856,11858,11860,11862,11865,11867,11869,11871,11873,11875,11877,11879,11881,11883,11885,11888,11890,11892,11894,11896,11898,11900,11902,11904,11906,11908,11911,11913,11915,11917,11919,11921,11924,11926],{"class":1225,"line":1263},[1223,11794,5138],{"class":1236},[1223,11796,1223],{"class":1240},[1223,11798,1245],{"class":1244},[1223,11800,1248],{"class":1236},[1223,11802,1251],{"class":1236},[1223,11804,1225],{"class":1254},[1223,11806,1251],{"class":1236},[1223,11808,7251],{"class":1236},[1223,11810,1223],{"class":1240},[1223,11812,11759],{"class":1244},[1223,11814,1248],{"class":1236},[1223,11816,1251],{"class":1236},[1223,11818,11819],{"class":1254},"color:#89DDFF;font-style:italic",[1223,11821,1251],{"class":1236},[1223,11823,1282],{"class":1236},[1223,11825,1745],{"class":1285},[1223,11827,1289],{"class":1236},[1223,11829,1223],{"class":1240},[1223,11831,7251],{"class":1236},[1223,11833,1223],{"class":1240},[1223,11835,11759],{"class":1244},[1223,11837,1248],{"class":1236},[1223,11839,1251],{"class":1236},[1223,11841,11819],{"class":1254},[1223,11843,1251],{"class":1236},[1223,11845,1282],{"class":1236},[1223,11847,1748],{"class":1285},[1223,11849,1289],{"class":1236},[1223,11851,1223],{"class":1240},[1223,11853,7251],{"class":1236},[1223,11855,1223],{"class":1240},[1223,11857,11759],{"class":1244},[1223,11859,1248],{"class":1236},[1223,11861,1251],{"class":1236},[1223,11863,11864],{"class":1254},"color:#82AAFF",[1223,11866,1251],{"class":1236},[1223,11868,1282],{"class":1236},[1223,11870,2820],{"class":1285},[1223,11872,1289],{"class":1236},[1223,11874,1223],{"class":1240},[1223,11876,7251],{"class":1236},[1223,11878,1223],{"class":1240},[1223,11880,11759],{"class":1244},[1223,11882,1248],{"class":1236},[1223,11884,1251],{"class":1236},[1223,11886,11887],{"class":1254},"color:#BABED8",[1223,11889,1251],{"class":1236},[1223,11891,1282],{"class":1236},[1223,11893,1754],{"class":1285},[1223,11895,1289],{"class":1236},[1223,11897,1223],{"class":1240},[1223,11899,7251],{"class":1236},[1223,11901,1223],{"class":1240},[1223,11903,11759],{"class":1244},[1223,11905,1248],{"class":1236},[1223,11907,1251],{"class":1236},[1223,11909,11910],{"class":1254},"color:#89DDFF",[1223,11912,1251],{"class":1236},[1223,11914,1282],{"class":1236},[1223,11916,5828],{"class":1285},[1223,11918,1289],{"class":1236},[1223,11920,1223],{"class":1240},[1223,11922,11923],{"class":1236},">\u003C/",[1223,11925,1223],{"class":1240},[1223,11927,1260],{"class":1236},[1223,11929,11930,11932,11934,11936,11938,11940,11942,11944,11946,11948,11950,11952,11954,11957,11959,11961,11963,11965,11967,11969,11971,11973,11975,11977,11979,11981,11983,11985,11987,11989,11991,11993,11995,11997,11999,12001,12003,12005,12007,12009,12011,12013,12015],{"class":1225,"line":1296},[1223,11931,5138],{"class":1236},[1223,11933,1223],{"class":1240},[1223,11935,1245],{"class":1244},[1223,11937,1248],{"class":1236},[1223,11939,1251],{"class":1236},[1223,11941,1225],{"class":1254},[1223,11943,1251],{"class":1236},[1223,11945,7251],{"class":1236},[1223,11947,1223],{"class":1240},[1223,11949,11759],{"class":1244},[1223,11951,1248],{"class":1236},[1223,11953,1251],{"class":1236},[1223,11955,11956],{"class":1254},"color:#F07178",[1223,11958,1251],{"class":1236},[1223,11960,1282],{"class":1236},[1223,11962,9678],{"class":1285},[1223,11964,1289],{"class":1236},[1223,11966,1223],{"class":1240},[1223,11968,7251],{"class":1236},[1223,11970,1223],{"class":1240},[1223,11972,11759],{"class":1244},[1223,11974,1248],{"class":1236},[1223,11976,1251],{"class":1236},[1223,11978,11910],{"class":1254},[1223,11980,1251],{"class":1236},[1223,11982,1282],{"class":1236},[1223,11984,1765],{"class":1285},[1223,11986,1289],{"class":1236},[1223,11988,1223],{"class":1240},[1223,11990,7251],{"class":1236},[1223,11992,1223],{"class":1240},[1223,11994,11759],{"class":1244},[1223,11996,1248],{"class":1236},[1223,11998,1251],{"class":1236},[1223,12000,11887],{"class":1254},[1223,12002,1251],{"class":1236},[1223,12004,1282],{"class":1236},[1223,12006,2848],{"class":1285},[1223,12008,1289],{"class":1236},[1223,12010,1223],{"class":1240},[1223,12012,11923],{"class":1236},[1223,12014,1223],{"class":1240},[1223,12016,1260],{"class":1236},[1223,12018,12019,12021,12023,12025,12027,12029,12031,12033,12035,12037,12039,12041,12043,12045,12047,12049,12051,12053,12055,12057,12059,12061,12063,12065,12068,12070,12072,12074,12076,12078,12080,12082,12084,12086,12088,12090,12092,12094,12096,12098,12100,12102,12104,12106,12108,12110,12112,12114,12116,12118,12120,12122,12124,12126],{"class":1225,"line":1325},[1223,12020,5138],{"class":1236},[1223,12022,1223],{"class":1240},[1223,12024,1245],{"class":1244},[1223,12026,1248],{"class":1236},[1223,12028,1251],{"class":1236},[1223,12030,1225],{"class":1254},[1223,12032,1251],{"class":1236},[1223,12034,7251],{"class":1236},[1223,12036,1223],{"class":1240},[1223,12038,11759],{"class":1244},[1223,12040,1248],{"class":1236},[1223,12042,1251],{"class":1236},[1223,12044,11910],{"class":1254},[1223,12046,1251],{"class":1236},[1223,12048,1282],{"class":1236},[1223,12050,9188],{"class":1285},[1223,12052,1289],{"class":1236},[1223,12054,1223],{"class":1240},[1223,12056,7251],{"class":1236},[1223,12058,1223],{"class":1240},[1223,12060,11759],{"class":1244},[1223,12062,1248],{"class":1236},[1223,12064,1251],{"class":1236},[1223,12066,12067],{"class":1254},"color:#C3E88D",[1223,12069,1251],{"class":1236},[1223,12071,1282],{"class":1236},[1223,12073,11715],{"class":1285},[1223,12075,1289],{"class":1236},[1223,12077,1223],{"class":1240},[1223,12079,7251],{"class":1236},[1223,12081,1223],{"class":1240},[1223,12083,11759],{"class":1244},[1223,12085,1248],{"class":1236},[1223,12087,1251],{"class":1236},[1223,12089,11910],{"class":1254},[1223,12091,1251],{"class":1236},[1223,12093,1282],{"class":1236},[1223,12095,1957],{"class":1285},[1223,12097,1289],{"class":1236},[1223,12099,1223],{"class":1240},[1223,12101,7251],{"class":1236},[1223,12103,1223],{"class":1240},[1223,12105,11759],{"class":1244},[1223,12107,1248],{"class":1236},[1223,12109,1251],{"class":1236},[1223,12111,11910],{"class":1254},[1223,12113,1251],{"class":1236},[1223,12115,1282],{"class":1236},[1223,12117,2333],{"class":1285},[1223,12119,1289],{"class":1236},[1223,12121,1223],{"class":1240},[1223,12123,11923],{"class":1236},[1223,12125,1223],{"class":1240},[1223,12127,1260],{"class":1236},[1223,12129,12130,12132,12134,12136,12138,12140,12142,12144,12146,12148,12150,12152,12154,12156,12158,12160,12162,12164,12166,12168,12170,12172,12174,12176,12178,12180,12182,12184,12186,12188,12190,12192],{"class":1225,"line":1355},[1223,12131,5138],{"class":1236},[1223,12133,1223],{"class":1240},[1223,12135,1245],{"class":1244},[1223,12137,1248],{"class":1236},[1223,12139,1251],{"class":1236},[1223,12141,1225],{"class":1254},[1223,12143,1251],{"class":1236},[1223,12145,7251],{"class":1236},[1223,12147,1223],{"class":1240},[1223,12149,11759],{"class":1244},[1223,12151,1248],{"class":1236},[1223,12153,1251],{"class":1236},[1223,12155,11887],{"class":1254},[1223,12157,1251],{"class":1236},[1223,12159,1282],{"class":1236},[1223,12161,9695],{"class":1285},[1223,12163,1289],{"class":1236},[1223,12165,1223],{"class":1240},[1223,12167,7251],{"class":1236},[1223,12169,1223],{"class":1240},[1223,12171,11759],{"class":1244},[1223,12173,1248],{"class":1236},[1223,12175,1251],{"class":1236},[1223,12177,11910],{"class":1254},[1223,12179,1251],{"class":1236},[1223,12181,1282],{"class":1236},[1223,12183,2333],{"class":1285},[1223,12185,1289],{"class":1236},[1223,12187,1223],{"class":1240},[1223,12189,11923],{"class":1236},[1223,12191,1223],{"class":1240},[1223,12193,1260],{"class":1236},[1223,12195,12196,12198,12200,12202,12204,12206,12208,12210,12212,12214,12216,12218,12220,12222,12224,12226,12228,12230,12232,12234,12236,12238,12240,12242,12244,12246,12248,12250,12252,12254,12256,12258],{"class":1225,"line":1771},[1223,12197,5138],{"class":1236},[1223,12199,1223],{"class":1240},[1223,12201,1245],{"class":1244},[1223,12203,1248],{"class":1236},[1223,12205,1251],{"class":1236},[1223,12207,1225],{"class":1254},[1223,12209,1251],{"class":1236},[1223,12211,7251],{"class":1236},[1223,12213,1223],{"class":1240},[1223,12215,11759],{"class":1244},[1223,12217,1248],{"class":1236},[1223,12219,1251],{"class":1236},[1223,12221,11910],{"class":1254},[1223,12223,1251],{"class":1236},[1223,12225,1282],{"class":1236},[1223,12227,1801],{"class":1285},[1223,12229,1289],{"class":1236},[1223,12231,1223],{"class":1240},[1223,12233,7251],{"class":1236},[1223,12235,1223],{"class":1240},[1223,12237,11759],{"class":1244},[1223,12239,1248],{"class":1236},[1223,12241,1251],{"class":1236},[1223,12243,11887],{"class":1254},[1223,12245,1251],{"class":1236},[1223,12247,1282],{"class":1236},[1223,12249,2541],{"class":1285},[1223,12251,1289],{"class":1236},[1223,12253,1223],{"class":1240},[1223,12255,11923],{"class":1236},[1223,12257,1223],{"class":1240},[1223,12259,1260],{"class":1236},[1223,12261,12262,12264,12266],{"class":1225,"line":1783},[1223,12263,5211],{"class":1236},[1223,12265,1220],{"class":1240},[1223,12267,1260],{"class":1236},[1223,12269,12270,12272,12274],{"class":1225,"line":1792},[1223,12271,1289],{"class":1236},[1223,12273,1213],{"class":1240},[1223,12275,1260],{"class":1236},[1143,12277,12278,12279,12282],{},"It might look a bit overwhelming if you read it, but ",[1159,12280,12281],{},"this piece of HTML works everywhere without any JavaScript or CSS",". TextMate grammars has a very rich representation of the types of every token (TextMate scopes). Since Shiki flattens all the tokens into styled spans, it achieves accurate results that most traditional CSS-based highlighters have difficulties achieving.",[1143,12284,12285],{},"While Shiki is awesome, it's still a library that is designed to run on Node.js. This means it is limited to highlighting static code only and would have trouble with dynamic code, because Shiki doesn't work in the browser. In addition, Shiki relies on the WASM binary of Oniguruma, as well as a bunch of heavy grammar and theme files in JSON. It uses Node.js filesystem and path resolution to load these files, which is not accessible in the browser.",[1143,12287,12288,12289,12294,12295,12300,12301,12304],{},"To improve that situation, I ",[2006,12290,12293],{"href":12291,"rel":12292},"https://github.com/shikijs/shiki/issues/91",[2010],"started this RFC"," that later landed with ",[2006,12296,12299],{"href":12297,"rel":12298},"https://github.com/shikijs/shiki/pull/109",[2010],"this PR"," and shipped in Shiki v0.9. While it abstracted the file loading layer to use fetch or filesystem based on the environment, it's still quite complicated to use as you need to serve the grammars and theme files somewhere in your bundle or CDN manually, then call the ",[1220,12302,12303],{},"setCDN"," method to tell Shiki where to load these files.",[1143,12306,12307],{},"The solution is not perfect but at least it made it possible to run Shiki in the browser to highlight dynamic content. We have been using that approach since then - until the story of this article began.",[1147,12309,12311],{"id":12310},"the-start","The Start",[1143,12313,12314,12315,12318,12319,12324],{},"Nuxt is putting a lot effort in pushing the ",[2006,12316,12317],{"href":1045},"web to the edge",", making the web more accessible with lower latency and better performance. Like CDN servers, edge hosting services such as ",[2006,12320,12323],{"href":12321,"rel":12322},"https://workers.cloudflare.com/",[2010],"CloudFlare Workers"," are deployed all over the world. Users get the content from the nearest edge server without the round trips to the origin server which could be thousands of miles away. With the awesome benefits it provides, it also comes with some trade-offs. For example, edge servers use a restricted runtime environment. CloudFlare Workers also does not support file system access and usually don't preserve the state between requests. While Shiki's main overhead is loading the grammars and themes upfront, that wouldn't work well in the edge environment.",[1143,12326,12327,12328,12333,12334,12338],{},"It all started with a chat between ",[2006,12329,12332],{"href":12330,"rel":12331},"https://x.com/Atinux",[2010],"Sébastien"," and me. We were trying to make ",[2006,12335,4387],{"href":12336,"rel":12337},"https://github.com/nuxt/content",[2010]," which uses Shiki to highlight the code blocks, to work on the edge.",[1143,12340,12341],{},[2243,12342],{"alt":12343,"className":12344,"src":12347},"Chat History Between Sébastien and Anthony",[2250,12345,12346,2247,2249],"shadow","max-w-[700px]","/assets/blog/shiki-start-chat.png",[1143,12349,12350,12351,12358,12359,12362,12363,12368],{},"I started the experiments by patching ",[2006,12352,12355],{"href":12353,"rel":12354},"https://github.com/pi0/shiki-es",[2010],[1220,12356,12357],{},"shiki-es"," (a ESM build of Shiki by ",[2006,12360,10194],{"href":10192,"rel":12361},[2010],") locally, to convert the grammars and themes files into ",[2006,12364,12367],{"href":12365,"rel":12366},"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules",[2010],"ECMAScript Module (ESM)"," so that it could be understood and bundled by the build tools. This was done to create the code bundle for CloudFlare Workers to consume without using the filesystem nor making network requests.",[1213,12370,12373],{"className":1669,"code":12371,"filename":12372,"language":1672,"meta":1218,"style":1218},"import fs from 'fs/promises'\n\nconst cssGrammar = JSON.parse(await fs.readFile('../langs/css.json', 'utf-8'))\n","Before - Read JSON assets from filesystem",[1220,12374,12375,12391,12395],{"__ignoreMap":1218},[1223,12376,12377,12379,12382,12384,12386,12389],{"class":1225,"line":1226},[1223,12378,1680],{"class":1679},[1223,12380,12381],{"class":1285}," fs ",[1223,12383,1711],{"class":1679},[1223,12385,1695],{"class":1236},[1223,12387,12388],{"class":1254},"fs/promises",[1223,12390,1701],{"class":1236},[1223,12392,12393],{"class":1225,"line":1233},[1223,12394,1740],{"emptyLinePlaceholder":1739},[1223,12396,12397,12399,12402,12404,12407,12409,12412,12414,12416,12419,12421,12424,12426,12428,12431,12433,12435,12437,12440,12442],{"class":1225,"line":1263},[1223,12398,3214],{"class":1244},[1223,12400,12401],{"class":1285}," cssGrammar ",[1223,12403,1248],{"class":1236},[1223,12405,12406],{"class":1285}," JSON",[1223,12408,2281],{"class":1236},[1223,12410,12411],{"class":1751},"parse",[1223,12413,1754],{"class":1285},[1223,12415,3773],{"class":1679},[1223,12417,12418],{"class":1285}," fs",[1223,12420,2281],{"class":1236},[1223,12422,12423],{"class":1751},"readFile",[1223,12425,1754],{"class":1285},[1223,12427,1957],{"class":1236},[1223,12429,12430],{"class":1254},"../langs/css.json",[1223,12432,1957],{"class":1236},[1223,12434,2333],{"class":1236},[1223,12436,1695],{"class":1236},[1223,12438,12439],{"class":1254},"utf-8",[1223,12441,1957],{"class":1236},[1223,12443,12444],{"class":1285},"))\n",[1213,12446,12449],{"className":1669,"code":12447,"filename":12448,"language":1672,"meta":1218,"style":1218},"const cssGrammar = await import('../langs/css.mjs').then(m => m.default)\n","After - Using ESM import",[1220,12450,12451],{"__ignoreMap":1218},[1223,12452,12453,12455,12457,12459,12461,12464,12466,12468,12471,12473,12475,12477,12480,12482,12485,12487,12490,12492],{"class":1225,"line":1226},[1223,12454,3214],{"class":1244},[1223,12456,12401],{"class":1285},[1223,12458,1248],{"class":1236},[1223,12460,10512],{"class":1679},[1223,12462,12463],{"class":1236}," import",[1223,12465,1754],{"class":1285},[1223,12467,1957],{"class":1236},[1223,12469,12470],{"class":1254},"../langs/css.mjs",[1223,12472,1957],{"class":1236},[1223,12474,2541],{"class":1285},[1223,12476,2281],{"class":1236},[1223,12478,12479],{"class":1751},"then",[1223,12481,1754],{"class":1285},[1223,12483,12484],{"class":2329},"m",[1223,12486,3125],{"class":1244},[1223,12488,12489],{"class":1285}," m",[1223,12491,2281],{"class":1236},[1223,12493,12494],{"class":1285},"default)\n",[1143,12496,12497,12498,12505,12506,12508,12509,12512,12513,12515,12516,4363,12521,12526,12527,2281],{},"We need to wrap the JSON files into ESM as inline literal so that we can use ",[2006,12499,12502],{"href":12500,"rel":12501},"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import",[2010],[1220,12503,12504],{},"import()"," to dynamically import them. The difference is that ",[1220,12507,12504],{}," is a standard JavaScript feature that works everywhere, while ",[1220,12510,12511],{},"fs.readFile"," is a Node.js specific API that only works in Node.js. Having ",[1220,12514,12504],{}," statically would also make bundlers like ",[2006,12517,12520],{"href":12518,"rel":12519},"https://rollupjs.org/",[2010],"Rollup",[2006,12522,12525],{"href":12523,"rel":12524},"https://webpack.js.org/",[2010],"webpack"," able to construct the module relationship graph and ",[2006,12528,12531],{"href":12529,"rel":12530},"https://rollupjs.org/tutorial/#code-splitting",[2010],"emit the bundled code as chunks",[1143,12533,12534],{},"Then, I realized that it actually takes more than that to make it work on edge runtimes. Since bundlers expect imports to be resolvable at build time (meaning that in order to support all the languages and themes), we need to list all the import statements in every single grammar and theme file in the codebase. This would end up with a huge bundle size with a bunch of grammars and themes that you might not actually use. This problem is particularly important in the edge environment, where the bundle size is critical for performance.",[1143,12536,12537],{},"So, we needed to figure out a better middle ground to make it work better.",[1147,12539,12541],{"id":12540},"the-fork-shikiji","The Fork - Shikiji",[1143,12543,12544,12545,12550,12551,2281],{},"Knowing this might fundamentally change the way Shiki works, and since we don't want to risk breaking the existing Shiki users with our experiments, I started a fork of Shiki called ",[2006,12546,12549],{"href":12547,"rel":12548},"https://github.com/antfu/shikiji",[2010],"Shikiji",". I rewrote the code from scratch while keeping the previous API design decisions in mind. The goal is to make Shiki runtime-agnostic, performant and efficient, like the philosophy we have at ",[2006,12552,10247],{"href":12553,"rel":12554},"https://github.com/unjs",[2010],[1143,12556,12557,12558,12563,12564,4363,12570,12577,12578,12583,12584,12586,12587,12594,12595,12600,12601,12606,12607,12614],{},"To make that happen, we need to make Shikiji completely ESM-friendly, pure and ",[2006,12559,12562],{"href":12560,"rel":12561},"https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking",[2010],"tree-shakable",". This goes all the way up to the dependencies of Shiki such as ",[2006,12565,12567],{"href":11651,"rel":12566},[2010],[1220,12568,12569],{},"vscode-oniguruma",[2006,12571,12574],{"href":12572,"rel":12573},"https://github.com/microsoft/vscode-textmate",[2010],[1220,12575,12576],{},"vscode-textmate",", which are provided in ",[2006,12579,12582],{"href":12580,"rel":12581},"https://requirejs.org/docs/commonjs.html",[2010],"Common JS (CJS)"," format.  ",[1220,12585,12569],{}," also contains a WASM binding generated by ",[2006,12588,12591],{"href":12589,"rel":12590},"https://github.com/emscripten-core/emscripten",[2010],[1220,12592,12593],{},"emscripten"," that contains ",[2006,12596,12599],{"href":12597,"rel":12598},"https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/no-floating-promises.md",[2010],"dangling promises"," that will make CloudFlare Workers fail to finish the request. We ended up by embedding the WASM binary into a ",[2006,12602,12605],{"href":12603,"rel":12604},"https://en.wikipedia.org/wiki/Base64",[2010],"base64 string"," and shipping it as an ES module, manually rewriting the WASM binding to avoid dangling promises, and ",[2006,12608,12611,12612],{"href":12609,"rel":12610},"https://github.com/shikijs/shiki/blob/main/CONTRIBUTING.md#clone",[2010],"vendored ",[1220,12613,12576],{}," to compile from its source code and produce the efficient ESM output.",[1143,12616,12617,12618,12623],{},"The end result was very promising. We managed to get Shikiji working on any runtime environment, with even the possibility to ",[2006,12619,12622],{"href":12620,"rel":12621},"https://shiki.style/guide/install#cdn-usage",[2010],"import it from CDN and run in the browser"," with a single line of code.",[1143,12625,12626,12627,12634,12635,12640],{},"We also took the chance to improve the API and the internal architecture of Shiki. We switched from simple string concatenation to use ",[2006,12628,12631],{"href":12629,"rel":12630},"https://github.com/syntax-tree/hast",[2010],[1220,12632,12633],{},"hast",", creating an Abstract Syntax Tree (AST) for generating the HTML output. This opens up the possibility of exposing a ",[2006,12636,12639],{"href":12637,"rel":12638},"https://shiki.style/guide/transformers",[2010],"Transformers API"," to allow users to modify the intermediate HAST and do many cool integrations that would be very hard to achieve previously.",[1143,12642,12643,12644,12649,12650,12655,12656,12661,12662,2281],{},"Dark/Light mode support ",[2006,12645,12648],{"href":12646,"rel":12647},"https://github.com/shikijs/shiki/issues/33",[2010],"was a frequently requested feature",". Because of the static approach Shiki takes, it won't be possible to change the theme on the fly at rendering. The solution in the past was to generate the highlighted HTML twice, and toggle their visibility based on the user's preference - it wasn't efficient as it duplicate the payload, or used ",[2006,12651,12654],{"href":12652,"rel":12653},"https://github.com/shikijs/shiki/pull/212",[2010],"CSS variables theme"," which lost the granular highlighting Shiki is great for. With the new architecture that Shikiji has, I took a step back and rethought the problem, and ",[2006,12657,12660],{"href":12658,"rel":12659},"https://github.com/shikijs/shiki/issues/33#issuecomment-1676362336",[2010],"came up with the idea"," of breaking down the common tokens and merge multiple themes as inlined CSS variables, which provide  efficient output while aligning with the Shiki's philosophy. You can learn more about it in ",[2006,12663,12666],{"href":12664,"rel":12665},"https://shiki.style/guide/dual-themes",[2010],"Shiki's documentation",[1143,12668,12669,12670,12678],{},"To make the migration easier, we also created the ",[2006,12671,12674,12677],{"href":12672,"rel":12673},"https://shikiji.netlify.app/guide/compat",[2010],[1220,12675,12676],{},"shikiji-compat"," compatibility layer",", which uses Shikiji's new foundation and provides backward compatibility API.",[1143,12680,12681,12682,12687,12688,12691,12692,12695,12696,12703,12704,12709,12710,12715,12716,12719],{},"To get Shikiji to work on Cloudflare Workers, we had one last challenge as they don't support ",[2006,12683,12686],{"href":12684,"rel":12685},"https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/instantiate_static",[2010],"initiating WASM instance","s from inlined binary data. Instead it requires importing the static ",[1220,12689,12690],{},".wasm"," assets for security reasons. This means that our \"All-in-ESM\" approach does not work well on CloudFlare. This would require extra work for users to provide different WASM sources, which makes the experience more difficult than we intended. At this moment, ",[2006,12693,10194],{"href":10192,"rel":12694},[2010]," stepped in and made the universal layer ",[2006,12697,12700],{"href":12698,"rel":12699},"https://github.com/unjs/unwasm",[2010],[1220,12701,12702],{},"unjs/unwasm",", which supports the upcoming ",[2006,12705,12708],{"href":12706,"rel":12707},"https://github.com/WebAssembly/esm-integration/tree/main/proposals/esm-integration",[2010],"WebAssembly/ES Module Integration"," proposal. It has been integrated into ",[2006,12711,12714],{"href":12712,"rel":12713},"https://github.com/unjs/nitro/pull/2037",[2010],"Nitro to have automated WASM targets",". We hope that ",[1220,12717,12718],{},"unwasm"," will help developers to have a better experience when working with WASM.",[1143,12721,12722,12723,5062,12726,4363,12731,12736],{},"Overall, the Shikiji rewrite works well. ",[2006,12724,4387],{"href":12336,"rel":12725},[2010],[2006,12727,12730],{"href":12728,"rel":12729},"https://vitepress.dev/",[2010],"VitePress",[2006,12732,12735],{"href":12733,"rel":12734},"https://astro.build/",[2010],"Astro"," have been migrated to it. The feedback we have received has also been very positive.",[1147,12738,12740],{"id":12739},"merging-back","Merging Back",[1143,12742,12743,12744,12748,12749,12754],{},"I am a team member of Shiki and have helped to do releases from time to time. While ",[2006,12745,12747],{"href":11645,"rel":12746},[2010],"Pine"," is the lead of Shiki, he was busy on other stuff and Shiki's iterations slowed down. During the experiments in Shikiji, I ",[2006,12750,12753],{"href":12751,"rel":12752},"https://github.com/shikijs/shiki/issues/510",[2010],"proposed a few improvements"," that could help Shiki acquire a modern structure. While generally everyone agreed with that direction, there would have been quite a lot of work to do and no one started to work on that.",[1143,12756,12757],{},"While we were happy to use Shikiji to solve the problems we had, we certainly didn't want to see the community split by two different versions of Shiki. After a call with Pine, we made the consensus to merge the two projects into one:",[3611,12759,12763],{"color":12760,"icon":12761,"to":12762},"purple","i-octicon-git-merge-24","https://github.com/shikijs/shiki/pull/557",[1143,12764,12765,12766],{},"feat!: merge Shikiji back into Shiki for v1.0 ",[1223,12767,12770],{"className":12768},[12769],"opacity-50","#557",[1143,12772,12773,12774,12777],{},"We are really happy to see that our work in Shikiji has been merged back to Shiki, that not only works for ourselves, but also benefits the entire community. With this merge, it ",[1159,12775,12776],{},"solves around 95% of the open issues"," we have had in Shiki for years:",[1143,12779,12780],{},[2243,12781],{"alt":12782,"className":12783,"src":12784},"Shikiji Merged Back to Shiki",[2250,12345],"/assets/blog/shiki-merge-pr.png",[1143,12786,12787,12788,12793],{},"Shiki now also got ",[2006,12789,12792],{"href":12790,"rel":12791},"https://shiki.style/",[2010],"a brand new documentation site"," where you can also play it right in your browser (thanks to the agnostic approach!). Many frameworks now has built-in integration with Shiki, maybe you are already using it somewhere!",[1147,12795,12797],{"id":12796},"twoslash","Twoslash",[1143,12799,12800,12804,12805,12810,12811,2260,12816,12821,12822,12827,12828,12833,12834,12839,12840,12843],{},[2006,12801,12797],{"href":12802,"rel":12803},"https://github.com/twoslashes/twoslash",[2010]," is an integration tool to retrieve type information from ",[2006,12806,12809],{"href":12807,"rel":12808},"https://github.com/microsoft/TypeScript/wiki/Using-the-Language-Service-API",[2010],"TypeScript Language Services"," and generated to your code snippet. It essentially make your static code snippet to have hover type information similar to your VS Code editor. It's made by ",[2006,12812,12815],{"href":12813,"rel":12814},"https://github.com/orta",[2010],"Orta Therox",[2006,12817,12820],{"href":12818,"rel":12819},"https://github.com/microsoft/TypeScript-Website",[2010],"TypeScript documentation site",", there you can find ",[2006,12823,12826],{"href":12824,"rel":12825},"https://github.com/microsoft/TypeScript-Website/tree/v2/packages/ts-twoslasher",[2010],"the original source code here",". Orta also created the ",[2006,12829,12832],{"href":12830,"rel":12831},"https://github.com/shikijs/twoslash",[2010],"Twoslash integration for Shiki v0.x versions",". Back then, Shiki ",[2006,12835,12838],{"href":12836,"rel":12837},"https://github.com/shikijs/shiki/issues/380",[2010],"did not have proper plugin system",", that makes the ",[1220,12841,12842],{},"shiki-twoslash"," had to be built as a wrapper over Shiki, make it a bit hard to set up as the existing Shiki integrations won't directly work with Twoslash.",[1143,12845,12846,12847,12852,12853,12858],{},"We also took the chance to revise the Twoslash integrations when we were rewriting Shikiji, also a way to ",[2006,12848,12851],{"href":12849,"rel":12850},"https://en.wikipedia.org/wiki/Eating_your_own_dog_food",[2010],"dog-fooding"," and verify the extensibility. With the new HAST internal, we are able to ",[2006,12854,12857],{"href":12855,"rel":12856},"https://shiki.style/packages/twoslash",[2010],"integrate Twoslash as a transformer plugin",", making it works everywhere that Shiki works and also in a composable way to be used with other transformers.",[1143,12860,12861,12862,12864,12865,12868],{},"With this, we started to think that we could probably get Twoslash to work on ",[2006,12863,2573],{"href":5061},", the website you are looking at. nuxt.com uses ",[2006,12866,4387],{"href":12336,"rel":12867},[2010]," under the hood, and different from other documentation tools like VitePress, one of the benefits Nuxt Content provides is that it's able to handle dynamic content and runs on the edge. Since Twoslash is relying on TypeScript as well as the giant types modules graph from your dependencies, that would be not ideal to ship all those things to the edge or browser. Sounds tricky, but challenge accepted!",[1143,12870,12871,12872,12877,12878,12883,12884,12891],{},"We first come up of fetching the types on-demand from CDN, using the ",[2006,12873,12876],{"href":12874,"rel":12875},"https://github.com/microsoft/TypeScript-Website/tree/v2/packages/ata",[2010],"Auto-Type-Acquisition"," technique that you will see on the ",[2006,12879,12882],{"href":12880,"rel":12881},"https://www.typescriptlang.org/play",[2010],"TypeScript playground",". We made the ",[2006,12885,12888],{"href":12886,"rel":12887},"https://github.com/antfu/twoslash-cdn",[2010],[1220,12889,12890],{},"twoslash-cdn"," that allows Twoslash to run in any runtime. However, still, it sounds like not the most optimal solution, as it would still require to make many network requests that might defeat the purpose of running on the edge.",[1143,12893,12894,12895,12902,12903,12910],{},"After a few iterations on the underlying tools (e.g. on ",[2006,12896,12899],{"href":12897,"rel":12898},"https://github.com/nuxt-modules/mdc/pull/129",[2010],[1220,12900,12901],{},"@nuxtjs/mdc",", the markdown compiler used by Nuxt Content), we managed to take the hybrid approach and made ",[2006,12904,12907],{"href":12905,"rel":12906},"https://github.com/antfu/nuxt-content-twoslash",[2010],[1220,12908,12909],{},"nuxt-content-twoslash"," that runs Twoslash on build time and caches the results for edge rendering. This way we could avoid shipping any extra dependencies to the final bundle, but still have the rich interactive code snippets on the website:",[1213,12912,12914],{"className":2595,"code":12913,"language":2597,"meta":12796,"style":1218},"\u003Cscript setup>\n// Try hover on identifiers below to see the types\nconst count = useState('counter', () => 0)\nconst double = computed(() => count.value * 2)\n\u003C/script>\n\n\u003Ctemplate>\n  \u003Cbutton>Count is: {{ count }}\u003C/button>\n  \u003Cdiv>Double is: {{ double }}\u003C/div>\n\u003C/template>\n",[1220,12915,12916,12926,12931,12963,12996,13004,13008,13016,13033,13050],{"__ignoreMap":1218},[1223,12917,12918,12920,12922,12924],{"class":1225,"line":1226},[1223,12919,1237],{"class":1236},[1223,12921,5899],{"class":1240},[1223,12923,5902],{"class":1244},[1223,12925,1260],{"class":1236},[1223,12927,12928],{"class":1225,"line":1233},[1223,12929,12930],{"class":1229},"// Try hover on identifiers below to see the types\n",[1223,12932,12933,12935,12938,12940,12943,12945,12947,12950,12952,12954,12956,12958,12961],{"class":1225,"line":1263},[1223,12934,3214],{"class":1244},[1223,12936,12937],{"class":1285}," count ",[1223,12939,1248],{"class":1236},[1223,12941,12942],{"class":1751}," useState",[1223,12944,1754],{"class":1285},[1223,12946,1957],{"class":1236},[1223,12948,12949],{"class":1254},"counter",[1223,12951,1957],{"class":1236},[1223,12953,2333],{"class":1236},[1223,12955,3122],{"class":1236},[1223,12957,3125],{"class":1244},[1223,12959,12960],{"class":6166}," 0",[1223,12962,1804],{"class":1285},[1223,12964,12965,12967,12970,12972,12975,12977,12979,12981,12984,12986,12989,12992,12994],{"class":1225,"line":1296},[1223,12966,3214],{"class":1244},[1223,12968,12969],{"class":1285}," double ",[1223,12971,1248],{"class":1236},[1223,12973,12974],{"class":1751}," computed",[1223,12976,1754],{"class":1285},[1223,12978,1777],{"class":1236},[1223,12980,3125],{"class":1244},[1223,12982,12983],{"class":1285}," count",[1223,12985,2281],{"class":1236},[1223,12987,12988],{"class":1285},"value ",[1223,12990,12991],{"class":1236},"*",[1223,12993,8930],{"class":6166},[1223,12995,1804],{"class":1285},[1223,12997,12998,13000,13002],{"class":1225,"line":1325},[1223,12999,1289],{"class":1236},[1223,13001,5899],{"class":1240},[1223,13003,1260],{"class":1236},[1223,13005,13006],{"class":1225,"line":1355},[1223,13007,1740],{"emptyLinePlaceholder":1739},[1223,13009,13010,13012,13014],{"class":1225,"line":1771},[1223,13011,1237],{"class":1236},[1223,13013,2606],{"class":1240},[1223,13015,1260],{"class":1236},[1223,13017,13018,13020,13022,13024,13027,13029,13031],{"class":1225,"line":1783},[1223,13019,1266],{"class":1236},[1223,13021,1330],{"class":1240},[1223,13023,1282],{"class":1236},[1223,13025,13026],{"class":1285},"Count is: {{ count }}",[1223,13028,1289],{"class":1236},[1223,13030,1330],{"class":1240},[1223,13032,1260],{"class":1236},[1223,13034,13035,13037,13039,13041,13044,13046,13048],{"class":1225,"line":1792},[1223,13036,1266],{"class":1236},[1223,13038,1241],{"class":1240},[1223,13040,1282],{"class":1236},[1223,13042,13043],{"class":1285},"Double is: {{ double }}",[1223,13045,1289],{"class":1236},[1223,13047,1241],{"class":1240},[1223,13049,1260],{"class":1236},[1223,13051,13052,13054,13056],{"class":1225,"line":1798},[1223,13053,1289],{"class":1236},[1223,13055,2606],{"class":1240},[1223,13057,1260],{"class":1236},[1143,13059,13060,13061,13064,13065,13072,13073,13078,13079,4363,13084,13091],{},"During that, we also took the chance to refactor ",[2006,13062,12797],{"href":12802,"rel":13063},[2010]," with Orta to have a more efficient and modern structure. It also allows us have ",[2006,13066,13069],{"href":13067,"rel":13068},"https://github.com/twoslashes/twoslash/tree/main/packages/twoslash-vue",[2010],[1220,13070,13071],{},"twoslash-vue"," that provides the ",[2006,13074,13077],{"href":13075,"rel":13076},"https://vuejs.org/guide/scaling-up/sfc.html",[2010],"Vue SFC"," support as you are playing above. It's powered by ",[2006,13080,13083],{"href":13081,"rel":13082},"https://github.com/volarjs/volar.js",[2010],"Volar.js",[2006,13085,13088],{"href":13086,"rel":13087},"https://github.com/vuejs/language-tools",[2010],[1220,13089,13090],{},"vuejs/language-tools",". With Volar growing to be framework agnostic and frameworks to work together, we are looking forward to see such integrations to expand to more syntaxes like Astro and Svelte components files in the future.",[1147,13093,13095],{"id":13094},"integrations","Integrations",[1143,13097,13098],{},"If you want to give Shiki a try in your own website, here you can find some integrations that we have made:",[1852,13100,13101,13140,13164],{},[1855,13102,13103,13108],{},[2006,13104,13107],{"href":13105,"rel":13106},"https://shiki.style/packages/nuxt",[2010],"Nuxt",[1852,13109,13110,13129],{},[1855,13111,13112,13113,13116,13117,13122,13123,13128],{},"If using ",[2006,13114,4387],{"href":4385,"rel":13115},[2010],", Shiki is ",[2006,13118,13121],{"href":13119,"rel":13120},"https://content.nuxt.com/get-started/configuration#highlight",[2010],"build-in",". For Twoslash, you can add ",[2006,13124,13126],{"href":12905,"rel":13125},[2010],[1220,13127,12909],{}," on top.",[1855,13130,13131,13132,13139],{},"If not, you can use ",[2006,13133,13136],{"href":13134,"rel":13135},"https://github.com/pi0/nuxt-shiki",[2010],[1220,13137,13138],{},"nuxt-shiki"," to use Shiki as Vue component or composibles.",[1855,13141,13142,13146],{},[2006,13143,12730],{"href":13144,"rel":13145},"https://shiki.style/packages/vitepress",[2010],[1852,13147,13148],{},[1855,13149,13150,13151,13156,13157,2281],{},"Shiki is ",[2006,13152,13155],{"href":13153,"rel":13154},"https://vitepress.dev/guide/markdown#syntax-highlighting-in-code-blocks",[2010],"built-in",". For Twoslash, you can use ",[2006,13158,13161],{"href":13159,"rel":13160},"https://shiki.style/packages/vitepress#twoslash",[2010],[1220,13162,13163],{},"vitepress-twoslash",[1855,13165,13166,13167],{},"Low-level integrations - Shiki provides official integrations for markdown compilers:\n",[1852,13168,13169,13185],{},[1855,13170,13171,13178,13179],{},[2006,13172,13175],{"href":13173,"rel":13174},"https://shiki.style/packages/markdown-it",[2010],[1220,13176,13177],{},"markdown-it"," - Plugin for ",[2006,13180,13183],{"href":13181,"rel":13182},"https://github.com/markdown-it/markdown-it",[2010],[1220,13184,13177],{},[1855,13186,13187,13178,13194],{},[2006,13188,13191],{"href":13189,"rel":13190},"https://shiki.style/packages/rehype",[2010],[1220,13192,13193],{},"rehype",[2006,13195,13198],{"href":13196,"rel":13197},"https://github.com/rehypejs/rehype",[2010],[1220,13199,13193],{},[1143,13201,13202,13203],{},"Check out more integrations on ",[2006,13204,13206],{"href":12790,"rel":13205},[2010],"Shiki's Documentation",[1147,13208,13210],{"id":13209},"conclusions","Conclusions",[1143,13212,13213,13216,13217,5062,13220,5062,13223,13226],{},[1159,13214,13215],{},"Our mission at Nuxt is not only to make a better framework for developers, but also to make the entire frontend and web ecosystem a better place."," We are keeping pushing the boundaries and endorse the modern web standards and best practices. We hope you enjoy the new ",[2006,13218,11635],{"href":11633,"rel":13219},[2010],[2006,13221,12718],{"href":12698,"rel":13222},[2010],[2006,13224,12797],{"href":12802,"rel":13225},[2010]," and many other tools we made in the process of making Nuxt and the web better.",[2160,13228,13229],{},"html pre.shiki code .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}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 .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .ssYd4, html code.shiki .ssYd4{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .svXlt, html code.shiki .svXlt{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sV9sa, html code.shiki .sV9sa{--shiki-light:#F76D47;--shiki-default:#F76D47;--shiki-dark:#F78C6C}",{"title":1218,"searchDepth":1233,"depth":1233,"links":13231},[13232,13233,13234,13235,13236,13237],{"id":12310,"depth":1233,"text":12311},{"id":12540,"depth":1233,"text":12541},{"id":12739,"depth":1233,"text":12740},{"id":12796,"depth":1233,"text":12797},{"id":13094,"depth":1233,"text":13095},{"id":13209,"depth":1233,"text":13210},"2024-03-11T00:00:00.000Z","Shiki v1.0 came with many improvements and features - see how Nuxt drives the evolution of Shiki!","/assets/blog/shiki-cover.png",{},{"title":1056,"description":13239},"SwdrfdfBW2",{"id":13245,"title":13246,"authors":13247,"body":13250,"category":2176,"date":14251,"description":14252,"draft":108,"extension":1954,"image":14253,"meta":14254,"navigation":108,"path":14255,"seo":14256,"stem":14257,"tags":6,"__hash__":14258},"blog/blog/20.v3-10.md","Nuxt 3.10",[13248],{"name":2190,"avatar":13249,"to":2193},{"src":2192},{"type":1140,"value":13251,"toc":14236},[13252,13255,13263,13271,13289,13331,13343,13346,13350,13363,13609,13616,13637,13640,13647,13656,13663,13705,13708,13799,13806,13810,13827,13833,13835,13839,13842,13885,13889,13899,13902,13972,13975,14031,14047,14051,14062,14106,14114,14118,14130,14146,14149,14152,14196,14198,14200,14215,14217,14219,14227,14229,14233],[1143,13253,13254],{},"v3.10 comes quite close on the heels of v3.9, but it's packed with features and fixes. Here are a few highlights.",[1155,13256,13258,13259,13262],{"id":13257},"experimental-shared-asyncdata-when-prerendering","✨ Experimental shared ",[1220,13260,13261],{},"asyncData"," when prerendering",[1143,13264,13265,13266,3681],{},"When prerendering routes, we can end up refetching the same data over and over again. In Nuxt 2 it was possible to create a 'payload' which could be fetched once and then accessed in every page (and this is of course possible to do manually in Nuxt 3 - see ",[2006,13267,13270],{"href":13268,"rel":13269},"https://roe.dev/blog/shared-data-nuxt-generate",[2010],"this article",[1143,13272,13273,13274,13279,13280,4363,13284,13288],{},"With ",[2006,13275,13278],{"href":13276,"rel":13277},"https://github.com/nuxt/nuxt/pull/24894",[2010],"#24894",", we are now able to do this automatically for you when prerendering your site. Your ",[2006,13281,13282],{"href":433},[1220,13283,432],{},[2006,13285,13286],{"href":445},[1220,13287,444],{}," calls will be deduplicated and cached between renders of your site.",[1213,13290,13292],{"className":1669,"code":13291,"filename":260,"language":1672,"meta":1218,"style":1218},"export defineNuxtConfig({\n  experimental: {\n    sharedPrerenderData: true\n  }\n})\n",[1220,13293,13294,13304,13312,13321,13325],{"__ignoreMap":1218},[1223,13295,13296,13298,13300,13302],{"class":1225,"line":1226},[1223,13297,1745],{"class":1244},[1223,13299,2820],{"class":1751},[1223,13301,1754],{"class":1285},[1223,13303,1757],{"class":1236},[1223,13305,13306,13308,13310],{"class":1225,"line":1233},[1223,13307,3074],{"class":1240},[1223,13309,1765],{"class":1236},[1223,13311,1891],{"class":1236},[1223,13313,13314,13317,13319],{"class":1225,"line":1263},[1223,13315,13316],{"class":1240},"    sharedPrerenderData",[1223,13318,1765],{"class":1236},[1223,13320,3088],{"class":2928},[1223,13322,13323],{"class":1225,"line":1296},[1223,13324,1990],{"class":1236},[1223,13326,13327,13329],{"class":1225,"line":1325},[1223,13328,1801],{"class":1236},[1223,13330,1804],{"class":1285},[13332,13333,13334],"important",{},[1143,13335,13336,13337,13339,13340,13342],{},"It is particularly important to make sure that any unique key of your data is always resolvable to the same data. For example, if you are using ",[1220,13338,432],{}," to fetch data related to a particular page, you should provide a key that uniquely matches that data. (",[1220,13341,444],{}," should do this automatically.)",[3611,13344],{"to":13345},"/docs/guide/going-further/experimental-features#sharedprerenderdata",[1155,13347,13349],{"id":13348},"ssr-safe-accessible-unique-id-creation","🆔 SSR-safe accessible unique ID creation",[1143,13351,13352,13353,13356,13357,13362],{},"We now ship a ",[1220,13354,13355],{},"useId"," composable for generating SSR-safe unique IDs (",[2006,13358,13361],{"href":13359,"rel":13360},"https://github.com/nuxt/nuxt/pull/23368",[2010],"#23368","). This allows creating more accessible interfaces in your app. For example:",[1213,13364,13367],{"className":2595,"code":13365,"filename":13366,"language":2597,"meta":1218,"style":1218},"\u003Cscript setup>\nconst emailId = useId()\nconst passwordId = useId()\n\u003C/script>\n\n\u003Ctemplate>\n  \u003Cform>\n    \u003Clabel :for=\"emailId\">Email\u003C/label>\n    \u003Cinput\n      :id=\"emailId\"\n      name=\"email\"\n      type=\"email\"\n    >\n    \u003Clabel :for=\"passwordId\">Password\u003C/label>\n    \u003Cinput\n      :id=\"passwordId\"\n      name=\"password\"\n      type=\"password\"\n    >\n  \u003C/form>\n\u003C/template>\n","components/MyForm.vue",[1220,13368,13369,13379,13393,13406,13414,13418,13426,13435,13465,13472,13486,13500,13513,13518,13546,13552,13564,13577,13589,13593,13601],{"__ignoreMap":1218},[1223,13370,13371,13373,13375,13377],{"class":1225,"line":1226},[1223,13372,1237],{"class":1236},[1223,13374,5899],{"class":1240},[1223,13376,5902],{"class":1244},[1223,13378,1260],{"class":1236},[1223,13380,13381,13383,13386,13388,13391],{"class":1225,"line":1233},[1223,13382,3214],{"class":1244},[1223,13384,13385],{"class":1285}," emailId ",[1223,13387,1248],{"class":1236},[1223,13389,13390],{"class":1751}," useId",[1223,13392,1789],{"class":1285},[1223,13394,13395,13397,13400,13402,13404],{"class":1225,"line":1263},[1223,13396,3214],{"class":1244},[1223,13398,13399],{"class":1285}," passwordId ",[1223,13401,1248],{"class":1236},[1223,13403,13390],{"class":1751},[1223,13405,1789],{"class":1285},[1223,13407,13408,13410,13412],{"class":1225,"line":1296},[1223,13409,1289],{"class":1236},[1223,13411,5899],{"class":1240},[1223,13413,1260],{"class":1236},[1223,13415,13416],{"class":1225,"line":1325},[1223,13417,1740],{"emptyLinePlaceholder":1739},[1223,13419,13420,13422,13424],{"class":1225,"line":1355},[1223,13421,1237],{"class":1236},[1223,13423,2606],{"class":1240},[1223,13425,1260],{"class":1236},[1223,13427,13428,13430,13433],{"class":1225,"line":1771},[1223,13429,1266],{"class":1236},[1223,13431,13432],{"class":1240},"form",[1223,13434,1260],{"class":1236},[1223,13436,13437,13439,13442,13445,13447,13449,13452,13454,13456,13459,13461,13463],{"class":1225,"line":1783},[1223,13438,5138],{"class":1236},[1223,13440,13441],{"class":1240},"label",[1223,13443,13444],{"class":1244}," :for",[1223,13446,1248],{"class":1236},[1223,13448,1251],{"class":1236},[1223,13450,13451],{"class":1254},"emailId",[1223,13453,1251],{"class":1236},[1223,13455,1282],{"class":1236},[1223,13457,13458],{"class":1285},"Email",[1223,13460,1289],{"class":1236},[1223,13462,13441],{"class":1240},[1223,13464,1260],{"class":1236},[1223,13466,13467,13469],{"class":1225,"line":1792},[1223,13468,5138],{"class":1236},[1223,13470,13471],{"class":1240},"input\n",[1223,13473,13474,13477,13479,13481,13483],{"class":1225,"line":1798},[1223,13475,13476],{"class":1244},"      :id",[1223,13478,1248],{"class":1236},[1223,13480,1251],{"class":1236},[1223,13482,13451],{"class":1254},[1223,13484,13485],{"class":1236},"\"\n",[1223,13487,13488,13491,13493,13495,13498],{"class":1225,"line":1975},[1223,13489,13490],{"class":1244},"      name",[1223,13492,1248],{"class":1236},[1223,13494,1251],{"class":1236},[1223,13496,13497],{"class":1254},"email",[1223,13499,13485],{"class":1236},[1223,13501,13502,13505,13507,13509,13511],{"class":1225,"line":1981},[1223,13503,13504],{"class":1244},"      type",[1223,13506,1248],{"class":1236},[1223,13508,1251],{"class":1236},[1223,13510,13497],{"class":1254},[1223,13512,13485],{"class":1236},[1223,13514,13515],{"class":1225,"line":1987},[1223,13516,13517],{"class":1236},"    >\n",[1223,13519,13520,13522,13524,13526,13528,13530,13533,13535,13537,13540,13542,13544],{"class":1225,"line":1993},[1223,13521,5138],{"class":1236},[1223,13523,13441],{"class":1240},[1223,13525,13444],{"class":1244},[1223,13527,1248],{"class":1236},[1223,13529,1251],{"class":1236},[1223,13531,13532],{"class":1254},"passwordId",[1223,13534,1251],{"class":1236},[1223,13536,1282],{"class":1236},[1223,13538,13539],{"class":1285},"Password",[1223,13541,1289],{"class":1236},[1223,13543,13441],{"class":1240},[1223,13545,1260],{"class":1236},[1223,13547,13548,13550],{"class":1225,"line":2720},[1223,13549,5138],{"class":1236},[1223,13551,13471],{"class":1240},[1223,13553,13554,13556,13558,13560,13562],{"class":1225,"line":2742},[1223,13555,13476],{"class":1244},[1223,13557,1248],{"class":1236},[1223,13559,1251],{"class":1236},[1223,13561,13532],{"class":1254},[1223,13563,13485],{"class":1236},[1223,13565,13566,13568,13570,13572,13575],{"class":1225,"line":6685},[1223,13567,13490],{"class":1244},[1223,13569,1248],{"class":1236},[1223,13571,1251],{"class":1236},[1223,13573,13574],{"class":1254},"password",[1223,13576,13485],{"class":1236},[1223,13578,13579,13581,13583,13585,13587],{"class":1225,"line":6695},[1223,13580,13504],{"class":1244},[1223,13582,1248],{"class":1236},[1223,13584,1251],{"class":1236},[1223,13586,13574],{"class":1254},[1223,13588,13485],{"class":1236},[1223,13590,13591],{"class":1225,"line":6714},[1223,13592,13517],{"class":1236},[1223,13594,13595,13597,13599],{"class":1225,"line":6719},[1223,13596,5211],{"class":1236},[1223,13598,13432],{"class":1240},[1223,13600,1260],{"class":1236},[1223,13602,13603,13605,13607],{"class":1225,"line":6724},[1223,13604,1289],{"class":1236},[1223,13606,2606],{"class":1240},[1223,13608,1260],{"class":1236},[1155,13610,13612,13613],{"id":13611},"️-extending-approuteroptions","✍️ Extending ",[1220,13614,13615],{},"app/router.options",[1143,13617,13618,13619,13622,13623,13628,13629,13632,13633,13636],{},"It's now possible for module authors to inject their own ",[1220,13620,13621],{},"router.options"," files (",[2006,13624,13627],{"href":13625,"rel":13626},"https://github.com/nuxt/nuxt/pull/24922",[2010],"#24922","). The new ",[1220,13630,13631],{},"pages:routerOptions"," hook allows module authors to do things like add custom ",[1220,13634,13635],{},"scrollBehavior"," or add runtime augmenting of routes.",[3611,13638],{"to":13639},"/docs/guide/going-further/custom-routing#router-options",[1155,13641,13643,13646],{"id":13642},"client-side-nodejs-support",[9878,13644],{"name":13645},"i-vscode-icons-file-type-node"," Client-side Node.js support",[1143,13648,13649,13650,13655],{},"We now support (experimentally) polyfilling key Node.js built-ins (",[2006,13651,13654],{"href":13652,"rel":13653},"https://github.com/nuxt/nuxt/pull/25028",[2010],"#25028","), just as we already do via Nitro on the server when deploying to non-Node environments.",[1143,13657,13658,13659,13662],{},"That means that, within your client-side code, you can import directly from Node built-ins (",[1220,13660,13661],{},"node:"," and node imports are supported). However, nothing is globally injected for you, to avoid increasing your bundle size unnecessarily. You can either import them where needed.",[1213,13664,13667],{"className":1669,"code":13665,"filename":13666,"language":1672,"meta":1218,"style":1218},"import { Buffer } from 'node:buffer'\nimport process from 'node:process'\n","some-file.ts",[1220,13668,13669,13689],{"__ignoreMap":1218},[1223,13670,13671,13673,13675,13678,13680,13682,13684,13687],{"class":1225,"line":1226},[1223,13672,1680],{"class":1679},[1223,13674,1683],{"class":1236},[1223,13676,13677],{"class":1285}," Buffer",[1223,13679,1689],{"class":1236},[1223,13681,1692],{"class":1679},[1223,13683,1695],{"class":1236},[1223,13685,13686],{"class":1254},"node:buffer",[1223,13688,1701],{"class":1236},[1223,13690,13691,13693,13696,13698,13700,13703],{"class":1225,"line":1233},[1223,13692,1680],{"class":1679},[1223,13694,13695],{"class":1285}," process ",[1223,13697,1711],{"class":1679},[1223,13699,1695],{"class":1236},[1223,13701,13702],{"class":1254},"node:process",[1223,13704,1701],{"class":1236},[1143,13706,13707],{},"Or provide your own polyfill, for example, inside a Nuxt plugin.",[1213,13709,13712],{"className":1669,"code":13710,"filename":13711,"language":1672,"meta":1218,"style":1218},"import { Buffer } from 'node:buffer'\nimport process from 'node:process'\n\nglobalThis.Buffer = Buffer\nglobalThis.process = process\n\nexport default defineNuxtPlugin({})\n","plugins/node.client.ts",[1220,13713,13714,13732,13746,13750,13765,13779,13783],{"__ignoreMap":1218},[1223,13715,13716,13718,13720,13722,13724,13726,13728,13730],{"class":1225,"line":1226},[1223,13717,1680],{"class":1679},[1223,13719,1683],{"class":1236},[1223,13721,13677],{"class":1285},[1223,13723,1689],{"class":1236},[1223,13725,1692],{"class":1679},[1223,13727,1695],{"class":1236},[1223,13729,13686],{"class":1254},[1223,13731,1701],{"class":1236},[1223,13733,13734,13736,13738,13740,13742,13744],{"class":1225,"line":1233},[1223,13735,1680],{"class":1679},[1223,13737,13695],{"class":1285},[1223,13739,1711],{"class":1679},[1223,13741,1695],{"class":1236},[1223,13743,13702],{"class":1254},[1223,13745,1701],{"class":1236},[1223,13747,13748],{"class":1225,"line":1263},[1223,13749,1740],{"emptyLinePlaceholder":1739},[1223,13751,13752,13755,13757,13760,13762],{"class":1225,"line":1296},[1223,13753,13754],{"class":1285},"globalThis",[1223,13756,2281],{"class":1236},[1223,13758,13759],{"class":1285},"Buffer ",[1223,13761,1248],{"class":1236},[1223,13763,13764],{"class":1285}," Buffer\n",[1223,13766,13767,13769,13771,13774,13776],{"class":1225,"line":1325},[1223,13768,13754],{"class":1285},[1223,13770,2281],{"class":1236},[1223,13772,13773],{"class":1285},"process ",[1223,13775,1248],{"class":1236},[1223,13777,13778],{"class":1285}," process\n",[1223,13780,13781],{"class":1225,"line":1355},[1223,13782,1740],{"emptyLinePlaceholder":1739},[1223,13784,13785,13787,13789,13792,13794,13797],{"class":1225,"line":1771},[1223,13786,1745],{"class":1679},[1223,13788,1748],{"class":1679},[1223,13790,13791],{"class":1751}," defineNuxtPlugin",[1223,13793,1754],{"class":1285},[1223,13795,13796],{"class":1236},"{}",[1223,13798,1804],{"class":1285},[1143,13800,13801,13802,13805],{},"This should make life easier for users who are working with libraries without proper browser support. However, because of the risk in increasing your bundle unnecessarily, we would strongly urge users ",[1159,13803,13804],{},"to choose other alternatives"," if at all possible.",[1155,13807,13809],{"id":13808},"better-cookie-reactivity","🍪 Better cookie reactivity",[1143,13811,13812,13813,13818,13819,13821,13822,3681],{},"We now allow you to opt-in to using the ",[2006,13814,13817],{"href":13815,"rel":13816},"https://developer.mozilla.org/en-US/docs/Web/API/CookieStore",[2010],"CookieStore",". If browser support is present, this will then be used instead of a BroadcastChannel to update ",[1220,13820,436],{}," values reactively when the cookies are updated (",[2006,13823,13826],{"href":13824,"rel":13825},"https://github.com/nuxt/nuxt/pull/25198",[2010],"#25198",[1143,13828,13829,13830,13832],{},"This also comes paired with a new composable, ",[1220,13831,627],{}," which allows manually refreshing cookie values, such as after performing a request.",[3611,13834],{"to":628},[1155,13836,13838],{"id":13837},"detecting-anti-patterns","🏥 Detecting anti-patterns",[1143,13840,13841],{},"In this release, we've also shipped a range of features to detect potential bugs and performance problems.",[1852,13843,13844,13856,13865],{},[1855,13845,13846,13847,13850,13851,3681],{},"We now will throw an error if ",[1220,13848,13849],{},"setInterval"," is used on server (",[2006,13852,13855],{"href":13853,"rel":13854},"https://github.com/nuxt/nuxt/pull/25259",[2010],"#25259",[1855,13857,13858,13859,13864],{},"We warn (in development only) if data fetch composables are used wrongly (",[2006,13860,13863],{"href":13861,"rel":13862},"https://github.com/nuxt/nuxt/pull/25071",[2010],"#25071","), such as outside of a plugin or setup context.",[1855,13866,13867,13868,13871,13872,13874,13875,13880,13881,13884],{},"We warn (in development only) if you are not using ",[1220,13869,13870],{},"\u003CNuxtPage />"," but have the ",[1220,13873,5507],{}," integration enabled (",[2006,13876,13879],{"href":13877,"rel":13878},"https://github.com/nuxt/nuxt/pull/25490",[2010],"#25490","). (",[1220,13882,13883],{},"\u003CRouterView />"," should not be used on its own.)",[1155,13886,13888],{"id":13887},"granular-view-transitions-support","🧂 Granular view transitions support",[1143,13890,13891,13892,3114,13894,3681],{},"It's now possible to control view transitions support on a per-page basis, using ",[1220,13893,587],{},[2006,13895,13898],{"href":13896,"rel":13897},"https://github.com/nuxt/nuxt/pull/25264",[2010],"#25264",[1143,13900,13901],{},"You need to have experimental view transitions support enabled first:",[1213,13903,13905],{"className":1669,"code":13904,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  experimental: {\n    viewTransition: true\n  },\n  app: {\n    // you can disable them globally if necessary (they are enabled by default)\n    viewTransition: false\n  }\n})\n",[1220,13906,13907,13919,13927,13936,13940,13949,13954,13962,13966],{"__ignoreMap":1218},[1223,13908,13909,13911,13913,13915,13917],{"class":1225,"line":1226},[1223,13910,1745],{"class":1679},[1223,13912,1748],{"class":1679},[1223,13914,2820],{"class":1751},[1223,13916,1754],{"class":1285},[1223,13918,1757],{"class":1236},[1223,13920,13921,13923,13925],{"class":1225,"line":1233},[1223,13922,3074],{"class":1240},[1223,13924,1765],{"class":1236},[1223,13926,1891],{"class":1236},[1223,13928,13929,13932,13934],{"class":1225,"line":1263},[1223,13930,13931],{"class":1240},"    viewTransition",[1223,13933,1765],{"class":1236},[1223,13935,3088],{"class":2928},[1223,13937,13938],{"class":1225,"line":1296},[1223,13939,3312],{"class":1236},[1223,13941,13942,13945,13947],{"class":1225,"line":1325},[1223,13943,13944],{"class":1240},"  app",[1223,13946,1765],{"class":1236},[1223,13948,1891],{"class":1236},[1223,13950,13951],{"class":1225,"line":1355},[1223,13952,13953],{"class":1229},"    // you can disable them globally if necessary (they are enabled by default)\n",[1223,13955,13956,13958,13960],{"class":1225,"line":1771},[1223,13957,13931],{"class":1240},[1223,13959,1765],{"class":1236},[1223,13961,10665],{"class":2928},[1223,13963,13964],{"class":1225,"line":1783},[1223,13965,1990],{"class":1236},[1223,13967,13968,13970],{"class":1225,"line":1792},[1223,13969,1801],{"class":1236},[1223,13971,1804],{"class":1285},[1143,13973,13974],{},"And you can opt in/out granularly:",[1213,13976,13978],{"className":2595,"code":13977,"filename":5115,"language":2597,"meta":1218,"style":1218},"\u003Cscript setup lang=\"ts\">\ndefinePageMeta({\n  viewTransition: false\n})\n\u003C/script>\n",[1220,13979,13980,14000,14008,14017,14023],{"__ignoreMap":1218},[1223,13981,13982,13984,13986,13988,13990,13992,13994,13996,13998],{"class":1225,"line":1226},[1223,13983,1237],{"class":1236},[1223,13985,5899],{"class":1240},[1223,13987,5902],{"class":1244},[1223,13989,6066],{"class":1244},[1223,13991,1248],{"class":1236},[1223,13993,1251],{"class":1236},[1223,13995,1672],{"class":1254},[1223,13997,1251],{"class":1236},[1223,13999,1260],{"class":1236},[1223,14001,14002,14004,14006],{"class":1225,"line":1233},[1223,14003,587],{"class":1751},[1223,14005,1754],{"class":1285},[1223,14007,1757],{"class":1236},[1223,14009,14010,14013,14015],{"class":1225,"line":1263},[1223,14011,14012],{"class":1240},"  viewTransition",[1223,14014,1765],{"class":1236},[1223,14016,10665],{"class":2928},[1223,14018,14019,14021],{"class":1225,"line":1296},[1223,14020,1801],{"class":1236},[1223,14022,1804],{"class":1285},[1223,14024,14025,14027,14029],{"class":1225,"line":1325},[1223,14026,1289],{"class":1236},[1223,14028,5899],{"class":1240},[1223,14030,1260],{"class":1236},[1143,14032,14033,14034,3114,14037,14042,14043,14046],{},"Finally, Nuxt will not apply View Transitions if the user's browser matches ",[1220,14035,14036],{},"prefers-reduced-motion: reduce",[2006,14038,14041],{"href":14039,"rel":14040},"https://github.com/nuxt/nuxt/pull/22292",[2010],"#22292","). You can set ",[1220,14044,14045],{},"viewTransition: 'always'","; it will then be up to you to respect the user's preference.",[1155,14048,14050],{"id":14049},"️-build-time-route-metadata","🏗️ Build-time route metadata",[1143,14052,14053,14054,14056,14057,3681],{},"It's now possible to access routing metadata defined in ",[1220,14055,587],{}," at build-time, allowing modules and hooks to modify and change these values (",[2006,14058,14061],{"href":14059,"rel":14060},"https://github.com/nuxt/nuxt/pull/25210",[2010],"#25210",[1213,14063,14065],{"className":1669,"code":14064,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  experimental: {\n    scanPageMeta: true\n  }\n})\n",[1220,14066,14067,14079,14087,14096,14100],{"__ignoreMap":1218},[1223,14068,14069,14071,14073,14075,14077],{"class":1225,"line":1226},[1223,14070,1745],{"class":1679},[1223,14072,1748],{"class":1679},[1223,14074,2820],{"class":1751},[1223,14076,1754],{"class":1285},[1223,14078,1757],{"class":1236},[1223,14080,14081,14083,14085],{"class":1225,"line":1233},[1223,14082,3074],{"class":1240},[1223,14084,1765],{"class":1236},[1223,14086,1891],{"class":1236},[1223,14088,14089,14092,14094],{"class":1225,"line":1263},[1223,14090,14091],{"class":1240},"    scanPageMeta",[1223,14093,1765],{"class":1236},[1223,14095,3088],{"class":2928},[1223,14097,14098],{"class":1225,"line":1296},[1223,14099,1990],{"class":1236},[1223,14101,14102,14104],{"class":1225,"line":1325},[1223,14103,1801],{"class":1236},[1223,14105,1804],{"class":1285},[1143,14107,14108,14109,14111,14112,2281],{},"Please, experiment with this and let us know how it works for you. We hope to improve performance and enable this by default in a future release so modules like ",[1220,14110,8224],{}," and others can provide a deeper integration with routing options set in ",[1220,14113,587],{},[1155,14115,14117],{"id":14116},"bundler-module-resolution","📦 Bundler module resolution",[1143,14119,13273,14120,14125,14126,14129],{},[2006,14121,14124],{"href":14122,"rel":14123},"https://github.com/nuxt/nuxt/pull/24837",[2010],"#24837",", we are now opting in to the TypeScript ",[1220,14127,14128],{},"bundler"," resolution which should more closely resemble the actual way that we resolve subpath imports for modules in Nuxt projects.",[1143,14131,14132,14133,4363,14138,14143,14144,2281],{},"'Bundler' module resolution is ",[2006,14134,14137],{"href":14135,"rel":14136},"https://github.com/vuejs/tsconfig/blob/mainz/tsconfig.json#L24-L26",[2010],"recommended by Vue",[2006,14139,14142],{"href":14140,"rel":14141},"https://vitejs.dev/guide/performance.html#reduce-resolve-operations",[2010],"by Vite",", but unfortunately there are still many packages that do not have the correct entries in their ",[1220,14145,264],{},[1143,14147,14148],{},"As part of this, we opened 85 PRs across the ecosystem to test switching the default, and identified and fixed some issues.",[1143,14150,14151],{},"If you need to switch off this behaviour, you can do so. However, please consider raising an issue (feel free to tag me in it) in the library or module's repo so it can be resolved at source.",[1213,14153,14155],{"className":1669,"code":14154,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  future: {\n    typescriptBundlerResolution: false\n  }\n})\n",[1220,14156,14157,14169,14177,14186,14190],{"__ignoreMap":1218},[1223,14158,14159,14161,14163,14165,14167],{"class":1225,"line":1226},[1223,14160,1745],{"class":1679},[1223,14162,1748],{"class":1679},[1223,14164,2820],{"class":1751},[1223,14166,1754],{"class":1285},[1223,14168,1757],{"class":1236},[1223,14170,14171,14173,14175],{"class":1225,"line":1233},[1223,14172,7935],{"class":1240},[1223,14174,1765],{"class":1236},[1223,14176,1891],{"class":1236},[1223,14178,14179,14182,14184],{"class":1225,"line":1263},[1223,14180,14181],{"class":1240},"    typescriptBundlerResolution",[1223,14183,1765],{"class":1236},[1223,14185,10665],{"class":2928},[1223,14187,14188],{"class":1225,"line":1296},[1223,14189,1990],{"class":1236},[1223,14191,14192,14194],{"class":1225,"line":1325},[1223,14193,1801],{"class":1236},[1223,14195,1804],{"class":1285},[1147,14197,3580],{"id":3579},[1143,14199,3583],{},[1213,14201,14203],{"className":3586,"code":14202,"language":3588,"meta":1218,"style":1218},"npx nuxi upgrade --force\n",[1220,14204,14205],{"__ignoreMap":1218},[1223,14206,14207,14209,14211,14213],{"class":1225,"line":1226},[1223,14208,2037],{"class":2036},[1223,14210,4554],{"class":1254},[1223,14212,3599],{"class":1254},[1223,14214,4019],{"class":1254},[1143,14216,4022],{},[1147,14218,4938],{"id":3608},[3611,14220,14222],{"to":14221,"color":3613,"icon":3614,"target":3615},"https://github.com/nuxt/nuxt/releases/tag/v3.10.0",[1143,14223,3619,14224,2281],{},[1220,14225,14226],{},"v3.10.0",[1143,14228,11586],{},[1143,14230,14231],{},[1159,14232,4631],{},[2160,14234,14235],{},"html pre.shiki code .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .sagxc, html code.shiki .sagxc{--shiki-light:#FF5370;--shiki-default:#FF5370;--shiki-dark:#FF9CAC}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 .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}html pre.shiki code .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .svXlt, html code.shiki .svXlt{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}",{"title":1218,"searchDepth":1233,"depth":1233,"links":14237},[14238,14240,14241,14243,14244,14245,14246,14247,14248,14249,14250],{"id":13257,"depth":1263,"text":14239},"✨ Experimental shared asyncData when prerendering",{"id":13348,"depth":1263,"text":13349},{"id":13611,"depth":1263,"text":14242},"✍️ Extending app/router.options",{"id":13642,"depth":1263,"text":13646},{"id":13808,"depth":1263,"text":13809},{"id":13837,"depth":1263,"text":13838},{"id":13887,"depth":1263,"text":13888},{"id":14049,"depth":1263,"text":14050},{"id":14116,"depth":1263,"text":14117},{"id":3579,"depth":1233,"text":3580},{"id":3608,"depth":1233,"text":4938},"2024-01-30T00:00:00.000Z","Nuxt 3.10 is out - packed with features and fixes. Here are a few highlights.","/assets/blog/v3.10.png",{},"/blog/v3-10",{"title":13246,"description":14252},"blog/20.v3-10","7gyGehCWpW",{"id":14260,"title":14261,"authors":14262,"body":14265,"category":2176,"date":14941,"description":14942,"draft":108,"extension":1954,"image":14943,"meta":14944,"navigation":108,"path":14945,"seo":14946,"stem":14947,"tags":6,"__hash__":14948},"blog/blog/19.v3-9.md","Nuxt 3.9",[14263],{"name":2190,"avatar":14264,"to":2193},{"src":2192},{"type":1140,"value":14266,"toc":14928},[14267,14270,14273,14277,14280,14289,14293,14305,14311,14401,14405,14408,14463,14469,14499,14502,14506,14509,14583,14597,14673,14677,14695,14709,14715,14718,14730,14845,14852,14854,14858,14875,14884,14888,14891,14893,14895,14909,14911,14919,14921,14925],[1143,14268,14269],{},"A very merry Christmas to you and yours from all Nuxters involved in this release! 🎁🎄",[1143,14271,14272],{},"We have lots of features packed into v3.9 and can't wait for you to try them out.",[1155,14274,14276],{"id":14275},"️-vite-5","⚡️ Vite 5",[1143,14278,14279],{},"This release comes with Vite 5 and Rollup 4 support. Module authors may need to check to ensure that any vite plugins you're creating are compatible with these latest releases.",[1143,14281,14282,14283,14288],{},"This comes with a whole host of great improvements and bug fixes - check out ",[2006,14284,14287],{"href":14285,"rel":14286},"https://vitejs.dev/guide/migration.html#migration-from-v4",[2010],"the Vite changelog"," for more info.",[1155,14290,14292],{"id":14291},"vue-34-ready","✨ Vue 3.4 ready",[1143,14294,14295,14296,14301,14302,14304],{},"This release is tested with the latest Vue 3.4 release candidate, and has the necessary configuration to take advantage of ",[2006,14297,14300],{"href":14298,"rel":14299},"https://blog.vuejs.org/posts/vue-3-4",[2010],"new features in Vue 3.4",", including debugging hydration errors in production (just set ",[1220,14303,3038],{},") in your Nuxt config.",[1143,14306,14307,14308,14310],{},"👉 To take advantage, just update your ",[1220,14309,2597],{}," version once v3.4 is released, or try out the release candidate today:",[1213,14312,14316],{"className":14313,"code":14314,"filename":264,"language":14315,"meta":1218,"style":1218},"language-json shiki shiki-themes material-theme-lighter material-theme-lighter material-theme-palenight","{\n  \"dependencies\": {\n    \"nuxt\": \"3.9.0\",\n    \"vue\": \"3.4.0-rc.1\",\n    \"vue-router\": \"latest\"\n  }\n}\n","json",[1220,14317,14318,14322,14336,14357,14376,14393,14397],{"__ignoreMap":1218},[1223,14319,14320],{"class":1225,"line":1226},[1223,14321,1757],{"class":1236},[1223,14323,14324,14327,14330,14332,14334],{"class":1225,"line":1233},[1223,14325,14326],{"class":1236},"  \"",[1223,14328,14329],{"class":1244},"dependencies",[1223,14331,1251],{"class":1236},[1223,14333,1765],{"class":1236},[1223,14335,1891],{"class":1236},[1223,14337,14338,14341,14343,14345,14347,14350,14353,14355],{"class":1225,"line":1263},[1223,14339,14340],{"class":1236},"    \"",[1223,14342,2367],{"class":2036},[1223,14344,1251],{"class":1236},[1223,14346,1765],{"class":1236},[1223,14348,14349],{"class":1236}," \"",[1223,14351,14352],{"class":1254},"3.9.0",[1223,14354,1251],{"class":1236},[1223,14356,1780],{"class":1236},[1223,14358,14359,14361,14363,14365,14367,14369,14372,14374],{"class":1225,"line":1296},[1223,14360,14340],{"class":1236},[1223,14362,2597],{"class":2036},[1223,14364,1251],{"class":1236},[1223,14366,1765],{"class":1236},[1223,14368,14349],{"class":1236},[1223,14370,14371],{"class":1254},"3.4.0-rc.1",[1223,14373,1251],{"class":1236},[1223,14375,1780],{"class":1236},[1223,14377,14378,14380,14382,14384,14386,14388,14391],{"class":1225,"line":1325},[1223,14379,14340],{"class":1236},[1223,14381,5507],{"class":2036},[1223,14383,1251],{"class":1236},[1223,14385,1765],{"class":1236},[1223,14387,14349],{"class":1236},[1223,14389,14390],{"class":1254},"latest",[1223,14392,13485],{"class":1236},[1223,14394,14395],{"class":1225,"line":1355},[1223,14396,1990],{"class":1236},[1223,14398,14399],{"class":1225,"line":1771},[1223,14400,2407],{"class":1236},[1155,14402,14404],{"id":14403},"️-interactive-server-components","🏝️ Interactive Server Components",[1143,14406,14407],{},"This is a highly-experimental update, but it's now possible to play around with interactive components within Nuxt server components. You'll need to enable this new feature additionally to component islands:",[1213,14409,14411],{"className":1669,"code":14410,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  experimental: {\n    componentIslands: {\n      selectiveClient: true\n    }\n  }\n})\n",[1220,14412,14413,14425,14433,14441,14449,14453,14457],{"__ignoreMap":1218},[1223,14414,14415,14417,14419,14421,14423],{"class":1225,"line":1226},[1223,14416,1745],{"class":1679},[1223,14418,1748],{"class":1679},[1223,14420,2820],{"class":1751},[1223,14422,1754],{"class":1285},[1223,14424,1757],{"class":1236},[1223,14426,14427,14429,14431],{"class":1225,"line":1233},[1223,14428,3074],{"class":1240},[1223,14430,1765],{"class":1236},[1223,14432,1891],{"class":1236},[1223,14434,14435,14437,14439],{"class":1225,"line":1263},[1223,14436,11278],{"class":1240},[1223,14438,1765],{"class":1236},[1223,14440,1891],{"class":1236},[1223,14442,14443,14445,14447],{"class":1225,"line":1296},[1223,14444,11287],{"class":1240},[1223,14446,1765],{"class":1236},[1223,14448,3088],{"class":2928},[1223,14450,14451],{"class":1225,"line":1325},[1223,14452,1984],{"class":1236},[1223,14454,14455],{"class":1225,"line":1355},[1223,14456,1990],{"class":1236},[1223,14458,14459,14461],{"class":1225,"line":1771},[1223,14460,1801],{"class":1236},[1223,14462,1804],{"class":1285},[1143,14464,14465,14466,14468],{},"Now, within a server component, you can specify components to hydrate by using the ",[1220,14467,11242],{}," directive:",[1213,14470,14473],{"className":2595,"code":14471,"filename":14472,"language":2597,"meta":1218,"style":1218},"\u003CNuxtLink :to=\"/\" nuxt-client />\n","components/SomeComponent.server.vue",[1220,14474,14475],{"__ignoreMap":1218},[1223,14476,14477,14479,14481,14484,14487,14489,14492,14495,14497],{"class":1225,"line":1226},[1223,14478,1237],{"class":1236},[1223,14480,5104],{"class":1240},[1223,14482,14483],{"class":1236}," :",[1223,14485,14486],{"class":1244},"to",[1223,14488,1248],{"class":1236},[1223,14490,14491],{"class":1236},"\"/",[1223,14493,14494],{"class":1254},"\" nuxt-client ",[1223,14496,5061],{"class":1236},[1223,14498,1260],{"class":1236},[1143,14500,14501],{},"We're pretty excited about this one - so do let us know how you're using it! 🙏",[1155,14503,14505],{"id":14504},"automatic-server-optimisations","🔥 Automatic Server Optimisations",[1143,14507,14508],{},"We now use Vite's new AST-aware 'define' to perform more accurate replacements on server-side code, meaning code like this will no longer throw an error:",[1213,14510,14512],{"className":2595,"code":14511,"filename":248,"language":2597,"meta":1218,"style":1218},"\u003Cscript setup lang=\"ts\">\nif (document) {\n  console.log(document.querySelector('div'))\n}\n\u003C/script>\n",[1220,14513,14514,14534,14543,14571,14575],{"__ignoreMap":1218},[1223,14515,14516,14518,14520,14522,14524,14526,14528,14530,14532],{"class":1225,"line":1226},[1223,14517,1237],{"class":1236},[1223,14519,5899],{"class":1240},[1223,14521,5902],{"class":1244},[1223,14523,6066],{"class":1244},[1223,14525,1248],{"class":1236},[1223,14527,1251],{"class":1236},[1223,14529,1672],{"class":1254},[1223,14531,1251],{"class":1236},[1223,14533,1260],{"class":1236},[1223,14535,14536,14538,14541],{"class":1225,"line":1233},[1223,14537,5978],{"class":1679},[1223,14539,14540],{"class":1285}," (document) ",[1223,14542,1757],{"class":1236},[1223,14544,14545,14547,14549,14551,14553,14556,14558,14561,14563,14565,14567,14569],{"class":1225,"line":1263},[1223,14546,10528],{"class":1285},[1223,14548,2281],{"class":1236},[1223,14550,6764],{"class":1751},[1223,14552,1754],{"class":1240},[1223,14554,14555],{"class":1285},"document",[1223,14557,2281],{"class":1236},[1223,14559,14560],{"class":1751},"querySelector",[1223,14562,1754],{"class":1240},[1223,14564,1957],{"class":1236},[1223,14566,1241],{"class":1254},[1223,14568,1957],{"class":1236},[1223,14570,12444],{"class":1240},[1223,14572,14573],{"class":1225,"line":1296},[1223,14574,2407],{"class":1236},[1223,14576,14577,14579,14581],{"class":1225,"line":1325},[1223,14578,1289],{"class":1236},[1223,14580,5899],{"class":1240},[1223,14582,1260],{"class":1236},[1143,14584,14585,14586,14588,14589,14592,14593,14596],{},"This hasn't been possible until now because we haven't wanted to run the risk of accidentally replacing normal words like ",[1220,14587,14555],{}," within non-JS parts of your apps. But Vite's new ",[1220,14590,14591],{},"define"," functionality is powered by ",[1220,14594,14595],{},"esbuild"," and is syntax-aware, so we feel confident in enabling this functionality. Nevertheless, you can opt out if you need to:",[1213,14598,14600],{"className":1669,"code":14599,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  hooks: {\n    'vite:extendConfig' (config) {\n      delete config.define!.document\n    }\n  }\n})\n",[1220,14601,14602,14614,14623,14641,14659,14663,14667],{"__ignoreMap":1218},[1223,14603,14604,14606,14608,14610,14612],{"class":1225,"line":1226},[1223,14605,1745],{"class":1679},[1223,14607,1748],{"class":1679},[1223,14609,2820],{"class":1751},[1223,14611,1754],{"class":1285},[1223,14613,1757],{"class":1236},[1223,14615,14616,14619,14621],{"class":1225,"line":1233},[1223,14617,14618],{"class":1240},"  hooks",[1223,14620,1765],{"class":1236},[1223,14622,1891],{"class":1236},[1223,14624,14625,14627,14630,14632,14634,14637,14639],{"class":1225,"line":1263},[1223,14626,9188],{"class":1236},[1223,14628,14629],{"class":1254},"vite:extendConfig",[1223,14631,1957],{"class":1236},[1223,14633,3114],{"class":1236},[1223,14635,14636],{"class":2329},"config",[1223,14638,2541],{"class":1236},[1223,14640,1891],{"class":1236},[1223,14642,14643,14646,14649,14651,14653,14656],{"class":1225,"line":1296},[1223,14644,14645],{"class":1236},"      delete",[1223,14647,14648],{"class":1285}," config",[1223,14650,2281],{"class":1236},[1223,14652,14591],{"class":1285},[1223,14654,14655],{"class":1236},"!.",[1223,14657,14658],{"class":1285},"document\n",[1223,14660,14661],{"class":1225,"line":1325},[1223,14662,1984],{"class":1236},[1223,14664,14665],{"class":1225,"line":1355},[1223,14666,1990],{"class":1236},[1223,14668,14669,14671],{"class":1225,"line":1771},[1223,14670,1801],{"class":1236},[1223,14672,1804],{"class":1285},[1155,14674,14676],{"id":14675},"granular-loading-api","🚦 Granular Loading API",[1143,14678,14679,14680,14684,14685,14687,14688,4363,14691,14694],{},"We now have a new hook-based system for ",[2006,14681,14682],{"href":398},[1220,14683,397],{},", including a ",[1220,14686,468],{}," composable that lets you control/stop/start the loading state. You can also hook into ",[1220,14689,14690],{},"page:loading:start",[1220,14692,14693],{},"page:loading:end"," if you prefer.",[7733,14696,14697],{},[1143,14698,14699,14700,14703,14704,3681],{},"You can read more ",[2006,14701,14702],{"href":469},"in the docs"," and in the original PR (",[2006,14705,14708],{"href":14706,"rel":14707},"https://github.com/nuxt/nuxt/pull/24010",[2010],"#24010",[1155,14710,14712,14713],{"id":14711},"run-single-events-in-callonce","🏁 Run single events in ",[1220,14714,559],{},[1143,14716,14717],{},"Sometimes you only want to run code once, no matter how many times you load a page - and you don't want to run it again on the client if it ran on the server.",[1143,14719,14720,14721,3114,14725,3681],{},"For this, we have a new utility: ",[2006,14722,14723],{"href":560},[1220,14724,559],{},[2006,14726,14729],{"href":14727,"rel":14728},"https://github.com/nuxt/nuxt/pull/24787",[2010],"#24787",[1213,14731,14733],{"className":2595,"code":14732,"filename":248,"language":2597,"meta":1218,"style":1218},"\u003Cscript setup>\nconst websiteConfig = useState('config')\n\nawait callOnce(async () => {\n  console.log('This will only be logged once')\n  websiteConfig.value = await $fetch('https://my-cms.com/api/website-config')\n})\n\u003C/script>\n",[1220,14734,14735,14745,14766,14770,14786,14805,14831,14837],{"__ignoreMap":1218},[1223,14736,14737,14739,14741,14743],{"class":1225,"line":1226},[1223,14738,1237],{"class":1236},[1223,14740,5899],{"class":1240},[1223,14742,5902],{"class":1244},[1223,14744,1260],{"class":1236},[1223,14746,14747,14749,14752,14754,14756,14758,14760,14762,14764],{"class":1225,"line":1233},[1223,14748,3214],{"class":1244},[1223,14750,14751],{"class":1285}," websiteConfig ",[1223,14753,1248],{"class":1236},[1223,14755,12942],{"class":1751},[1223,14757,1754],{"class":1285},[1223,14759,1957],{"class":1236},[1223,14761,14636],{"class":1254},[1223,14763,1957],{"class":1236},[1223,14765,1804],{"class":1285},[1223,14767,14768],{"class":1225,"line":1263},[1223,14769,1740],{"emptyLinePlaceholder":1739},[1223,14771,14772,14774,14776,14778,14780,14782,14784],{"class":1225,"line":1296},[1223,14773,3773],{"class":1679},[1223,14775,3776],{"class":1751},[1223,14777,1754],{"class":1285},[1223,14779,6380],{"class":1244},[1223,14781,3122],{"class":1236},[1223,14783,3125],{"class":1244},[1223,14785,1891],{"class":1236},[1223,14787,14788,14790,14792,14794,14796,14798,14801,14803],{"class":1225,"line":1325},[1223,14789,10528],{"class":1285},[1223,14791,2281],{"class":1236},[1223,14793,6764],{"class":1751},[1223,14795,1754],{"class":1240},[1223,14797,1957],{"class":1236},[1223,14799,14800],{"class":1254},"This will only be logged once",[1223,14802,1957],{"class":1236},[1223,14804,1804],{"class":1240},[1223,14806,14807,14810,14812,14814,14816,14818,14820,14822,14824,14827,14829],{"class":1225,"line":1355},[1223,14808,14809],{"class":1285},"  websiteConfig",[1223,14811,2281],{"class":1236},[1223,14813,3790],{"class":1285},[1223,14815,2339],{"class":1236},[1223,14817,10512],{"class":1679},[1223,14819,10550],{"class":1751},[1223,14821,1754],{"class":1240},[1223,14823,1957],{"class":1236},[1223,14825,14826],{"class":1254},"https://my-cms.com/api/website-config",[1223,14828,1957],{"class":1236},[1223,14830,1804],{"class":1240},[1223,14832,14833,14835],{"class":1225,"line":1771},[1223,14834,1801],{"class":1236},[1223,14836,1804],{"class":1285},[1223,14838,14839,14841,14843],{"class":1225,"line":1783},[1223,14840,1289],{"class":1236},[1223,14842,5899],{"class":1240},[1223,14844,1260],{"class":1236},[1143,14846,14847,14848,14851],{},"Note that this utility is context-aware so it ",[3746,14849,14850],{},"must"," be called in component setup function or Nuxt plugin, as with other Nuxt composables.",[3611,14853],{"to":560},[1155,14855,14857],{"id":14856},"error-types","🚨 Error Types",[1143,14859,14860,14861,4363,14863,14865,14866,14869,14870,8602,14872,14874],{},"For a while now, errors returned by ",[1220,14862,432],{},[1220,14864,444],{}," have been typed pretty generically as ",[1220,14867,14868],{},"Error",". We've significantly improved the type possibilities for them to make them more accurate in terms of what you'll actually receive. (We normalise errors with the ",[1220,14871,1155],{},[1220,14873,575],{}," utility under the hood, so they can be serialised from server to client, for example.)",[1143,14876,14877,14878,14883],{},"We've tried to implement the type change in a backwards compatible way, but you might notice that you need to update the generic if you're manually configuring the generics for these composables. See (",[2006,14879,14882],{"href":14880,"rel":14881},"https://github.com/nuxt/nuxt/pull/24396",[2010],"#24396",") for more information, and do let us know if you experience any issues.",[1155,14885,14887],{"id":14886},"schema-performance","🔥 Schema Performance",[1143,14889,14890],{},"We've taken some time in this release to make some minor performance improvements, so you should notice some things are a bit faster. This is an ongoing project and we have ideas for improving initial load time of the Nuxt dev server.",[1147,14892,3580],{"id":3579},[1143,14894,3583],{},[1213,14896,14898],{"className":3586,"code":14897,"language":3588,"meta":1218,"style":1218},"npx nuxi upgrade\n",[1220,14899,14900],{"__ignoreMap":1218},[1223,14901,14902,14904,14906],{"class":1225,"line":1226},[1223,14903,2037],{"class":2036},[1223,14905,4554],{"class":1254},[1223,14907,14908],{"class":1254}," upgrade\n",[1147,14910,4938],{"id":3608},[3611,14912,14914],{"to":14913,"color":3613,"icon":3614},"https://github.com/nuxt/nuxt/releases/tag/v3.9.0",[1143,14915,3619,14916,2281],{},[1220,14917,14918],{},"v3.9.0",[1143,14920,11586],{},[1143,14922,14923],{},[1159,14924,4631],{},[2160,14926,14927],{},"html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}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 .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .sagxc, html code.shiki .sagxc{--shiki-light:#FF5370;--shiki-default:#FF5370;--shiki-dark:#FF9CAC}html pre.shiki code .ssYd4, html code.shiki .ssYd4{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":1218,"searchDepth":1233,"depth":1233,"links":14929},[14930,14931,14932,14933,14934,14935,14937,14938,14939,14940],{"id":14275,"depth":1263,"text":14276},{"id":14291,"depth":1263,"text":14292},{"id":14403,"depth":1263,"text":14404},{"id":14504,"depth":1263,"text":14505},{"id":14675,"depth":1263,"text":14676},{"id":14711,"depth":1263,"text":14936},"🏁 Run single events in callOnce",{"id":14856,"depth":1263,"text":14857},{"id":14886,"depth":1263,"text":14887},{"id":3579,"depth":1233,"text":3580},{"id":3608,"depth":1233,"text":4938},"2023-12-25T00:00:00.000Z","Nuxt 3.9 is out - a Christmas gift from the Nuxt team bringing Vite 5, interactive server components, new composables, a new loading API and more.","/assets/blog/v3.9.png",{},"/blog/v3-9",{"title":14261,"description":14942},"blog/19.v3-9","bezcPDQz9F",{"id":14950,"title":1048,"authors":14951,"body":14954,"category":2176,"date":15610,"description":15611,"draft":108,"extension":1954,"image":15612,"meta":15613,"navigation":1739,"path":1049,"seo":15614,"stem":1050,"tags":6,"__hash__":15615},"blog/blog/18.nuxt-devtools-v1-0.md",[14952],{"name":4066,"avatar":14953,"to":4069,"twitter":4070},{"src":4068},{"type":1140,"value":14955,"toc":15577},[14956,14963,14973,14984,15029,15033,15036,15063,15070,15073,15077,15080,15087,15090,15093,15100,15103,15109,15113,15116,15120,15123,15143,15147,15150,15153,15157,15160,15163,15166,15170,15173,15176,15180,15183,15186,15189,15193,15199,15202,15206,15209,15212,15216,15228,15231,15235,15249,15252,15255,15259,15265,15268,15272,15275,15280,15283,15287,15290,15293,15297,15309,15312,15316,15319,15322,15326,15329,15332,15336,15339,15342,15346,15349,15352,15354,15357,15361,15364,15372,15375,15382,15385,15392,15395,15402,15405,15412,15415,15422,15425,15428,15432,15435,15472,15475,15478,15481,15506,15508,15511,15515,15522,15528,15531,15537,15543,15546,15553,15556,15559,15563,15571,15574],[1143,14957,14958,14959,14962],{},"We are thrilled to announce the release of ",[2006,14960,1048],{"href":9558,"rel":14961},[2010],"! 🎉",[7733,14964,14965],{},[1143,14966,14967,14968,14972],{},"Since this release, Nuxt DevTools is now enabled with ",[2006,14969,14971],{"href":14970},"/blog/v3-8","Nuxt v3.8"," and onwards by default. Generally available to all Nuxt projects!",[1143,14974,14975,14976,14979,14980,14983],{},"You can start playing with it by upgrading to the latest Nuxt, and press ",[1220,14977,14978],{},"Shift + Option + D"," (macOS) or ",[1220,14981,14982],{},"Shift + Alt + D"," (Windows) in your browser to open the DevTools. By default the floating panel is hidden to reduce the distraction. You can enable it inside Nuxt DevTools settings page, or explicitly enabled it in your config:",[1213,14985,14987],{"className":1669,"code":14986,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  devtools: {\n    enabled: true\n  }\n})\n",[1220,14988,14989,15001,15010,15019,15023],{"__ignoreMap":1218},[1223,14990,14991,14993,14995,14997,14999],{"class":1225,"line":1226},[1223,14992,1745],{"class":1679},[1223,14994,1748],{"class":1679},[1223,14996,2820],{"class":1751},[1223,14998,1754],{"class":1285},[1223,15000,1757],{"class":1236},[1223,15002,15003,15006,15008],{"class":1225,"line":1233},[1223,15004,15005],{"class":1240},"  devtools",[1223,15007,1765],{"class":1236},[1223,15009,1891],{"class":1236},[1223,15011,15012,15015,15017],{"class":1225,"line":1263},[1223,15013,15014],{"class":1240},"    enabled",[1223,15016,1765],{"class":1236},[1223,15018,3088],{"class":2928},[1223,15020,15021],{"class":1225,"line":1296},[1223,15022,1990],{"class":1236},[1223,15024,15025,15027],{"class":1225,"line":1325},[1223,15026,1801],{"class":1236},[1223,15028,1804],{"class":1285},[1147,15030,15032],{"id":15031},"the-reasons-we-built-nuxt-devtools","The Reasons We Built Nuxt DevTools",[1143,15034,15035],{},"Over the recent years, there has been an increasing focus on Developer Experience (DX). Tools and frameworks have been striving to improve the DX. Along the way, Nuxt introduced many innovative features and conventions to make your day-to-day development easier and more efficient.",[1143,15037,15038,15039,5062,15042,5062,15045,5062,15047,5062,15050,5062,15053,5062,15058,15062],{},"For example, ",[2006,15040,15041],{"href":208},"file-based routing",[2006,15043,15044],{"href":192},"layout system",[2006,15046,211],{"href":212},[2006,15048,15049],{"href":196},"route middleware",[2006,15051,15052],{"href":124},"composables auto-import",[2006,15054,15057],{"href":15055,"rel":15056},"https://nitro.unjs.io/guide/routing",[2010],"file-based server APIs",[2006,15059,15061],{"href":15060},"/modules","powerful module system"," and many more.",[1143,15064,15065],{},[2243,15066],{"alt":15067,"className":15068,"src":15069},"List of Nuxt features that enhance developer experience",[2247,2248,2249,2250],"/assets/blog/devtools/slide-dx.png",[1143,15071,15072],{},"Nuxt is capable of creating various range of applications, from simple hobby projects to large scale applications, from simple client-rendered single-page applications to hybrid rendered sites with serverless functions on edge, etc. We provide those features and conventions to make it easier to support all those use cases and scenarios.",[1155,15074,15076],{"id":15075},"the-problem","The Problem",[1143,15078,15079],{},"Out of all these benefits of having a powerful framework, we have to made some trade-offs. Sometimes, we have to sacrifice a bit of the transparency of the underlying implementation to make things easier to use.",[1143,15081,15082],{},[2243,15083],{"alt":15084,"className":15085,"src":15086},"\"Transparency\" as the trade offs of having \"Conventions\", \"Abstractions\", \"Sensible Defaults\" and \"Normalizations\"",[2247,2248,2249,2250],"/assets/blog/devtools/slide-transparency.png",[1143,15088,15089],{},"Conventional abstractions are great things to transfer implementation complexity and make things easier to get more focus when building. On the other hand, they can also add extra burden for users to learn and understand what's going on under the hood. Leading also to implicitness, like where a auto-imported component is from, or how many modules is using a certain component, etc. It can also make things hard to debug.",[1143,15091,15092],{},"Trade-offs are inevitable. Generally we believe those trade-offs are worth it, as they would help organizing users' codebase and make it easier to maintain in the long run. In the meantime, we also want to compensate the transparency we lost by providing a tool to help you understand what's going on under the hood and make the learning curve smoother.",[1143,15094,15095,15096,15099],{},"That's where Nuxt DevTools comes in! We ",[2006,15097,15098],{"href":1073},"first introduced it"," in February 2023 to experiment with the idea. After a few months of exploration and development, from surprisingly positive feedbacks from the community, this idea has been proven to be useful and we decided to make it a core part of your Nuxt development experience.",[1147,15101,283],{"id":15102},"features",[1143,15104,15105,15108],{},[2006,15106,9560],{"href":9558,"rel":15107},[2010]," is a set of visual tools to help you understand your Nuxt app and improve the developer experience even further. It's created to provide better transparency between Nuxt and your app, find performance bottlenecks and help you manage your app and configuration.",[1155,15110,15112],{"id":15111},"in-app-devtools","In App DevTools",[1143,15114,15115],{},"From the overview, Nuxt DevTools is an in-app DevTools that lives alongside your app. It will show up as a floating panel that you can click to open.",[15117,15118],"article-video",{"cloudinary":15119},"v1700132388/devtools/0-intro_ilgwel",[1143,15121,15122],{},"We believe this is a better approach than the traditional browser extension DevTools, as it's:",[1852,15124,15125,15131,15137],{},[1855,15126,15127,15130],{},[1159,15128,15129],{},"Works across all browsers",", and even on mobile devices! - The capability of browser extension DevTools are limited by the APIs each browsers provides, and also maintain multiple extensions would require a lot of effort. This approach would allow us to focus more on the functionality and features, while having it accessible to users on any browsers and devices.",[1855,15132,15133,15136],{},[1159,15134,15135],{},"Build tools integrations"," - Tranditionally browser extension DevTools are only able to access the runtime context of your app and have no access to the build tools. Having the DevTools comes with Nuxt, allows us to communicate with the build tools and provide much more insights and features.",[1855,15138,15139,15142],{},[1159,15140,15141],{},"Avoid layout shifts"," - Having the DevTools as a floating panel would avoid the layout shifts when toggling the DevTools.",[1155,15144,15146],{"id":15145},"pages-view","Pages View",[1143,15148,15149],{},"To help improving the implicitness of file-based routing, we introduced the Pages View in DevTools. It lists all the pages that have been registered in your app, that you can easily test and navigate between them.",[15117,15151],{"cloudinary":15152},"v1700132393/devtools/1-pages_kkbecx",[1155,15154,15156],{"id":15155},"components-view","Components View",[1143,15158,15159],{},"The Components tab shows all the components you are using in your app and where they are from. You can also search for them and go to the source code.",[1143,15161,15162],{},"It also provides a graph view that show the relationship between components. You can filter the components to see the dependencies of a specific component. This could help to identify unintended dependencies and improve the performance and bundle size of pages.",[15117,15164],{"cloudinary":15165},"v1700132398/devtools/2-components_paj0uv",[1155,15167,15169],{"id":15168},"composables-view","Composables View",[1143,15171,15172],{},"Composables view shows all the auto-imported composables registered to Nuxt. You can see which files are importing them, and where they are from. Some entries can also provide short descriptions and documentation links.",[15117,15174],{"cloudinary":15175},"v1700132395/devtools/3-imports_qhahdf",[1155,15177,15179],{"id":15178},"modules-management","Modules Management",[1143,15181,15182],{},"The Modules tab shows all the modules that are registered in your app, with the links to their documentations and repositories.",[1143,15184,15185],{},"We also provide the ability for you to search for and explore the modules from the community. And install them with a single click!",[15117,15187],{"cloudinary":15188},"v1700132389/devtools/4-modules_v5ha5u",[1155,15190,15192],{"id":15191},"static-assets-management","Static Assets Management",[1143,15194,15195,15196,15198],{},"The Assets tab shows all the static assets under your ",[1220,15197,215],{}," directory. It supports previewing images, videos, fonts, PDFs, and other files, that you can easily copy the URL or code snippet to use in your app. You may also drag and drop files to upload them directly from Nuxt DevTools.",[15117,15200],{"cloudinary":15201},"v1700132394/devtools/5-assets_mpzyrs",[1155,15203,15205],{"id":15204},"runtime-configs-editor","Runtime Configs Editor",[1143,15207,15208],{},"The Runtime Configs tab shows the runtime configs of your app and provides an interactive editor for you to play with different values.",[15117,15210],{"cloudinary":15211},"v1700132393/devtools/6-runtime-configs_fzlrik",[1155,15213,15215],{"id":15214},"payload-editor","Payload Editor",[1143,15217,15218,15219,4363,15223,15227],{},"Similar to the Runtime Configs Editor, the Payload Editor allows you to edit the payload from composables like ",[2006,15220,15221],{"href":537},[1220,15222,536],{},[2006,15224,15225],{"href":445},[1220,15226,444],{}," to see what have been passed from server to client on server-side rendering.",[15117,15229],{"cloudinary":15230},"v1700132389/devtools/7-payload_nfzobp",[1155,15232,15234],{"id":15233},"open-graph-preview","Open Graph Preview",[1143,15236,15237,15242,15243,15248],{},[2006,15238,15241],{"href":15239,"rel":15240},"https://ogp.me/",[2010],"Open Graph"," plays an important role in social media sharing as well as ",[2006,15244,15247],{"href":15245,"rel":15246},"https://en.wikipedia.org/wiki/Search_engine_optimization",[2010],"SEO",". In the traditional workflow, we usually need to first deploy our app to check if the Open Graph is working as expected on various social media platforms. With the Open Graph Preview, you can now preview the Open Graph in DevTools and update it live with an instant feedback loop.",[1143,15250,15251],{},"We also help you check the Open Graph tags in your app and provide suggestions to improve them. You can copy the generated code snippet and paste it to your routes to fix them in one go.",[15117,15253],{"cloudinary":15254},"v1700132390/devtools/8-open-graph_hjawen",[1155,15256,15258],{"id":15257},"plugins-overview","Plugins Overview",[1143,15260,15261,15262,15264],{},"Plugins Overview list all the ",[2006,15263,211],{"href":212}," registered in your app. As the plugins are executed in the runtime before your app renders, it's important to keep plugins performant and avoid blocking the rendering. We provide the execution time of each plugin and the total time of all plugins, so you can better identify the potential performance bottlenecks.",[15117,15266],{"cloudinary":15267},"v1700132390/devtools/9-plugins_bhcobr",[1155,15269,15271],{"id":15270},"timeline","Timeline",[1143,15273,15274],{},"Timeline is a tool for you to check when and how each composable been called. Different from browser DevTools' performance tools, this tab only check the high-level composables combining with other events like route navigration, which is closer to day-to-day use. It also records the arguments and return values of each call, so you can better understand what's going on under the hood.",[1604,15276,15277],{},[1143,15278,15279],{},"As of November 2023, the Timeline is still an experimental feature that requires manually opt-in.",[15117,15281],{"cloudinary":15282},"v1700132392/devtools/10-timeline_zeei5s",[1155,15284,15286],{"id":15285},"production-build-analyzer","Production Build Analyzer",[1143,15288,15289],{},"While Nuxt DevTools is mostly focused on providing development tools, sometimes we might want to know how chunks are composed in production. The Build Analyzer allows you to fire up a production build and analyze the chunks and modules at any time and see how they are bundled. You can also do multiple builds on different branches to compare how your refactoring/changes affect the bundle size, etc.",[15117,15291],{"cloudinary":15292},"v1700132394/devtools/11-build-analyze_f3wx6q",[1155,15294,15296],{"id":15295},"server-api-playground","Server API Playground",[1143,15298,15299,15300,15304,15305,15308],{},"Nuxt provides a very convenient way to create server API functions with the ",[2006,15301,15303],{"href":15302},"/docs/guide/directory-structure/server#server-routes","server routes",". Since in Nuxt we have that information, we are able to provide a playground for you to test and debug your server API functions, similar to tools like Postman. We list all the server APIs available in your app automatically. And we execute those functions ",[1159,15306,15307],{},"within the same context of your app",", so you don't need to manually set them up in external tools. As always, we also have code snippets for you to copy and paste into your app.",[15117,15310],{"cloudinary":15311},"v1700132388/devtools/12-server-api_owjyjg",[1155,15313,15315],{"id":15314},"embedded-full-feature-vs-code","Embedded Full-feature VS Code",[1143,15317,15318],{},"Thanks to the flexibility of our DevTools approach, we can leverage the power of the modern web to embed a full-featured VS Code right in the DevTools. In that VS Code, you can sign in to your account and synchronize your settings, and all the extensions just work as your normal VS Code client. This allows you to quickly edit your code without leaving your browser.",[15117,15320],{"cloudinary":15321},"v1700132395/devtools/13-vscode_je5x0m",[1155,15323,15325],{"id":15324},"component-inspector","Component Inspector",[1143,15327,15328],{},"The Inspector allows you to inspect the DOM tree and see which component is rendering it. Click to go to your editor for the specific line. Making it much easier to make changes without the requirement of understanding the project structure thoroughly.",[15117,15330],{"cloudinary":15331},"v1700132391/devtools/0-inspector_fuxmr7",[1155,15333,15335],{"id":15334},"split-screens","Split Screens",[1143,15337,15338],{},"In the recent releases, we introduced a split screen feature, that allows you to open two tabs side-by-side.",[15117,15340],{"cloudinary":15341},"v1700132391/devtools/0-split-view_mdeiie",[1155,15343,15345],{"id":15344},"ui-customization","UI Customization",[1143,15347,15348],{},"In DevTools setting, we provide a few options for you to customize the tabs you want to see, and the layout of the DevTools.",[15117,15350],{"cloudinary":15351},"v1700132391/devtools/0-settings_weflmu",[1147,15353,9767],{"id":9766},[1143,15355,15356],{},"In Nuxt, we value the ecosystem a lot. Similar to how Nuxt modules enhance Nuxt core, we also designed Nuxt DevTools to be highly extensible, allowing modules to provide additional features and integrations.",[1155,15358,15360],{"id":15359},"community-modules","Community Modules",[1143,15362,15363],{},"We are proud to see the community has already started to build modules for Nuxt DevTools. Here are some of them:",[1143,15365,15366,15371],{},[2006,15367,15370],{"href":15368,"rel":15369},"https://nuxt.com/modules/vitest",[2010],"Vitest module"," provides Vitest UI for tests running with the same pipeline as your Nuxt app. Made it easier to debug your tests alongside your app.",[15117,15373],{"cloudinary":15374},"v1700132393/devtools/99-vitest_wwikpc",[1143,15376,15377,15381],{},[2006,15378,15380],{"href":15379},"/modules/vueuse","VueUse module"," provides a search page for available composables and see their documentation.",[15117,15383],{"cloudinary":15384},"v1700132390/devtools/99-vueuse_simsfj",[1143,15386,15387,15391],{},[2006,15388,15390],{"href":15389},"/modules/sitemap","SiteMap module"," provides an interactive editor for you to manage your sitemap.",[15117,15393],{"cloudinary":15394},"v1700132390/devtools/99-sitemap_xpsfek",[1143,15396,15397,15401],{},[2006,15398,15400],{"href":15399},"/modules/tailwindcss","TailwindCSS module"," provides the Tailwind Config Viewer for you to check what's available based on your config.",[15117,15403],{"cloudinary":15404},"v1700132388/devtools/99-tailwind_dgiodc",[1143,15406,15407,15411],{},[2006,15408,15410],{"href":15409},"/modules/unocss","UnoCSS module"," provides an interactive inspector to see how each module contributes to the final CSS.",[15117,15413],{"cloudinary":15414},"v1700132394/devtools/99-unocss_xvii5x",[1143,15416,15417,15421],{},[2006,15418,15420],{"href":15419},"/modules/storybook","Storybook module"," provides a Storybook UI for your components.",[15117,15423],{"cloudinary":15424},"v1700132388/devtools/99-storybook_ifxt4r",[1143,15426,15427],{},"And they are just a few of them! We are looking forward to see more modules coming to Nuxt DevTools!",[1155,15429,15431],{"id":15430},"projects-inspired-by-nuxt-devtools","Projects Inspired by Nuxt DevTools",[1143,15433,15434],{},"In the meantime, we are also flattered that other frameworks are starting to build their own DevTools inspired by Nuxt DevTools:",[1852,15436,15437,15447,15456,15464],{},[1855,15438,15439,15446],{},[2006,15440,15443],{"href":15441,"rel":15442},"https://github.com/webfansplz/vite-plugin-vue-devtools",[2010],[1220,15444,15445],{},"webfansplz/vite-plugin-vue-devtools"," - A Nuxt DevTools port to support DevTools for Vite + Vue 3 apps.",[1855,15448,15449,15455],{},[2006,15450,15452],{"href":10002,"rel":15451},[2010],[1220,15453,15454],{},"pheno-agency/vite-plugin-devtools"," - An experiment on building framework-agnostic DevTools for Vite.",[1855,15457,15458,15463],{},[2006,15459,15462],{"href":15460,"rel":15461},"https://github.com/Asuka109/modern.js/tree/dev/modernjs-devtools/packages/devtools/plugin",[2010],"Modern.js DevTools"," - In App DevTools for Modern.js",[1855,15465,15466,15471],{},[2006,15467,15470],{"href":15468,"rel":15469},"https://github.com/QwikDev/devtools",[2010],"Qwik DevTools"," - DevTools for Qwik",[1143,15473,15474],{},"We are working closely with the maintainers of those projects to see how we can bring the experience of DevTools to the next level.",[1147,15476,15477],{"id":7754},"What's Next",[1143,15479,15480],{},"Nuxt DevTools just reached v1.0, but t doesn't mean we are done. There are still a lot of things we want to explore and improve. Here are some of the ideas we are considering:",[1852,15482,15483,15492,15499],{},[1855,15484,15485,15486,15491],{},"Nuxt Accessibility Integration - We are building an a11y integration for Nuxt (",[2006,15487,15490],{"href":15488,"rel":15489},"https://github.com/nuxt/nuxt/issues/23255",[2010],"#23255","). We'll build a dedicated view in Nuxt DevTools for you to check the accessibility hints interactively.",[1855,15493,15494,15495,15498],{},"Vue DevTools Integration - We are working with the Vue team to bring the Vue DevTools experience to a shared tool that works for both browser extensions and in-app DevTools like ",[1220,15496,15497],{},"vite-plugin-vue-devtools"," and Nuxt DevTools.",[1855,15500,15501],{},[2006,15502,15505],{"href":15503,"rel":15504},"https://github.com/nuxt/devtools/discussions/29",[2010],"Let us know your ideas/suggestions!",[1147,15507,9804],{"id":9803},[1143,15509,15510],{},"We are excited to see how Nuxt DevTools can help you build better apps and improve your developer experience. Going forward, we are imagining something bigger than Nuxt DevTools itself. We believe that having such framework-specific DevTools is the way onwards to provide even better developer experience. We also see there are many parts of such tools can actually be shared and reused across tools. We came up with the idea of the DevTools Kit.",[1155,15512,15514],{"id":15513},"devtools-kit","DevTools Kit",[1143,15516,15517,15518,15521],{},"DevTools Kit is an idea of the universal protocol that is still in the early brainstorming phase. We imagine that in the best world, each feature of the DevTools should be ",[1159,15519,15520],{},"composable, extensible, and collaborative",". Meta-frameworks could build their own features for their specific needs, while the common web-related tools could be shared and collaborated on between different frameworks.",[1143,15523,15524],{},[2243,15525],{"alt":15514,"className":15526,"src":15527},[2247,2248,2249,2250],"/assets/blog/devtools/slide-devtools-kit.png",[1143,15529,15530],{},"Imagine we could have all these features, each as a standalone package. We could have general web-related tools like SEO, Accessibility, PWA, Static Assets, etc. Then low-level build tools related, like Vite build analyzer, Vite Inspector, or Webpack visualizer, etc. And finally, we could have framework and meta-framework specific tools like Vue Components view, or Nuxt Server API Playground, etc.",[1143,15532,15533],{},[2243,15534],{"alt":9560,"className":15535,"src":15536},[2247,2248,2249,2250],"/assets/blog/devtools/slide-nuxt-devtools.png",[1143,15538,15539],{},[2243,15540],{"alt":9560,"className":15541,"src":15542},[2247,2248,2249,2250],"/assets/blog/devtools/slide-vue-devtools.png",[1143,15544,15545],{},"At that time, Vue DevTools would be a composition of common web features and Vue-specific features. And Nuxt DevTools would essentially be a composition of the features above, inherit all features from Vue DevTools, and add Nuxt specific features on top of it.",[1143,15547,15548],{},[2243,15549],{"alt":15550,"className":15551,"src":15552},"Your DevTools",[2247,2248,2249,2250],"/assets/blog/devtools/slide-your-devtools.png",[1143,15554,15555],{},"It would even be possible to compose your own DevTools as you like.",[1143,15557,15558],{},"That said, we are still thinking about and discussing the details of the DevTools Kit. Stay tuned for more updates!",[1147,15560,15562],{"id":15561},"conclusion","Conclusion",[1143,15564,15565,15566,15570],{},"We hope you enjoy the new Nuxt DevTools experience! We are looking forward to seeing how it can help you build better apps and improve your developer experience. If you have any ideas or suggestions, feel free to let us know in the ",[2006,15567,15569],{"href":15503,"rel":15568},[2010],"Ideas & Suggestions"," discussion.",[1143,15572,15573],{},"Thank you for your support and happy hacking! 🚀",[2160,15575,15576],{},"html pre.shiki code .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .sagxc, html code.shiki .sagxc{--shiki-light:#FF5370;--shiki-default:#FF5370;--shiki-dark:#FF9CAC}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);}",{"title":1218,"searchDepth":1233,"depth":1233,"links":15578},[15579,15582,15601,15605,15606,15609],{"id":15031,"depth":1233,"text":15032,"children":15580},[15581],{"id":15075,"depth":1263,"text":15076},{"id":15102,"depth":1233,"text":283,"children":15583},[15584,15585,15586,15587,15588,15589,15590,15591,15592,15593,15594,15595,15596,15597,15598,15599,15600],{"id":15111,"depth":1263,"text":15112},{"id":15145,"depth":1263,"text":15146},{"id":15155,"depth":1263,"text":15156},{"id":15168,"depth":1263,"text":15169},{"id":15178,"depth":1263,"text":15179},{"id":15191,"depth":1263,"text":15192},{"id":15204,"depth":1263,"text":15205},{"id":15214,"depth":1263,"text":15215},{"id":15233,"depth":1263,"text":15234},{"id":15257,"depth":1263,"text":15258},{"id":15270,"depth":1263,"text":15271},{"id":15285,"depth":1263,"text":15286},{"id":15295,"depth":1263,"text":15296},{"id":15314,"depth":1263,"text":15315},{"id":15324,"depth":1263,"text":15325},{"id":15334,"depth":1263,"text":15335},{"id":15344,"depth":1263,"text":15345},{"id":9766,"depth":1233,"text":9767,"children":15602},[15603,15604],{"id":15359,"depth":1263,"text":15360},{"id":15430,"depth":1263,"text":15431},{"id":7754,"depth":1233,"text":15477},{"id":9803,"depth":1233,"text":9804,"children":15607},[15608],{"id":15513,"depth":1263,"text":15514},{"id":15561,"depth":1233,"text":15562},"2023-11-13","Nuxt DevTools v1.0 is out, generally available to all Nuxt projects!","/assets/blog/nuxt-devtools-1-0.png",{},{"title":1048,"description":15611},"kluel30emW",{"id":15617,"title":15618,"authors":15619,"body":15622,"category":2176,"date":16893,"description":16894,"draft":108,"extension":1954,"image":16895,"meta":16896,"navigation":108,"path":14970,"seo":16897,"stem":16898,"tags":6,"__hash__":16899},"blog/blog/17.v3-8.md","Nuxt 3.8",[15620],{"name":2190,"avatar":15621,"to":2193},{"src":2192},{"type":1140,"value":15623,"toc":16877},[15624,15628,15637,15645,15650,15659,15663,15666,15671,15675,15686,15698,15717,15728,15732,15738,15752,15790,15799,15803,15815,15826,15837,15969,15977,15994,15998,16015,16031,16038,16063,16070,16114,16119,16123,16138,16154,16157,16245,16249,16260,16292,16411,16421,16428,16559,16563,16588,16611,16617,16621,16632,16662,16671,16675,16678,16697,16703,16707,16712,16722,16733,16762,16765,16768,16839,16842,16844,16846,16858,16860,16868,16870,16874],[1155,15625,15627],{"id":15626},"cli-improvements","💻 CLI Improvements",[1143,15629,15630,15631,15636],{},"Just to remind you, we're now using ",[2006,15632,15635],{"href":15633,"rel":15634},"https://github.com/nuxt/cli",[2010],"the new Nuxt CLI"," which is now versioned separately.",[7733,15638,15639],{},[1143,15640,15641,15642],{},"You can now install a module with ",[1220,15643,15644],{},"nuxi module add \u003Cmodule-name>",[7747,15646,15647],{"icon":14},[1143,15648,15649],{},"We now share the same port with the Vite websocket, meaning better support for docker containers in development.",[3611,15651,15653],{"to":15652,"icon":3614,"color":3613,"target":3615},"https://github.com/nuxt/cli/releases/tag/v3.9.0",[1143,15654,15655,15656,15658],{},"Read the Nuxt CLI ",[1220,15657,14918],{}," release notes.",[1155,15660,15662],{"id":15661},"built-in-nuxt-devtools","✨ Built-in Nuxt DevTools",[1143,15664,15665],{},"Nuxt DevTools v1.0.0 is out and we now think it's ready to be shipped as a direct dependency of Nuxt.",[3611,15667,15668],{"to":1049,"icon":3614,"color":3613},[1143,15669,15670],{},"Check out Nuxt DevTools v1.0 announcement.",[1155,15672,15674],{"id":15673},"nuxt-image-auto-install","📸 Nuxt Image Auto-install",[1143,15676,15677,4363,15681,15685],{},[2006,15678,15679],{"href":414},[1220,15680,413],{},[2006,15682,15683],{"href":373},[1220,15684,372],{}," first-class built-in components.",[1143,15687,15688,15689,15692,15693,3681],{},"We now auto-installing ",[1220,15690,15691],{},"@nuxt/image"," the first time that they are used (",[2006,15694,15697],{"href":15695,"rel":15696},"https://github.com/nuxt/nuxt/pull/23717",[2010],"#23717",[7119,15699,15704,15709,15713],{":controls":9655,"className":15700,"controls":1739,"poster":15703},[15701,15702,2249],"rounded","dark:border","https://res.cloudinary.com/nuxt/video/upload/v1697721767/nuxt3/nuxt-image-auto-install_uqkptq.jpg",[15705,15706],"source",{"src":15707,"type":15708},"https://res.cloudinary.com/nuxt/video/upload/v1697721767/nuxt3/nuxt-image-auto-install_uqkptq.webm","video/webm",[15705,15710],{"src":15711,"type":15712},"https://res.cloudinary.com/nuxt/video/upload/v1697721767/nuxt3/nuxt-image-auto-install_uqkptq.mp4","video/mp4",[15705,15714],{"src":15715,"type":15716},"https://res.cloudinary.com/nuxt/video/upload/v1697721767/nuxt3/nuxt-image-auto-install_uqkptq.ogg","video/ogg",[7733,15718,15719],{},[1143,15720,15721,15722,15727],{},"We advise using ",[2006,15723,15725],{"href":9966,"rel":15724},[2010],[1220,15726,15691],{}," if you're using images in your site; it can apply optimisations to make your site more performant.",[1155,15729,15731],{"id":15730},"deeper-layout-scanning","📂 Deeper Layout Scanning",[15733,15734,15735],"caution",{},[1143,15736,15737],{},"This is a behaviour change so do take care with this one.",[1143,15739,15740,15741,15746,15747,2281],{},"We now support scanning layouts within subfolders in ",[2006,15742,15743],{"href":192},[1220,15744,15745],{},"~/layouts"," in the same way as we do with ",[2006,15748,15749],{"href":180},[1220,15750,15751],{},"~/components",[1509,15753,15754,15764],{},[1512,15755,15756],{},[1515,15757,15758,15761],{},[1518,15759,15760],{},"File",[1518,15762,15763],{},"Layout name",[1528,15765,15766,15774,15782],{},[1515,15767,15768,15771],{},[1533,15769,15770],{},"~/layouts/desktop/default.vue",[1533,15772,15773],{},"'desktop-default'",[1515,15775,15776,15779],{},[1533,15777,15778],{},"~/layouts/desktop-base/base.vue",[1533,15780,15781],{},"'desktop-base'",[1515,15783,15784,15787],{},[1533,15785,15786],{},"~/layouts/desktop/index.vue",[1533,15788,15789],{},"'desktop'",[3611,15791,15793],{"to":15792},"/docs/guide/directory-structure/layouts#named-layout",[1143,15794,15795,15796,2281],{},"Read more about ",[1159,15797,15798],{},"Named Layouts",[1155,15800,15802],{"id":15801},"app-manifest","📊 App Manifest",[1143,15804,15805,15806,15811,15812,2281],{},"We now support a built-in app manifest (see ",[2006,15807,15810],{"href":15808,"rel":15809},"https://github.com/nuxt/nuxt/pull/21641",[2010],"PR #21641","), which generates a manifest at ",[1220,15813,15814],{},"/_nuxt/builds/meta/\u003CbuildId>.json",[1143,15816,15817,15818,15821,15822,15825],{},"It enables loading payloads ",[1159,15819,15820],{},"only for prerendered routes",", if a site is generated with ",[1220,15823,15824],{},"nuxt generate",", preventing 404s in the console.",[1143,15827,15828,15829,15832,15833,15836],{},"It also enables ",[1159,15830,15831],{},"client-side route rules",". Only ",[1220,15834,15835],{},"redirect"," route rules is supported for now; they will now redirect when performing client-side navigation.",[2054,15838,15839,15900],{},[1213,15840,15842],{"className":1669,"code":15841,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  routeRules: {\n    '/about': { redirect: '/about-us' }\n  }\n})\n",[1220,15843,15844,15856,15864,15890,15894],{"__ignoreMap":1218},[1223,15845,15846,15848,15850,15852,15854],{"class":1225,"line":1226},[1223,15847,1745],{"class":1679},[1223,15849,1748],{"class":1679},[1223,15851,2820],{"class":1751},[1223,15853,1754],{"class":1285},[1223,15855,1757],{"class":1236},[1223,15857,15858,15860,15862],{"class":1225,"line":1233},[1223,15859,10778],{"class":1240},[1223,15861,1765],{"class":1236},[1223,15863,1891],{"class":1236},[1223,15865,15866,15868,15870,15872,15874,15876,15879,15881,15883,15886,15888],{"class":1225,"line":1263},[1223,15867,9188],{"class":1236},[1223,15869,5065],{"class":1240},[1223,15871,1957],{"class":1236},[1223,15873,1765],{"class":1236},[1223,15875,1683],{"class":1236},[1223,15877,15878],{"class":1240}," redirect",[1223,15880,1765],{"class":1236},[1223,15882,1695],{"class":1236},[1223,15884,15885],{"class":1254},"/about-us",[1223,15887,1957],{"class":1236},[1223,15889,5311],{"class":1236},[1223,15891,15892],{"class":1225,"line":1296},[1223,15893,1990],{"class":1236},[1223,15895,15896,15898],{"class":1225,"line":1325},[1223,15897,1801],{"class":1236},[1223,15899,1804],{"class":1285},[1213,15901,15903],{"className":2595,"code":15902,"filename":5115,"language":2597,"meta":1218,"style":1218},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003C!-- Will be redirected to /about-us on client-side -->\n    \u003CNuxtLink to=\"/about\">About\u003C/NuxtLink>\n  \u003C/div>\n\u003C/template>\n",[1220,15904,15905,15913,15921,15926,15953,15961],{"__ignoreMap":1218},[1223,15906,15907,15909,15911],{"class":1225,"line":1226},[1223,15908,1237],{"class":1236},[1223,15910,2606],{"class":1240},[1223,15912,1260],{"class":1236},[1223,15914,15915,15917,15919],{"class":1225,"line":1233},[1223,15916,1266],{"class":1236},[1223,15918,1241],{"class":1240},[1223,15920,1260],{"class":1236},[1223,15922,15923],{"class":1225,"line":1263},[1223,15924,15925],{"class":1229},"    \u003C!-- Will be redirected to /about-us on client-side -->\n",[1223,15927,15928,15930,15932,15934,15936,15938,15940,15942,15944,15947,15949,15951],{"class":1225,"line":1296},[1223,15929,5138],{"class":1236},[1223,15931,5104],{"class":1240},[1223,15933,11109],{"class":1244},[1223,15935,1248],{"class":1236},[1223,15937,1251],{"class":1236},[1223,15939,5065],{"class":1254},[1223,15941,1251],{"class":1236},[1223,15943,1282],{"class":1236},[1223,15945,15946],{"class":1285},"About",[1223,15948,1289],{"class":1236},[1223,15950,5104],{"class":1240},[1223,15952,1260],{"class":1236},[1223,15954,15955,15957,15959],{"class":1225,"line":1325},[1223,15956,5211],{"class":1236},[1223,15958,1241],{"class":1240},[1223,15960,1260],{"class":1236},[1223,15962,15963,15965,15967],{"class":1225,"line":1355},[1223,15964,1289],{"class":1236},[1223,15966,2606],{"class":1240},[1223,15968,1260],{"class":1236},[7733,15970,15971],{"icon":14},[1143,15972,15973,15974,2281],{},"The app manifest also enables future enhancements including detection of a new deployment by checking ",[1220,15975,15976],{},"/_nuxt/builds/latest.json",[7747,15978,15979],{},[1143,15980,15981,15982,15985,15986,4880,15989,2131,15991,15993],{},"You can ",[1159,15983,15984],{},"opt-on from this behaviour if you need to"," by setting ",[1220,15987,15988],{},"experimental.appManifest",[1220,15990,6969],{},[1220,15992,5357],{}," file.",[1155,15995,15997],{"id":15996},"scope-and-context-improvements","🤝 Scope and Context Improvements",[1143,15999,16000,16001,16006,16007,16014],{},"We now define a 'scope' for Nuxt composables executed in plugins (",[2006,16002,16005],{"href":16003,"rel":16004},"https://github.com/nuxt/nuxt/pull/23667",[2010],"#23667","), which allows running synchronous cleanup before navigating away from your site, using the Vue ",[2006,16008,16011],{"href":16009,"rel":16010},"https://vuejs.org/api/reactivity-advanced.html#onscopedispose",[2010],[1220,16012,16013],{},"onScopeDispose"," lifecycle method.",[7747,16016,16017],{},[1143,16018,16019,16020,16025,16026,3681],{},"This should fix an edge case with cookies (",[2006,16021,16024],{"href":16022,"rel":16023},"https://github.com/nuxt/nuxt/pull/23697",[2010],"#23697",") and also improves memory management such as Pinia stores (",[2006,16027,16030],{"href":16028,"rel":16029},"https://github.com/nuxt/nuxt/issues/23650",[2010],"#23650",[3611,16032,16035],{"to":16033,"icon":16034,"target":3615},"https://vuejs.org/api/reactivity-advanced.html#effectscope","i-simple-icons-vuedotjs",[1143,16036,16037],{},"Read more about Vue effect scopes.",[1143,16039,16040,16041,2260,16048,3114,16051,16056,16057,2281],{},"We also now support ",[2006,16042,16045],{"href":16043,"rel":16044},"https://nodejs.org/api/async_context.html",[2010],[1159,16046,16047],{},"native async context",[3746,16049,16050],{},"Vue composition API",[2006,16052,16055],{"href":16053,"rel":16054},"https://github.com/nuxt/nuxt/pull/23526",[2010],"#23526","). In case you're unaware, we support native async context on Node and Bun, enabled with ",[2006,16058,16060],{"href":16059},"/docs/guide/going-further/experimental-features#asynccontext",[1220,16061,16062],{},"experimental.asyncContext",[1143,16064,16065,16066,16069],{},"If you experience issues with ",[1220,16067,16068],{},"Nuxt instance unavailable",", enabling this option may solve your issues:",[1213,16071,16073],{"className":1669,"code":16072,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  experimental: {\n    asyncContext: true\n  }\n})\n",[1220,16074,16075,16087,16095,16104,16108],{"__ignoreMap":1218},[1223,16076,16077,16079,16081,16083,16085],{"class":1225,"line":1226},[1223,16078,1745],{"class":1679},[1223,16080,1748],{"class":1679},[1223,16082,2820],{"class":1751},[1223,16084,1754],{"class":1285},[1223,16086,1757],{"class":1236},[1223,16088,16089,16091,16093],{"class":1225,"line":1233},[1223,16090,3074],{"class":1240},[1223,16092,1765],{"class":1236},[1223,16094,1891],{"class":1236},[1223,16096,16097,16100,16102],{"class":1225,"line":1263},[1223,16098,16099],{"class":1240},"    asyncContext",[1223,16101,1765],{"class":1236},[1223,16103,3088],{"class":2928},[1223,16105,16106],{"class":1225,"line":1296},[1223,16107,1990],{"class":1236},[1223,16109,16110,16112],{"class":1225,"line":1325},[1223,16111,1801],{"class":1236},[1223,16113,1804],{"class":1285},[7747,16115,16116],{},[1143,16117,16118],{},"Once we have cross-runtime support, we will enable it by default.",[1155,16120,16122],{"id":16121},"nuxtlink-defaults","🔗 NuxtLink Defaults",[1143,16124,16125,16126,16130,16131,16137],{},"You can define your own ",[2006,16127,16128],{"href":394},[1220,16129,393],{}," components with the ",[2006,16132,16134],{"href":16133},"/docs/api/components/nuxt-link#definenuxtlink-signature",[1220,16135,16136],{},"defineNuxtLink"," utility.",[1143,16139,16140,16141,16145,16146,16148,16149,3681],{},"Today, you can cutomize the options for the built-in ",[2006,16142,16143],{"href":394},[1220,16144,393],{},", directly in your ",[1220,16147,5357],{}," file (",[2006,16150,16153],{"href":16151,"rel":16152},"https://github.com/nuxt/nuxt/pull/23724",[2010],"#23724",[1143,16155,16156],{},"This can enable you to enforce trailing slash behaviour across your entire site, for example:",[1213,16158,16160],{"className":1669,"code":16159,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  experimental: {\n    defaults: {\n      nuxtLink: {\n        activeClass: 'nuxt-link-active',\n        trailingSlash: 'append'\n      }\n    }\n  }\n})\n",[1220,16161,16162,16174,16182,16190,16198,16214,16227,16231,16235,16239],{"__ignoreMap":1218},[1223,16163,16164,16166,16168,16170,16172],{"class":1225,"line":1226},[1223,16165,1745],{"class":1679},[1223,16167,1748],{"class":1679},[1223,16169,2820],{"class":1751},[1223,16171,1754],{"class":1285},[1223,16173,1757],{"class":1236},[1223,16175,16176,16178,16180],{"class":1225,"line":1233},[1223,16177,3074],{"class":1240},[1223,16179,1765],{"class":1236},[1223,16181,1891],{"class":1236},[1223,16183,16184,16186,16188],{"class":1225,"line":1263},[1223,16185,5258],{"class":1240},[1223,16187,1765],{"class":1236},[1223,16189,1891],{"class":1236},[1223,16191,16192,16194,16196],{"class":1225,"line":1296},[1223,16193,5267],{"class":1240},[1223,16195,1765],{"class":1236},[1223,16197,1891],{"class":1236},[1223,16199,16200,16203,16205,16207,16210,16212],{"class":1225,"line":1325},[1223,16201,16202],{"class":1240},"        activeClass",[1223,16204,1765],{"class":1236},[1223,16206,1695],{"class":1236},[1223,16208,16209],{"class":1254},"nuxt-link-active",[1223,16211,1957],{"class":1236},[1223,16213,1780],{"class":1236},[1223,16215,16216,16219,16221,16223,16225],{"class":1225,"line":1355},[1223,16217,16218],{"class":1240},"        trailingSlash",[1223,16220,1765],{"class":1236},[1223,16222,1695],{"class":1236},[1223,16224,9138],{"class":1254},[1223,16226,1701],{"class":1236},[1223,16228,16229],{"class":1225,"line":1771},[1223,16230,1978],{"class":1236},[1223,16232,16233],{"class":1225,"line":1783},[1223,16234,1984],{"class":1236},[1223,16236,16237],{"class":1225,"line":1792},[1223,16238,1990],{"class":1236},[1223,16240,16241,16243],{"class":1225,"line":1798},[1223,16242,1801],{"class":1236},[1223,16244,1804],{"class":1285},[1155,16246,16248],{"id":16247},"️-data-fetching-improvements","⚡️ Data Fetching Improvements",[1143,16250,16251,16252,4363,16256,1765],{},"We have two very significant new features for ",[2006,16253,16254],{"href":433},[1220,16255,432],{},[2006,16257,16258],{"href":445},[1220,16259,444],{},[2412,16261,16262,16280],{},[1855,16263,16264,16265,16268,16269,16271,16272,16277,16278,2281],{},"You can now set ",[1220,16266,16267],{},"deep: false"," to prevent deep reactivity on the ",[1220,16270,7073],{}," object returned from these composables (",[2006,16273,16276],{"href":16274,"rel":16275},"https://github.com/nuxt/nuxt/pull/23600",[2010],"#23600","). It should be a performance improvement if you are returning large arrays or objects. The object will still update when refetched; it just won't trigger reactive effects if you change a property deep within the ",[1220,16279,7073],{},[1855,16281,16282,16283,16286,16287,2541],{},"You can now use the ",[1220,16284,16285],{},"getCachedData"," option to handle custom caching for these composables (",[2006,16288,16291],{"href":16289,"rel":16290},"https://github.com/nuxt/nuxt/pull/20747",[2010],"#20747",[1213,16293,16295],{"className":2595,"code":16294,"filename":5115,"language":2597,"meta":1218,"style":1218},"\u003Cscript setup>\nconst nuxtApp = useNuxtApp()\nconst { data } = await useAsyncData(() => { /* fetcher */ }, {\n  // this will not refetch if the key exists in the payload\n  getCachedData: key => nuxtApp.payload.static[key] ?? nuxtApp.payload.data[key]\n})\n\u003C/script>\n",[1220,16296,16297,16307,16321,16353,16358,16397,16403],{"__ignoreMap":1218},[1223,16298,16299,16301,16303,16305],{"class":1225,"line":1226},[1223,16300,1237],{"class":1236},[1223,16302,5899],{"class":1240},[1223,16304,5902],{"class":1244},[1223,16306,1260],{"class":1236},[1223,16308,16309,16311,16314,16316,16319],{"class":1225,"line":1233},[1223,16310,3214],{"class":1244},[1223,16312,16313],{"class":1285}," nuxtApp ",[1223,16315,1248],{"class":1236},[1223,16317,16318],{"class":1751}," useNuxtApp",[1223,16320,1789],{"class":1285},[1223,16322,16323,16325,16327,16329,16331,16333,16335,16337,16339,16341,16343,16345,16348,16351],{"class":1225,"line":1263},[1223,16324,3214],{"class":1244},[1223,16326,1683],{"class":1236},[1223,16328,10505],{"class":1285},[1223,16330,1801],{"class":1236},[1223,16332,2339],{"class":1236},[1223,16334,10512],{"class":1679},[1223,16336,10515],{"class":1751},[1223,16338,1754],{"class":1285},[1223,16340,1777],{"class":1236},[1223,16342,3125],{"class":1244},[1223,16344,1683],{"class":1236},[1223,16346,16347],{"class":1229}," /* fetcher */",[1223,16349,16350],{"class":1236}," },",[1223,16352,1891],{"class":1236},[1223,16354,16355],{"class":1225,"line":1296},[1223,16356,16357],{"class":1229},"  // this will not refetch if the key exists in the payload\n",[1223,16359,16360,16363,16365,16368,16370,16373,16375,16378,16380,16383,16386,16388,16390,16392,16394],{"class":1225,"line":1325},[1223,16361,16362],{"class":1751},"  getCachedData",[1223,16364,1765],{"class":1236},[1223,16366,16367],{"class":2329}," key",[1223,16369,3125],{"class":1244},[1223,16371,16372],{"class":1285}," nuxtApp",[1223,16374,2281],{"class":1236},[1223,16376,16377],{"class":1285},"payload",[1223,16379,2281],{"class":1236},[1223,16381,16382],{"class":1285},"static[key] ",[1223,16384,16385],{"class":1236},"??",[1223,16387,16372],{"class":1285},[1223,16389,2281],{"class":1236},[1223,16391,16377],{"class":1285},[1223,16393,2281],{"class":1236},[1223,16395,16396],{"class":1285},"data[key]\n",[1223,16398,16399,16401],{"class":1225,"line":1355},[1223,16400,1801],{"class":1236},[1223,16402,1804],{"class":1285},[1223,16404,16405,16407,16409],{"class":1225,"line":1771},[1223,16406,1289],{"class":1236},[1223,16408,5899],{"class":1240},[1223,16410,1260],{"class":1236},[7733,16412,16415],{"icon":16413,"target":3615,"to":16414},"i-logos-youtube-icon","https://www.youtube.com/watch?v=aQPR0xn-MMk",[1143,16416,16417,16418,2281],{},"Watch the video from Alexander Lichter about ",[1159,16419,16420],{},"Client-side caching with getCachedData",[1143,16422,16423,16424,2887],{},"We also support configuring some default values for these composables in an app-wide way (",[2006,16425,16427],{"href":16289,"rel":16426},[2010],"#23725",[1213,16429,16431],{"className":1669,"code":16430,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  experimental: {\n    defaults: {\n      useAsyncData: {\n        deep: false\n      },\n      useFetch: {\n        retry: false,\n        retryDelay: 100,\n        retryStatusCodes: [500],\n        timeout: 100\n      }\n    }\n  }\n})\n",[1220,16432,16433,16445,16453,16461,16470,16479,16483,16492,16503,16515,16531,16541,16545,16549,16553],{"__ignoreMap":1218},[1223,16434,16435,16437,16439,16441,16443],{"class":1225,"line":1226},[1223,16436,1745],{"class":1679},[1223,16438,1748],{"class":1679},[1223,16440,2820],{"class":1751},[1223,16442,1754],{"class":1285},[1223,16444,1757],{"class":1236},[1223,16446,16447,16449,16451],{"class":1225,"line":1233},[1223,16448,3074],{"class":1240},[1223,16450,1765],{"class":1236},[1223,16452,1891],{"class":1236},[1223,16454,16455,16457,16459],{"class":1225,"line":1263},[1223,16456,5258],{"class":1240},[1223,16458,1765],{"class":1236},[1223,16460,1891],{"class":1236},[1223,16462,16463,16466,16468],{"class":1225,"line":1296},[1223,16464,16465],{"class":1240},"      useAsyncData",[1223,16467,1765],{"class":1236},[1223,16469,1891],{"class":1236},[1223,16471,16472,16475,16477],{"class":1225,"line":1325},[1223,16473,16474],{"class":1240},"        deep",[1223,16476,1765],{"class":1236},[1223,16478,10665],{"class":2928},[1223,16480,16481],{"class":1225,"line":1355},[1223,16482,1933],{"class":1236},[1223,16484,16485,16488,16490],{"class":1225,"line":1771},[1223,16486,16487],{"class":1240},"      useFetch",[1223,16489,1765],{"class":1236},[1223,16491,1891],{"class":1236},[1223,16493,16494,16497,16499,16501],{"class":1225,"line":1783},[1223,16495,16496],{"class":1240},"        retry",[1223,16498,1765],{"class":1236},[1223,16500,5299],{"class":2928},[1223,16502,1780],{"class":1236},[1223,16504,16505,16508,16510,16513],{"class":1225,"line":1792},[1223,16506,16507],{"class":1240},"        retryDelay",[1223,16509,1765],{"class":1236},[1223,16511,16512],{"class":6166}," 100",[1223,16514,1780],{"class":1236},[1223,16516,16517,16520,16522,16524,16527,16529],{"class":1225,"line":1798},[1223,16518,16519],{"class":1240},"        retryStatusCodes",[1223,16521,1765],{"class":1236},[1223,16523,2848],{"class":1285},[1223,16525,16526],{"class":6166},"500",[1223,16528,2858],{"class":1285},[1223,16530,1780],{"class":1236},[1223,16532,16533,16536,16538],{"class":1225,"line":1975},[1223,16534,16535],{"class":1240},"        timeout",[1223,16537,1765],{"class":1236},[1223,16539,16540],{"class":6166}," 100\n",[1223,16542,16543],{"class":1225,"line":1981},[1223,16544,1978],{"class":1236},[1223,16546,16547],{"class":1225,"line":1987},[1223,16548,1984],{"class":1236},[1223,16550,16551],{"class":1225,"line":1993},[1223,16552,1990],{"class":1236},[1223,16554,16555,16557],{"class":1225,"line":2720},[1223,16556,1801],{"class":1236},[1223,16558,1804],{"class":1285},[1155,16560,16562],{"id":16561},"layer-improvements","🔢 Layer Improvements",[1143,16564,16565,16566,4363,16571,16576,16577,4363,16582,16587],{},"We now more carefully load layer plugins (",[2006,16567,16570],{"href":16568,"rel":16569},"https://github.com/nuxt/nuxt/pull/22889",[2010],"#22889",[2006,16572,16575],{"href":16573,"rel":16574},"https://github.com/nuxt/nuxt/pull/23148",[2010],"#23148",") and middleware (",[2006,16578,16581],{"href":16579,"rel":16580},"https://github.com/nuxt/nuxt/pull/22925",[2010],"#22925",[2006,16583,16586],{"href":16584,"rel":16585},"https://github.com/nuxt/nuxt/pull/23552",[2010],"#23552",") in the order of the layers, always loading your own plugins and middleware last. This should mean you can rely on utilities that layers may inject.",[1143,16589,16590,16591,4710,16596,16601,16602,16610],{},"And probably one of the most significant changes - if you are using remote layers we now clone these within your ",[2006,16592,16593],{"href":204},[1220,16594,16595],{},"node_modules/",[2006,16597,16600],{"href":16598,"rel":16599},"https://github.com/unjs/c12/pull/109",[2010],"#109",") so layers can use dependencies with your project. See ",[2006,16603,16606,16609],{"href":16604,"rel":16605},"https://github.com/unjs/c12/releases/tag/v1.5.1",[2010],[1220,16607,16608],{},"c12"," release notes"," for full details.",[7733,16612,16614],{"icon":16613},"i-lucide-check-circle",[1143,16615,16616],{},"We've also added a test suite to cover these layer resolution changes.",[1155,16618,16620],{"id":16619},"nightly-release-channel","😴 Nightly Release Channel",[1143,16622,16623,16624,16627,16628,16631],{},"Every commit to the ",[1220,16625,16626],{},"main"," branch of Nuxt is automatically deployed to a new release, for easier testing before releases. We've renamed this from the 'edge release channel' to the 'nightly release channel' to avoid confusion with ",[3746,16629,16630],{},"edge deployments",". And probably also with Microsoft Edge (though I haven't heard that anyone was confused with that one!)",[1852,16633,16634,16643,16651,16659],{},[1855,16635,16636,16639,16640],{},[1220,16637,16638],{},"nuxt3"," is now ",[1220,16641,16642],{},"nuxt-nightly",[1855,16644,16645,16639,16648],{},[1220,16646,16647],{},"nuxi-edge",[1220,16649,16650],{},"nuxi-nightly",[1855,16652,16653,16639,16656],{},[1220,16654,16655],{},"@​nuxt/kit-edge",[1220,16657,16658],{},"@​nuxt/kit-nightly",[1855,16660,16661],{},"... and so on.",[3611,16663,16665],{"to":16664},"/docs/guide/going-further/nightly-release-channel#nightly-release-channel",[1143,16666,16667,16668,2281],{},"Read more about the ",[1159,16669,16670],{},"Nighly Release Channel",[1155,16672,16674],{"id":16673},"️-nitro-v27","⚗️ Nitro v2.7",[1143,16676,16677],{},"Nitro v2.7 has been released with lots of improvements and bug fixes.",[7733,16679,16680],{"icon":14},[1143,16681,16682,16683,16686,16687,16690,16691,16696],{},"🔥 One of the most significant is that we now save ",[1159,16684,16685],{},"40% of bundle size in production"," by using native ",[1220,16688,16689],{},"fetch"," supported in Node 18+ (",[2006,16692,16695],{"href":16693,"rel":16694},"https://github.com/unjs/nitro/pull/1724",[2010],"#1724","). So if possible, we'd recommend you update your Node version to at least 18.",[3611,16698,16700],{"to":16699,"icon":3614,"color":3613,"target":3615},"https://github.com/unjs/nitro/releases/tag/v2.7.0",[1143,16701,16702],{},"Check out Nitro v2.7 release note.",[1155,16704,16706],{"id":16705},"type-import-changes","💪 Type Import Changes",[1604,16708,16709],{},[1143,16710,16711],{},"This is likely to need code changes in your project.",[1143,16713,16714,16715,2281],{},"Vue requires that type imports be explicit (so that the Vue compiler can correctly optimise and resolve type imports for props and so on). See ",[2006,16716,16719,16720],{"href":16717,"rel":16718},"https://github.com/vuejs/tsconfig/blob/main/tsconfig.json#L30-L33",[2010],"core Vue ",[1220,16721,268],{},[1143,16723,16724,16725,16728,16729,16732],{},"We've therefore taken the decision to turn on ",[1220,16726,16727],{},"verbatimModuleSyntax"," by default in Nuxt projects, which will throw a type error if types are imported without an explicit ",[1220,16730,16731],{},"type"," import. To resolve it you will need to update your imports:",[1213,16734,16738],{"className":16735,"code":16736,"language":16737,"meta":1218,"style":1218},"language-diff shiki shiki-themes material-theme-lighter material-theme-lighter material-theme-palenight","- import { someFunction, SomeOptions } from 'some-library'\n+ import { someFunction } from 'some-library'\n+ import type { SomeOptions } from 'some-library'\n","diff",[1220,16739,16740,16747,16755],{"__ignoreMap":1218},[1223,16741,16742,16744],{"class":1225,"line":1226},[1223,16743,5004],{"class":1236},[1223,16745,16746],{"class":1240}," import { someFunction, SomeOptions } from 'some-library'\n",[1223,16748,16749,16752],{"class":1225,"line":1233},[1223,16750,16751],{"class":1236},"+",[1223,16753,16754],{"class":1254}," import { someFunction } from 'some-library'\n",[1223,16756,16757,16759],{"class":1225,"line":1263},[1223,16758,16751],{"class":1236},[1223,16760,16761],{"class":1254}," import type { SomeOptions } from 'some-library'\n",[1143,16763,16764],{},"You may also encounter modules in the Nuxt ecosystem that need to be updated; please open an issue for those modules. I'm also very happy to help if you're encountering any problems with this, if you're a module author. Just tag me and I'll take a look.",[1143,16766,16767],{},"If for whatever reason you need to undo this change in your project you can set the following configuration:",[1213,16769,16771],{"className":1669,"code":16770,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  typescript: {\n    tsConfig: {\n      compilerOptions: {\n        verbatimModuleSyntax: false\n      }\n    }\n  }\n})\n",[1220,16772,16773,16785,16794,16803,16812,16821,16825,16829,16833],{"__ignoreMap":1218},[1223,16774,16775,16777,16779,16781,16783],{"class":1225,"line":1226},[1223,16776,1745],{"class":1679},[1223,16778,1748],{"class":1679},[1223,16780,2820],{"class":1751},[1223,16782,1754],{"class":1285},[1223,16784,1757],{"class":1236},[1223,16786,16787,16790,16792],{"class":1225,"line":1233},[1223,16788,16789],{"class":1240},"  typescript",[1223,16791,1765],{"class":1236},[1223,16793,1891],{"class":1236},[1223,16795,16796,16799,16801],{"class":1225,"line":1263},[1223,16797,16798],{"class":1240},"    tsConfig",[1223,16800,1765],{"class":1236},[1223,16802,1891],{"class":1236},[1223,16804,16805,16808,16810],{"class":1225,"line":1296},[1223,16806,16807],{"class":1240},"      compilerOptions",[1223,16809,1765],{"class":1236},[1223,16811,1891],{"class":1236},[1223,16813,16814,16817,16819],{"class":1225,"line":1325},[1223,16815,16816],{"class":1240},"        verbatimModuleSyntax",[1223,16818,1765],{"class":1236},[1223,16820,10665],{"class":2928},[1223,16822,16823],{"class":1225,"line":1355},[1223,16824,1978],{"class":1236},[1223,16826,16827],{"class":1225,"line":1771},[1223,16828,1984],{"class":1236},[1223,16830,16831],{"class":1225,"line":1783},[1223,16832,1990],{"class":1236},[1223,16834,16835,16837],{"class":1225,"line":1792},[1223,16836,1801],{"class":1236},[1223,16838,1804],{"class":1285},[1143,16840,16841],{},"However, we'd recommend only doing that temporarily, as Vue does need this option to be set for best results.",[1147,16843,3580],{"id":3579},[1143,16845,3583],{},[1213,16847,16848],{"className":3586,"code":14897,"language":3588,"meta":1218,"style":1218},[1220,16849,16850],{"__ignoreMap":1218},[1223,16851,16852,16854,16856],{"class":1225,"line":1226},[1223,16853,2037],{"class":2036},[1223,16855,4554],{"class":1254},[1223,16857,14908],{"class":1254},[1147,16859,4938],{"id":3608},[3611,16861,16863],{"to":16862,"icon":3614,"color":3613},"https://github.com/nuxt/nuxt/releases/tag/v3.8.0",[1143,16864,3619,16865,2281],{},[1220,16866,16867],{},"v3.8.0",[1143,16869,11586],{},[1143,16871,16872],{},[1159,16873,4631],{},[2160,16875,16876],{},"html pre.shiki code .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}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 .svXlt, html code.shiki .svXlt{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .sagxc, html code.shiki .sagxc{--shiki-light:#FF5370;--shiki-default:#FF5370;--shiki-dark:#FF9CAC}html pre.shiki code .ssYd4, html code.shiki .ssYd4{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sV9sa, html code.shiki .sV9sa{--shiki-light:#F76D47;--shiki-default:#F76D47;--shiki-dark:#F78C6C}html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}",{"title":1218,"searchDepth":1233,"depth":1233,"links":16878},[16879,16880,16881,16882,16883,16884,16885,16886,16887,16888,16889,16890,16891,16892],{"id":15626,"depth":1263,"text":15627},{"id":15661,"depth":1263,"text":15662},{"id":15673,"depth":1263,"text":15674},{"id":15730,"depth":1263,"text":15731},{"id":15801,"depth":1263,"text":15802},{"id":15996,"depth":1263,"text":15997},{"id":16121,"depth":1263,"text":16122},{"id":16247,"depth":1263,"text":16248},{"id":16561,"depth":1263,"text":16562},{"id":16619,"depth":1263,"text":16620},{"id":16673,"depth":1263,"text":16674},{"id":16705,"depth":1263,"text":16706},{"id":3579,"depth":1233,"text":3580},{"id":3608,"depth":1233,"text":4938},"2023-10-19","Nuxt 3.8 is out, bringing built-in DevTools, automatic Nuxt Image install, a new app manifest and much more.","/assets/blog/v3.8.png",{},{"title":15618,"description":16894},"blog/17.v3-8","mEdPNjDByj",{"id":16901,"title":16902,"authors":16903,"body":16908,"category":7880,"date":17319,"description":17320,"draft":108,"extension":1954,"image":17321,"meta":17322,"navigation":108,"path":17323,"seo":17324,"stem":17325,"tags":6,"__hash__":17326},"blog/blog/16.new-website.md","A New Website",[16904,16906],{"name":1130,"avatar":16905,"to":1133,"twitter":7721},{"src":1132},{"name":1125,"avatar":16907,"to":1128},{"src":1127},{"type":1140,"value":16909,"toc":17309},[16910,16917,16921,16931,16940,16953,16956,16999,17005,17009,17012,17025,17028,17041,17045,17067,17074,17082,17086,17102,17105,17119,17122,17135,17139,17157,17165,17180,17191,17211,17218,17222,17225,17231,17238,17245,17249,17256,17265,17268,17271,17291,17306],[1143,16911,16912,16913,16916],{},"Nuxt.com is the main entry point when you want to learn Nuxt. With ",[1159,16914,16915],{},"more than 300k visitors every month",", it was time to give it a new look and feel.",[1147,16918,16920],{"id":16919},"new-design","New Design",[1143,16922,16923,16924,16927,16928,3681],{},"We are back to the original colors of Nuxt, with a navy background (",[1220,16925,16926],{},"#020420",") and its signature shiny green (",[1220,16929,16930],{},"#00DC82",[16932,16933],"nuxt-img",{"alt":16934,"className":16935,"height":16937,"src":16938,"width":16939},"Nuxt Website Screenshot",[2250,2247,16936],"border-gray-700",497,"/assets/blog/website/nuxt-website.png",832,[3611,16941,16943],{"to":16942,"icon":47},"/design-kit",[1143,16944,16945,16946,16949,16950,2281],{},"Discover the ",[1159,16947,16948],{},"Nuxt Design Kit"," as well as our ",[1159,16951,16952],{},"Logo History",[1143,16954,16955],{},"We wanted to achieve a consistent design across all our official documentations:",[1241,16957,16962,16976,16984,16992],{"className":16958},[16959,16960,16961],"grid","sm:grid-cols-2","gap-4",[16963,16964,16967],"nuxt-link",{"className":16965,"target":3615,"to":9966},[16966],"hover:border-transparent",[16932,16968],{"alt":16969,"className":16970,"height":16973,"src":16974,"width":16975},"Nuxt Image",[16971,2247,16972,16936],"m-0","rounded-md",255,"/assets/blog/website/nuxt-image.png",408,[16963,16977,16980],{"className":16978,"target":3615,"to":16979},[16966],"https://content.nuxt.com",[16932,16981],{"alt":4387,"className":16982,"height":16973,"src":16983,"width":16975},[16971,2247,16972,16936],"/assets/blog/website/nuxt-content.png",[16963,16985,16988],{"className":16986,"target":3615,"to":16987},[16966],"https://devtools.nuxt.com",[16932,16989],{"alt":9560,"className":16990,"height":16973,"src":16991,"width":16975},[16971,2247,16972,16936],"/assets/blog/website/nuxt-devtools.png",[16963,16993,16995],{"className":16994,"target":3615,"to":10021},[16966],[16932,16996],{"alt":10023,"className":16997,"height":16973,"src":16998,"width":16975},[16971,2247,16972,16936],"/assets/blog/website/nuxt-ui.png",[1143,17000,17001,17002],{},"We really love this new design and hope you do too. ",[1159,17003,17004],{},"This is only the first step toward many improvements coming to the website.",[1147,17006,17008],{"id":17007},"improved-navigation","Improved Navigation",[1143,17010,17011],{},"From now on, you can easily jump between the five main documentation categories:",[7119,17013,17016,17019,17022],{":controls":9655,"className":17014,"controls":1739,"poster":17015},[15701,15702,2249],"https://res.cloudinary.com/nuxt/video/upload/v1697548111/nuxt3/nuxt-website-docs-nav.jpg",[15705,17017],{"src":17018,"type":15708},"https://res.cloudinary.com/nuxt/video/upload/v1697548111/nuxt3/nuxt-website-docs-nav.webm",[15705,17020],{"src":17021,"type":15712},"https://res.cloudinary.com/nuxt/video/upload/v1697548111/nuxt3/nuxt-website-docs-nav.mp4",[15705,17023],{"src":17024,"type":15716},"https://res.cloudinary.com/nuxt/video/upload/v1697548111/nuxt3/nuxt-website-docs-nav.ogg",[1143,17026,17027],{},"On the right side, you can see the table of contents as well as community shortcuts: Edit this page, Chat on Discord, etc.",[7119,17029,17032,17035,17038],{":controls":9655,"className":17030,"controls":1739,"poster":17031},[15701,15702,2249],"https://res.cloudinary.com/nuxt/video/upload/v1697549697/nuxt3/nuxt-website-docs-aside.jpg",[15705,17033],{"src":17034,"type":15708},"https://res.cloudinary.com/nuxt/video/upload/v1697549697/nuxt3/nuxt-website-docs-aside.webm",[15705,17036],{"src":17037,"type":15712},"https://res.cloudinary.com/nuxt/video/upload/v1697549697/nuxt3/nuxt-website-docs-aside.mp4",[15705,17039],{"src":17040,"type":15716},"https://res.cloudinary.com/nuxt/video/upload/v1697549697/nuxt3/nuxt-website-docs-aside.ogg",[1147,17042,17044],{"id":17043},"source-code-buttons","Source Code Buttons",[1143,17046,17047,17048,5062,17050,5062,17052,5062,17054,4363,17057,17060,17061,17066],{},"When looking at Nuxt built-in ",[2006,17049,179],{"href":356},[2006,17051,183],{"href":420},[2006,17053,227],{"href":543},[2006,17055,17056],{"href":658},"commands",[2006,17058,17059],{"href":724},"kit utilities",", you can now jump to the source code by clicking on the ",[17062,17063,17065],"u-button",{"color":3613,"icon":3614,"size":17064},"xs","Source"," button.",[16932,17068],{"alt":17069,"className":17070,"height":17071,"src":17072,"width":17073},"Nuxt Source Code Button",[2247,15701,16936],343,"/assets/blog/website/nuxt-website-source-button.png",818,[3611,17075,17076],{"to":394},[1143,17077,17078,17079,17081],{},"Checkout an example on ",[1220,17080,393],{}," documentation page.",[1147,17083,17085],{"id":17084},"improved-search-feature","Improved Search Feature",[1143,17087,17088,17089,17093,17094,17101],{},"You may notice a new modal when hitting ",[17090,17091,17092],"kbd",{},"CMD+K",". We leverage the Nuxt UI ",[2006,17095,17098],{"href":17096,"rel":17097},"https://ui.nuxt.com/navigation/command-palette",[2010],[1220,17099,17100],{},"\u003CCommandPalette>"," components combined with Nuxt Content data (search & navigation) to provide a better search experience.",[1143,17103,17104],{},"With the command palette, you can:",[1852,17106,17107,17110,17113,17116],{},[1855,17108,17109],{},"Jump to a page",[1855,17111,17112],{},"Search in the documentation",[1855,17114,17115],{},"Search a module",[1855,17117,17118],{},"Switch the color mode",[1143,17120,17121],{},"We plan to add more commands soon.",[7119,17123,17126,17129,17132],{":controls":9655,"className":17124,"controls":1739,"poster":17125},[15701,15702,2249],"https://res.cloudinary.com/nuxt/video/upload/v1697550571/nuxt3/nuxt-website-search.jpg",[15705,17127],{"src":17128,"type":15708},"https://res.cloudinary.com/nuxt/video/upload/v1697550571/nuxt3/nuxt-website-search.webm",[15705,17130],{"src":17131,"type":15712},"https://res.cloudinary.com/nuxt/video/upload/v1697550571/nuxt3/nuxt-website-search.mp4",[15705,17133],{"src":17134,"type":15716},"https://res.cloudinary.com/nuxt/video/upload/v1697550571/nuxt3/nuxt-website-search.ogg",[1147,17136,17138],{"id":17137},"migration-to-nuxt-ui","Migration to Nuxt UI",[1143,17140,17141,17142,17145,17146,17151,17152,2281],{},"The new website is powered by ",[2006,17143,10023],{"href":10021,"rel":17144},[2010],", our UI library tailored made for Nuxt and built on top of ",[2006,17147,17150],{"href":17148,"rel":17149},"https://tailwindcss.com",[2010],"Tailwind CSS"," & ",[2006,17153,17156],{"href":17154,"rel":17155},"https://headlessui.com/",[2010],"Headless UI",[1143,17158,17159,17160,17164],{},"The website also uses ",[2006,17161,10203],{"href":17162,"rel":17163},"https://ui.nuxt.com/pro",[2010],", a set of premium components built on top of Nuxt UI to create beautiful & responsive Nuxt applications in minutes.",[1143,17166,17167,17168,5062,17171,5062,17174,5062,17177,10010],{},"It includes components such as ",[1220,17169,17170],{},"\u003CUHeader>",[1220,17172,17173],{},"\u003CUFooter>",[1220,17175,17176],{},"\u003CULandingHero>",[1220,17178,17179],{},"\u003CULandingCard>",[7747,17181,17182],{},[1143,17183,17184,17185,17190],{},"We plan to launch the full documentation of Nuxt UI Pro at the end of October. If you cannot wait and want early access, you can already ",[2006,17186,17189],{"href":17187,"rel":17188},"https://ui.nuxt.com/pro/purchase",[2010],"purchase a license"," now and get access to our private repository on GitHub.",[1143,17192,17193,17194,17198,17199,17204,17205,17210],{},"This ",[2006,17195,2011],{"href":17196,"rel":17197},"https://github.com/nuxt/nuxt.com/pull/1365",[2010]," was a great opportunity to improve Nuxt UI & UI Pro and fix some bugs, as well as a difference of ",[1223,17200,17203],{"className":17201},[17202],"text-green-500","+9,004"," / ",[1223,17206,17209],{"className":17207},[17208],"text-red-500","-23,113"," lines of code changed.",[3611,17212,17214],{"to":10021,"icon":17213,"target":3615},"i-simple-icons-nuxtdotjs",[1143,17215,15795,17216,2281],{},[1159,17217,10023],{},[1147,17219,17221],{"id":17220},"open-graph-images","Open Graph Images",[1143,17223,17224],{},"We are big fans of having a custom image when we share a link on social media. That's why we have added OG images on all our documentation pages.",[1143,17226,17227,17228,1765],{},"Example of the ",[2006,17229,17230],{"href":25},"Installation page",[2243,17232],{"alt":17233,"className":17234,"height":17235,"src":17236,"width":17237},"Nuxt OG Image",[2247,15701,16936],630,"/__og-image__/image/docs/getting-started/introduction/og.png",1200,[3611,17239,17241],{"to":17240,"target":3615},"https://nuxtseo.com/og-image/getting-started/installation",[1143,17242,16945,17243,7989],{},[1159,17244,17233],{},[1147,17246,17248],{"id":17247},"available-on-github","Available on GitHub",[1143,17250,17251,17252,17255],{},"We are proud to announce that the website is ",[1159,17253,17254],{},"now open source"," and available on GitHub.",[3611,17257,17258],{"to":2571,"icon":3614,"target":3615,"color":3613},[1143,17259,17260,17261,17264],{},"Check out ",[1220,17262,17263],{},"nuxt/nuxt.com"," on GitHub.",[1147,17266,17267],{"id":7754},"What's next?",[1143,17269,17270],{},"This new website is the beginning of upcoming changes we are planing, some of them are:",[1852,17272,17273,17276,17279,17288],{},[1855,17274,17275],{},"Team & Contributors pages",[1855,17277,17278],{},"Integrations page to showcase all the possibilities with Nuxt: Hosting, CMS, Database, etc.",[1855,17280,17281,17282,17287],{},"Templates page (currently ",[2006,17283,17286],{"href":17284,"rel":17285},"https://nuxt.new",[2010],"nuxt.new",") to list official and community starters",[1855,17289,17290],{},"And more...",[1143,17292,17293,2281],{},[1159,17294,17295,17296,5062,17299,6381,17303],{},"We are looking forward to your feedback on ",[2006,17297,10291],{"href":10289,"rel":17298},[2010],[2006,17300,9951],{"href":17301,"rel":17302},"https://discord.com/invite/nuxt",[2010],[2006,17304,10296],{"href":2571,"rel":17305},[2010],[1143,17307,17308],{},"Thank you for reading this blog post, and happy Nuxting 🤟",{"title":1218,"searchDepth":1233,"depth":1233,"links":17310},[17311,17312,17313,17314,17315,17316,17317,17318],{"id":16919,"depth":1233,"text":16920},{"id":17007,"depth":1233,"text":17008},{"id":17043,"depth":1233,"text":17044},{"id":17084,"depth":1233,"text":17085},{"id":17137,"depth":1233,"text":17138},{"id":17220,"depth":1233,"text":17221},{"id":17247,"depth":1233,"text":17248},{"id":7754,"depth":1233,"text":17267},"2023-10-18","We are thrilled to release the new nuxt.com, powered by Nuxt UI and now open source.","/assets/blog/new-website.png",{},"/blog/new-website",{"title":16902,"description":17320},"blog/16.new-website","zRyoXNjZof",{"id":17328,"title":17329,"authors":17330,"body":17333,"category":2176,"date":17893,"description":17894,"draft":108,"extension":1954,"image":17895,"meta":17896,"navigation":108,"path":17897,"seo":17898,"stem":17899,"tags":6,"__hash__":17900},"blog/blog/15.v3-7.md","Nuxt 3.7",[17331],{"name":2190,"avatar":17332,"to":2193},{"src":2192},{"type":1140,"value":17334,"toc":17879},[17335,17339,17355,17377,17383,17390,17410,17421,17425,17456,17476,17520,17528,17532,17560,17562,17687,17691,17694,17703,17707,17722,17730,17744,17748,17756,17767,17772,17814,17818,17821,17825,17832,17840,17842,17844,17858,17865,17869,17876],[1155,17336,17338],{"id":17337},"a-new-cli","🐣 A New CLI",[1143,17340,17341,17342,5754,17344,17349,17350,17354],{},"We've refactored ",[1220,17343,11566],{},[2006,17345,17348],{"href":17346,"rel":17347},"http://github.com/unjs/citty",[2010],"unjs/citty"," and this marks the first Nuxt release that depends on the new version, safely in its own repository. We have grand plans for this - check out some of the features + roadmap discussions in ",[2006,17351,17353],{"href":15633,"rel":17352},[2010],"nuxt/cli"," and please feel free to contribute!",[1852,17356,17357,17365,17371],{},[1855,17358,17359],{},[2006,17360,17362],{"href":17361,"target":3615},"https://github.com/nuxt/cli/discussions/3",[1159,17363,17364],{},"Project Goals",[1855,17366,17367],{},[2006,17368,17370],{"href":17369,"target":3615},"https://github.com/nuxt/cli/discussions/4","Feedbacks and Ideas",[1855,17372,17373],{},[2006,17374,17376],{"href":17375,"target":3615},"https://github.com/nuxt/cli/discussions/7","The journey of Nuxt CLI Generations",[1143,17378,17379,17380,17382],{},"Nuxi is now decoupled from the main ",[1220,17381,2367],{}," version - we plan to iterate and release nuxi more quickly in future so you can expect new things coming soon!",[1155,17384,17386,17387],{"id":17385},"️-native-web-streams-and-response","🕸️ Native Web Streams and ",[1220,17388,17389],{},"Response",[1143,17391,17392,17393,4363,17398,17403,17404,17406,17407,17409],{},"With improvements in ",[2006,17394,17397],{"href":17395,"rel":17396},"https://github.com/unjs/h3",[2010],"unjs/h3",[2006,17399,17402],{"href":17400,"rel":17401},"https://github.com/unjs/nitro",[2010],"unjs/nitro",", it's now possible to directly return a ",[1220,17405,17389],{}," object from server routes, meaning it's ",[3746,17408,10238],{}," possible to return and handle streams natively in Nuxt.",[1143,17411,17412,17413,4363,17417,15658],{},"👉 Check out the full detail in the ",[2006,17414,17397],{"href":17415,"rel":17416},"https://github.com/unjs/h3/releases",[2010],[2006,17418,17402],{"href":17419,"rel":17420},"https://github.com/unjs/nitro/releases",[2010],[1155,17422,17424],{"id":17423},"html-rendering-optimisations","🔥 HTML Rendering Optimisations",[1143,17426,17427,17428,17431,17432,3114,17434,17439,17440,17443,17444,5062,17447,5062,17450,5062,17452,17455],{},"This release comes with a couple of improvements in rendering HTML responses from the server. We now determine whether to preload/prefetch resources at build time (so you can customise this in the ",[1220,17429,17430],{},"build:manifest"," hook). We also now manage rendering the HTML for them directly in ",[1220,17433,2291],{},[2006,17435,17438],{"href":17436,"rel":17437},"https://github.com/nuxt/nuxt/pull/22179",[2010],"#22179","), which means you can configure the ",[3746,17441,17442],{},"order"," for ",[1220,17445,17446],{},"\u003Clink>",[1220,17448,17449],{},"\u003Cmeta>",[1220,17451,6466],{},[1220,17453,17454],{},"\u003Cstyle>",", and more. And - in our preliminary testing - it's even faster!",[1143,17457,17458,17459,17462,17463,3114,17468,17473,17474,1765],{},"It's possible to opt-in to upcoming head improvements with the ",[1220,17460,17461],{},"experimental.headNext"," flag. This currently includes a new ordering algorithm based on ",[2006,17464,17467],{"href":17465,"rel":17466},"https://github.com/rviscomi/capo.js",[2010],"capo.js",[2006,17469,17472],{"href":17470,"rel":17471},"https://github.com/nuxt/nuxt/pull/22431",[2010],"#22431",") and allows enabling future optimisations as they are released in ",[1220,17475,2291],{},[1213,17477,17479],{"className":1669,"code":17478,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  experimental: {\n    headNext: true\n  }\n})\n",[1220,17480,17481,17493,17501,17510,17514],{"__ignoreMap":1218},[1223,17482,17483,17485,17487,17489,17491],{"class":1225,"line":1226},[1223,17484,1745],{"class":1679},[1223,17486,1748],{"class":1679},[1223,17488,2820],{"class":1751},[1223,17490,1754],{"class":1285},[1223,17492,1757],{"class":1236},[1223,17494,17495,17497,17499],{"class":1225,"line":1233},[1223,17496,3074],{"class":1240},[1223,17498,1765],{"class":1236},[1223,17500,1891],{"class":1236},[1223,17502,17503,17506,17508],{"class":1225,"line":1263},[1223,17504,17505],{"class":1240},"    headNext",[1223,17507,1765],{"class":1236},[1223,17509,3088],{"class":2928},[1223,17511,17512],{"class":1225,"line":1296},[1223,17513,1990],{"class":1236},[1223,17515,17516,17518],{"class":1225,"line":1325},[1223,17517,1801],{"class":1236},[1223,17519,1804],{"class":1285},[1143,17521,17522,17523,2281],{},"We'd love your thoughts - you can respond with any issues/feedback in ",[2006,17524,17527],{"href":17525,"rel":17526},"https://github.com/nuxt/nuxt/discussions/22632",[2010],"this discussion",[1155,17529,17531],{"id":17530},"️-build-environment-shortcuts","🛠️ Build Environment Shortcuts",[1143,17533,17534,17535,4363,17538,17541,17542,17547,17548,17553,17554,4363,17556,17559],{},"In your Nuxt config you can now use ",[1220,17536,17537],{},"$client",[1220,17539,17540],{},"$server"," shortcuts to easily define configuration that is specific to just the Vite client/server (",[2006,17543,17546],{"href":17544,"rel":17545},"https://github.com/nuxt/nuxt/pull/22302",[2010],"#22302",") or webpack client/server (",[2006,17549,17552],{"href":17550,"rel":17551},"https://github.com/nuxt/nuxt/pull/22304",[2010],"#22304",") builds. This previously was only possible with the ",[1220,17555,14629],{},[1220,17557,17558],{},"webpack:config"," hooks.",[1143,17561,4993],{},[1213,17563,17565],{"className":1669,"code":17564,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  vite: {\n    $client: {\n      build: {\n        rollupOptions: {\n          output: {\n            chunkFileNames: '_nuxt/[hash].js',\n            assetFileNames: '_nuxt/[hash][extname]',\n            entryFileNames: '_nuxt/[hash].js'\n          }\n        }\n      }\n    }\n  }\n})\n",[1220,17566,17567,17579,17587,17595,17603,17611,17619,17633,17649,17661,17665,17669,17673,17677,17681],{"__ignoreMap":1218},[1223,17568,17569,17571,17573,17575,17577],{"class":1225,"line":1226},[1223,17570,1745],{"class":1679},[1223,17572,1748],{"class":1679},[1223,17574,2820],{"class":1751},[1223,17576,1754],{"class":1285},[1223,17578,1757],{"class":1236},[1223,17580,17581,17583,17585],{"class":1225,"line":1233},[1223,17582,11419],{"class":1240},[1223,17584,1765],{"class":1236},[1223,17586,1891],{"class":1236},[1223,17588,17589,17591,17593],{"class":1225,"line":1263},[1223,17590,11428],{"class":1240},[1223,17592,1765],{"class":1236},[1223,17594,1891],{"class":1236},[1223,17596,17597,17599,17601],{"class":1225,"line":1296},[1223,17598,11437],{"class":1240},[1223,17600,1765],{"class":1236},[1223,17602,1891],{"class":1236},[1223,17604,17605,17607,17609],{"class":1225,"line":1325},[1223,17606,11446],{"class":1240},[1223,17608,1765],{"class":1236},[1223,17610,1891],{"class":1236},[1223,17612,17613,17615,17617],{"class":1225,"line":1355},[1223,17614,11455],{"class":1240},[1223,17616,1765],{"class":1236},[1223,17618,1891],{"class":1236},[1223,17620,17621,17623,17625,17627,17629,17631],{"class":1225,"line":1771},[1223,17622,11464],{"class":1240},[1223,17624,1765],{"class":1236},[1223,17626,1695],{"class":1236},[1223,17628,11388],{"class":1254},[1223,17630,1957],{"class":1236},[1223,17632,1780],{"class":1236},[1223,17634,17635,17638,17640,17642,17645,17647],{"class":1225,"line":1783},[1223,17636,17637],{"class":1240},"            assetFileNames",[1223,17639,1765],{"class":1236},[1223,17641,1695],{"class":1236},[1223,17643,17644],{"class":1254},"_nuxt/[hash][extname]",[1223,17646,1957],{"class":1236},[1223,17648,1780],{"class":1236},[1223,17650,17651,17653,17655,17657,17659],{"class":1225,"line":1792},[1223,17652,11479],{"class":1240},[1223,17654,1765],{"class":1236},[1223,17656,1695],{"class":1236},[1223,17658,11388],{"class":1254},[1223,17660,1701],{"class":1236},[1223,17662,17663],{"class":1225,"line":1798},[1223,17664,3480],{"class":1236},[1223,17666,17667],{"class":1225,"line":1975},[1223,17668,3485],{"class":1236},[1223,17670,17671],{"class":1225,"line":1981},[1223,17672,1978],{"class":1236},[1223,17674,17675],{"class":1225,"line":1987},[1223,17676,1984],{"class":1236},[1223,17678,17679],{"class":1225,"line":1993},[1223,17680,1990],{"class":1236},[1223,17682,17683,17685],{"class":1225,"line":2720},[1223,17684,1801],{"class":1236},[1223,17686,1804],{"class":1285},[1155,17688,17690],{"id":17689},"️-vite-44","⚡️ Vite 4.4",[1143,17692,17693],{},"We've chosen to unpin Vite from minor versions, meaning whenever Vite releases a new feature version you can opt-in straight away. Vite 4.4 brings a lot of exciting things, including experimental Lightning CSS support - and much more!",[1143,17695,17696,17697,17702],{},"👉 Check out the ",[2006,17698,17701],{"href":17699,"rel":17700},"https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#440-2023-07-06",[2010],"Vite release notes"," for more.",[1155,17704,17706],{"id":17705},"typescript-updates","💪 TypeScript Updates",[1143,17708,17709,17710,17712,17713,17716,17717,3681],{},"We now use purely relative paths in the generated ",[1220,17711,268],{}," instead of setting a ",[1220,17714,17715],{},"baseUrl",". This means better support for dev environments like docker images where the absolute path may not match your IDE (",[2006,17718,17721],{"href":17719,"rel":17720},"https://github.com/nuxt/nuxt/pull/22410",[2010],"#22410",[1143,17723,17724,17725,3681],{},"We also set a couple of additional compiler flag defaults to match Vite/TS recommendations (",[2006,17726,17729],{"href":17727,"rel":17728},"https://github.com/nuxt/nuxt/pull/22468",[2010],"#22468",[1143,17731,17732,17733,17735,17736,3114,17739,3681],{},"Plus, you should now get type hinted access to layouts in ",[1220,17734,639],{}," and also in ",[1220,17737,17738],{},"\u003CNuxtLayout name>",[2006,17740,17743],{"href":17741,"rel":17742},"https://github.com/nuxt/nuxt/pull/22362",[2010],"#22363",[1155,17745,17747],{"id":17746},"async-context-support","🦄 Async Context support",[1143,17749,17750,17751,3681],{},"If you've ever got an issue with 'Nuxt context unavailable' this might be one for you. We now support  native async context for Bun and Node under an experimental flag, in both Nuxt and Nitro (",[2006,17752,17755],{"href":17753,"rel":17754},"https://github.com/nuxt/nuxt/pull/20918",[2010],"#20918",[1143,17757,17758,17759,17762,17763,17766],{},"This enables using Nuxt composables on the server ",[3746,17760,17761],{},"without"," needing to ensure they are being called directly in a setup function. It also allows the same in Nitro, with a new ",[1220,17764,17765],{},"useEvent()"," utility that is usable in server routes.",[1143,17768,17769,17770,1765],{},"To try it out, you can enable ",[1220,17771,16062],{},[1213,17773,17774],{"className":1669,"code":16072,"language":1672,"meta":1218,"style":1218},[1220,17775,17776,17788,17796,17804,17808],{"__ignoreMap":1218},[1223,17777,17778,17780,17782,17784,17786],{"class":1225,"line":1226},[1223,17779,1745],{"class":1679},[1223,17781,1748],{"class":1679},[1223,17783,2820],{"class":1751},[1223,17785,1754],{"class":1285},[1223,17787,1757],{"class":1236},[1223,17789,17790,17792,17794],{"class":1225,"line":1233},[1223,17791,3074],{"class":1240},[1223,17793,1765],{"class":1236},[1223,17795,1891],{"class":1236},[1223,17797,17798,17800,17802],{"class":1225,"line":1263},[1223,17799,16099],{"class":1240},[1223,17801,1765],{"class":1236},[1223,17803,3088],{"class":2928},[1223,17805,17806],{"class":1225,"line":1296},[1223,17807,1990],{"class":1236},[1223,17809,17810,17812],{"class":1225,"line":1325},[1223,17811,1801],{"class":1236},[1223,17813,1804],{"class":1285},[1155,17815,17817],{"id":17816},"watcher-updates","👓 Watcher Updates",[1143,17819,17820],{},"We've fixed a couple of issues with watchers, meaning that you should need to restart your server less often - and you should see a significant performance increase if you are using layers.",[1155,17822,17824],{"id":17823},"️-nitro-26","⚗️ Nitro 2.6",[1143,17826,17827,17828,17831],{},"There lots more exciting features coming directly from Nitro 2.6, including smaller, lighter servers and new persistent data storage in a ",[1220,17829,17830],{},".data"," directory.",[1143,17833,17834,17835,2281],{},"👉 Read more in ",[2006,17836,17839],{"href":17837,"rel":17838},"https://unjs.io/blog/2023-08-25-nitro-2.6",[2010],"the full release article",[1147,17841,3580],{"id":3579},[1143,17843,3583],{},[1213,17845,17846],{"className":3586,"code":14202,"language":3588,"meta":1218,"style":1218},[1220,17847,17848],{"__ignoreMap":1218},[1223,17849,17850,17852,17854,17856],{"class":1225,"line":1226},[1223,17851,2037],{"class":2036},[1223,17853,4554],{"class":1254},[1223,17855,3599],{"class":1254},[1223,17857,4019],{"class":1254},[1143,17859,17860,17861,17864],{},"This will refresh your lockfile as well, and ensures that you pull in updates from other dependencies that Nuxt relies on, particularly in the ",[2006,17862,3540],{"href":12553,"rel":17863},[2010]," ecosystem.",[1147,17866,17868],{"id":17867},"full-changelog","📃 Full changelog",[1143,17870,17871,17872],{},"Read the full release notes on ",[2006,17873,17874],{"href":17874,"rel":17875},"https://github.com/nuxt/nuxt/releases/tag/v3.7.0",[2010],[2160,17877,17878],{},"html pre.shiki code .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .sagxc, html code.shiki .sagxc{--shiki-light:#FF5370;--shiki-default:#FF5370;--shiki-dark:#FF9CAC}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 .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}",{"title":1218,"searchDepth":1233,"depth":1233,"links":17880},[17881,17882,17884,17885,17886,17887,17888,17889,17890,17891,17892],{"id":17337,"depth":1263,"text":17338},{"id":17385,"depth":1263,"text":17883},"🕸️ Native Web Streams and Response",{"id":17423,"depth":1263,"text":17424},{"id":17530,"depth":1263,"text":17531},{"id":17689,"depth":1263,"text":17690},{"id":17705,"depth":1263,"text":17706},{"id":17746,"depth":1263,"text":17747},{"id":17816,"depth":1263,"text":17817},{"id":17823,"depth":1263,"text":17824},{"id":3579,"depth":1233,"text":3580},{"id":17867,"depth":1233,"text":17868},"2023-08-25","Nuxt 3.7 is out, bringing a new CLI, native web streams and response, rendering optimisations, async context support - and much more.","/assets/blog/v3.7.png",{},"/blog/v3-7",{"title":17329,"description":17894},"blog/15.v3-7","pMOJpuyaMV",{"id":17902,"title":1044,"authors":17903,"body":17906,"category":9834,"date":18343,"description":18344,"draft":108,"extension":1954,"image":18345,"meta":18346,"navigation":1739,"path":1045,"seo":18347,"stem":1046,"tags":6,"__hash__":18348},"blog/blog/14.nuxt-on-the-edge.md",[17904],{"name":1130,"avatar":17905,"to":1133,"twitter":7721},{"src":1132},{"type":1140,"value":17907,"toc":18337},[17908,17911,17926,17929,17935,17944,17957,17961,17964,17978,17981,17984,17988,17994,17997,18024,18033,18038,18041,18078,18089,18093,18100,18110,18167,18170,18256,18267,18273,18302,18316,18318,18321,18334],[1147,17909,19],{"id":17910},"introduction",[1143,17912,17913,17914,17919,17920,17925],{},"In September 2017, Cloudflare ",[2006,17915,17918],{"href":17916,"rel":17917},"https://blog.cloudflare.com/introducing-cloudflare-workers/",[2010],"introduced Cloudflare Workers",", giving the ability to run JavaScript on their ",[2006,17921,17924],{"href":17922,"rel":17923},"https://www.cloudflare.com/network/",[2010],"edge network",". This means your code will deploy on the entire edge network in over a hundred locations worldwide in about 30 seconds. This technology allows you to focus on writing your application close to your users, wherever they are in the world (~50ms latency).",[1143,17927,17928],{},"The worker's runtime is not the same as Node.js or the Browser, it executes the code using V8, the JavaScript engine developed by Google Chrome. Until now, what you could run on their platform were small scripts running on the edge before hitting your server to increase the performance or add some logic based on request headers, for example.",[1143,17930,17931,17932,2281],{},"In November 2020, while working on Nuxt 3, ",[1159,17933,17934],{},"we made the bet to run Nuxt in-production on edge runtimes / V8 isolates",[1143,17936,17937,17938,17943],{},"It unlocks the ability to server-render pages in ~50ms from all over the world when using a platform like CloudFlare Workers, without having to deal with servers, load balancers and caching, for about ",[2006,17939,17942],{"href":17940,"rel":17941},"https://developers.cloudflare.com/workers/platform/pricing/",[2010],"$0.3 per million requests",". As of today, new platforms are coming to let run apps on V8 isolates such as Deno Deploy.",[1588,17945,17946],{},[1143,17947,17948,17951,17952,17956],{},[1159,17949,17950],{},"2024 update:"," I released ",[2006,17953,10215],{"href":17954,"rel":17955},"https://hub.nuxt.com",[2010]," to let you build full-stack applications with Nuxt on the edge, on your Cloudflare account with zero configuration. It includes a database, blob storage, KV, remote storage and more.",[1147,17958,17960],{"id":17959},"the-challenge","The Challenge",[1143,17962,17963],{},"In order to make Nuxt run in workers, we had to rewrite some parts of Nuxt to be environmentally agnostic (runs in Node.js, Browser or V8).",[1143,17965,17966,17967,17971,17972,17977],{},"We started with our server and created ",[2006,17968,17397],{"href":17969,"rel":17970},"http://github.com/unjs/h3",[2010],": a minimal http framework built for high performance and portability. It replaces ",[2006,17973,17976],{"href":17974,"rel":17975},"https://github.com/senchalabs/connect",[2010],"Connect"," we used in Nuxt 2 but has compatibility with it so you can keep using Connect/Express middleware. In the workers, for each incoming request, it starts Nuxt in production, sends the request to it and sends back the response.",[1143,17979,17980],{},"In Nuxt 2, the duration to start the server in production in memory (also named cold start) was about ~300ms, because we had to load all the dependencies of your server and application in order to handle the request.",[1143,17982,17983],{},"By working on h3, we decided to code-split each handler attached to the server and lazy-load them only when requested. When you start Nuxt 3, we only load h3 in memory and the corresponding handlers. When a request comes in, we load the handler corresponding to the route and execute it.",[7119,17985],{":controls":9655,"poster":17986,"src":17987},"https://res.cloudinary.com/nuxt/video/upload/v1689236511/nuxt3/nuxt3-server-performance.jpg","https://res.cloudinary.com/nuxt/video/upload/v1689236511/nuxt3/nuxt3-server-performance.mp4",[1143,17989,17990,17991,2281],{},"By adopting this approach, ",[1159,17992,17993],{},"we reduced the cold start from ~300ms to ~2ms",[1143,17995,17996],{},"We had another challenge in order to run Nuxt on the edge: the production bundle size. This includes the server, Vue app and Node.js dependencies combined. Cloudflare workers currently have a limit of 1MB (free plan) and 5MB ($5 per month plan) for the worker size.",[1143,17998,17999,18000,18004,18005,18008,18009,4363,18012,18017,18018,18020,18021],{},"In order to achieve this, we created ",[2006,18001,17402],{"href":18002,"rel":18003},"https://nitro.unjs.io/",[2010],", our server engine, when running the ",[1220,18006,18007],{},"nuxt build"," command, it bundles your whole project and includes all dependencies into the final output. It uses ",[2006,18010,12520],{"href":12518,"rel":18011},[2010],[2006,18013,18016],{"href":18014,"rel":18015},"https://github.com/vercel/nft",[2010],"vercel/nft"," to trace only the code used by the ",[1220,18019,203],{}," to remove unnecessary code. ",[1159,18022,18023],{},"The total size of the generated output for a basic Nuxt 3 application is about 700kB gzip.",[1143,18025,18026,18027,18032],{},"Lastly, to provide the same developer experience between development (Node.js) and production on Cloudflare (Edge runtime), we created ",[2006,18028,18031],{"href":18029,"rel":18030},"https://github.com/unjs/unenv",[2010],"unjs/unenv",": a library to convert JavaScript code to run everywhere (platform agnostic) by mocking or adding polyfills for known dependencies.",[1143,18034,18035],{},[1159,18036,18037],{},"At Nuxt, we believe that you should have the freedom to choose the hosting provider that fits you best.",[1143,18039,18040],{},"This is why you can deploy a Nuxt application with edge-side rendering on:",[1852,18042,18043,18048,18055,18062,18070],{},[1855,18044,18045],{},[2006,18046,10215],{"href":17954,"rel":18047},[2010],[1855,18049,18050],{},[2006,18051,18054],{"href":18052,"rel":18053},"https://nitro.unjs.io/deploy/providers/cloudflare#cloudflare-pages",[2010],"Cloudflare Page",[1855,18056,18057],{},[2006,18058,18061],{"href":18059,"rel":18060},"https://nitro.unjs.io/deploy/providers/deno-deploy",[2010],"Deno Deploy",[1855,18063,18064,18069],{},[2006,18065,18068],{"href":18066,"rel":18067},"https://nitro.unjs.io/deploy/providers/vercel#vercel-edge-functions",[2010],"Vercel Edge Functions"," (using CloudFlare Workers under the hood)",[1855,18071,18072,18077],{},[2006,18073,18076],{"href":18074,"rel":18075},"https://nitro.unjs.io/deploy/providers/netlify#netlify-edge-functions",[2010],"Netlify Edge Functions"," (using Deno under the hood)",[1143,18079,18080,18081,6381,18085,2281],{},"We also support many other deployment providers, including ",[2006,18082,18084],{"href":18083},"/docs/getting-started/deployment#static-hosting","static hosting",[2006,18086,18088],{"href":18087},"/docs/getting-started/deployment#nodejs-server","traditional Node.js serverless and server hosts",[1147,18090,18092],{"id":18091},"pushing-full-stack-capabilities","Pushing Full-stack Capabilities",[1143,18094,18095,18096,18099],{},"Now that we have Nuxt running on edge runtime, we can do more than render a Vue application. Thanks to the ",[2006,18097,18098],{"href":220},"server directory",", creating an API route is a TypeScript file away.",[1143,18101,18102,18103,18106,18107,7913],{},"To add the ",[1220,18104,18105],{},"/api/hello"," route, create a ",[1220,18108,18109],{},"server/api/hello.ts",[1213,18111,18113],{"className":1669,"code":18112,"filename":18109,"language":1672,"meta":1218,"style":1218},"export default defineEventHandler((event) => {\n  return {\n    hello: 'world'\n  }\n})\n",[1220,18114,18115,18137,18143,18157,18161],{"__ignoreMap":1218},[1223,18116,18117,18119,18121,18124,18126,18128,18131,18133,18135],{"class":1225,"line":1226},[1223,18118,1745],{"class":1679},[1223,18120,1748],{"class":1679},[1223,18122,18123],{"class":1751}," defineEventHandler",[1223,18125,1754],{"class":1285},[1223,18127,1754],{"class":1236},[1223,18129,18130],{"class":2329},"event",[1223,18132,2541],{"class":1236},[1223,18134,3125],{"class":1244},[1223,18136,1891],{"class":1236},[1223,18138,18139,18141],{"class":1225,"line":1233},[1223,18140,2374],{"class":1679},[1223,18142,1891],{"class":1236},[1223,18144,18145,18148,18150,18152,18155],{"class":1225,"line":1263},[1223,18146,18147],{"class":1240},"    hello",[1223,18149,1765],{"class":1236},[1223,18151,1695],{"class":1236},[1223,18153,18154],{"class":1254},"world",[1223,18156,1701],{"class":1236},[1223,18158,18159],{"class":1225,"line":1296},[1223,18160,1990],{"class":1236},[1223,18162,18163,18165],{"class":1225,"line":1325},[1223,18164,1801],{"class":1236},[1223,18166,1804],{"class":1285},[1143,18168,18169],{},"You can now universally call this API in your pages and components:",[1213,18171,18173],{"className":2595,"code":18172,"filename":5115,"language":2597,"meta":1218,"style":1218},"\u003Cscript setup>\nconst { data } = await useFetch('/api/hello')\n\u003C/script>\n\n\u003Ctemplate>\n  \u003Cpre>{{ data }}\u003C/pre>\n\u003C/template>\n",[1220,18174,18175,18185,18211,18219,18223,18231,18248],{"__ignoreMap":1218},[1223,18176,18177,18179,18181,18183],{"class":1225,"line":1226},[1223,18178,1237],{"class":1236},[1223,18180,5899],{"class":1240},[1223,18182,5902],{"class":1244},[1223,18184,1260],{"class":1236},[1223,18186,18187,18189,18191,18193,18195,18197,18199,18201,18203,18205,18207,18209],{"class":1225,"line":1233},[1223,18188,3214],{"class":1244},[1223,18190,1683],{"class":1236},[1223,18192,10505],{"class":1285},[1223,18194,1801],{"class":1236},[1223,18196,2339],{"class":1236},[1223,18198,10512],{"class":1679},[1223,18200,10971],{"class":1751},[1223,18202,1754],{"class":1285},[1223,18204,1957],{"class":1236},[1223,18206,18105],{"class":1254},[1223,18208,1957],{"class":1236},[1223,18210,1804],{"class":1285},[1223,18212,18213,18215,18217],{"class":1225,"line":1263},[1223,18214,1289],{"class":1236},[1223,18216,5899],{"class":1240},[1223,18218,1260],{"class":1236},[1223,18220,18221],{"class":1225,"line":1296},[1223,18222,1740],{"emptyLinePlaceholder":1739},[1223,18224,18225,18227,18229],{"class":1225,"line":1325},[1223,18226,1237],{"class":1236},[1223,18228,2606],{"class":1240},[1223,18230,1260],{"class":1236},[1223,18232,18233,18235,18237,18239,18242,18244,18246],{"class":1225,"line":1355},[1223,18234,1266],{"class":1236},[1223,18236,1213],{"class":1240},[1223,18238,1282],{"class":1236},[1223,18240,18241],{"class":1285},"{{ data }}",[1223,18243,1289],{"class":1236},[1223,18245,1213],{"class":1240},[1223,18247,1260],{"class":1236},[1223,18249,18250,18252,18254],{"class":1225,"line":1771},[1223,18251,1289],{"class":1236},[1223,18253,2606],{"class":1240},[1223,18255,1260],{"class":1236},[1143,18257,18258,18259,4363,18261,18263,18264,2281],{},"One important thing to note when we created ",[2006,18260,444],{"href":445},[2006,18262,547],{"href":548}," is that during server-side rendering, if you call your API routes, it will emulate the request and call the function code directly: ",[1159,18265,18266],{},"avoiding an HTTP request and reducing page’s rendering time",[1143,18268,18269,18270],{},"In terms of developer experience, you will notice that when creating server files, the Nuxt server keeps running without rebuilding the Vue app. ",[1159,18271,18272],{},"This is because Nuxt 3 supports Hot Module Replacement (HMR) when creating API and server routes.",[1143,18274,18275,18276,18281,18282,5062,18287,5062,18292,5062,18297,10010],{},"Furthermore, by leveraging Object Relational Mapping (ORM) like ",[2006,18277,18280],{"href":18278,"rel":18279},"https://orm.drizzle.team/",[2010],"drizzle-orm",", developers can connect Edge & Serverless databases such as ",[2006,18283,18286],{"href":18284,"rel":18285},"https://developers.cloudflare.com/d1/",[2010],"D1",[2006,18288,18291],{"href":18289,"rel":18290},"https://turso.tech/",[2010],"Turso",[2006,18293,18296],{"href":18294,"rel":18295},"https://neon.tech",[2010],"Neon",[2006,18298,18301],{"href":18299,"rel":18300},"https://planetscale.com/",[2010],"Planetscale",[1143,18303,18304,18305,18310,18311,2281],{},"I created ",[2006,18306,18309],{"href":18307,"rel":18308},"https://todos.nuxt.dev/",[2010],"Atidone",", an open source demo to showcase a full-stack application with authentication and a database running on the edge. The source code is available on GitHub under the MIT license at ",[2006,18312,18315],{"href":18313,"rel":18314},"https://github.com/atinux/atidone",[2010],"atinux/atidone",[1147,18317,15562],{"id":15561},[1143,18319,18320],{},"We are excited about edge-side rendering and what it unlocks. Our team at Nuxt can’t wait to see what you will build on top of this!",[1143,18322,18323,18324,18328,18329,18333],{},"Feel free to join our ",[2006,18325,18327],{"href":17301,"rel":18326},[2010],"Discord server"," or mention ",[2006,18330,18332],{"href":10289,"rel":18331},[2010],"@nuxt_js"," on Twitter to share your work.",[2160,18335,18336],{},"html pre.shiki code .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .ssYd4, html code.shiki .ssYd4{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}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);}",{"title":1218,"searchDepth":1233,"depth":1233,"links":18338},[18339,18340,18341,18342],{"id":17910,"depth":1233,"text":19},{"id":17959,"depth":1233,"text":17960},{"id":18091,"depth":1233,"text":18092},{"id":15561,"depth":1233,"text":15562},"2023-07-13","Learn how we made Nuxt 3 capable of running on edge runtimes to run with server-side rendering close to your users.","/assets/blog/nuxt-on-the-edge.png",{},{"title":1044,"description":18344},"FrARxEYCul",{"id":18350,"title":1040,"authors":18351,"body":18354,"category":2176,"date":18685,"description":18686,"draft":108,"extension":1954,"image":18687,"meta":18688,"navigation":1739,"path":1041,"seo":18689,"stem":1042,"tags":6,"__hash__":18690},"blog/blog/13.v3-6.md",[18352],{"name":2190,"avatar":18353,"to":2193},{"src":2192},{"type":1140,"value":18355,"toc":18672},[18356,18366,18378,18385,18396,18399,18408,18415,18418,18422,18430,18440,18444,18457,18461,18483,18487,18502,18510,18514,18531,18539,18551,18578,18586,18590,18599,18608,18612,18629,18642,18644,18646,18660,18662,18664,18670],[1147,18357,18359,18365],{"id":18358},"spa-loading-indicator",[2243,18360],{"style":18361,"src":18362,"width":18363,"height":18363,"vAlign":18364},"display:inline","https://nuxt.com/assets/design-kit/icon-green.svg",36,"center","  SPA loading indicator",[1143,18367,18368,18369,18372,18373,2281],{},"If your site is served with ",[1220,18370,18371],{},"ssr: false"," or you have disabled server-rendering on some of your pages, you might be particularly interested in the new ",[2006,18374,18377],{"href":18375,"rel":18376},"https://github.com/nuxt/nuxt/pull/21640",[2010],"built-in SPA loading indicator",[1143,18379,18380,18381,18384],{},"You can now place an HTML file in ",[1220,18382,18383],{},"~/app/spa-loading-template.html"," with some HTML you would like to use to render a loading screen that will be rendered until your app is hydrated on these pages.",[1143,18386,18387,18388,18391,18392,18395],{},"👉 ",[1159,18389,18390],{},"By default an animated Nuxt icon is rendered",". You can completely disable this indicator by setting ",[1220,18393,18394],{},"spaLoadingTemplate: false"," in your nuxt configuration file.",[1147,18397,18398],{"id":2474},"⚡️ Performance improvements",[1143,18400,18401,18402,18407],{},"The first thing that happens when your app is hydrated is that your plugins run, and so we now perform ",[2006,18403,18406],{"href":18404,"rel":18405},"https://github.com/nuxt/nuxt/pull/21611",[2010],"build-time optimisations on your plugins",", meaning they do not need to be normalised or reordered at runtime.",[1143,18409,18410,18411,18414],{},"We also include your error component JS in your main entrypoint, meaning that if an error occurs when a user has no connectivity, you can still handle it with your ",[1220,18412,18413],{},"~/error.vue",". (This also should decrease your total bundle size.)",[1143,18416,18417],{},"👉 Compared to Nuxt 3.5.3, the minimal client bundle has decreased by ~0.7kB. Let's keep this up!",[1147,18419,18421],{"id":18420},"fully-static-server-components","🔥 Fully static server components",[1143,18423,18424,18425,2281],{},"It has been possible to use server components on static pages, but until now they would increase the payload size of your application. That is no longer true. We now store ",[2006,18426,18429],{"href":18427,"rel":18428},"https://github.com/nuxt/nuxt/pull/21461",[2010],"rendered server components as separate files, which are preloaded before navigation",[1143,18431,18387,18432,18435,18436,18439],{},[1159,18433,18434],{},"This does rely on the new, richer JSON payload format",", so make sure you have not disabled this by setting ",[1220,18437,18438],{},"experimental.renderJsonPayloads"," to false.",[1147,18441,18443],{"id":18442},"better-style-inlining","🎨 Better style inlining",[1143,18445,18446,18447,18450,18451,18456],{},"If you're monitoring your metrics closely and have not turned off ",[1220,18448,18449],{},"experimental.inlineSSRStyles",", you should see more CSS inlined in your page, and a significantly external CSS file. We're now ",[2006,18452,18455],{"href":18453,"rel":18454},"https://github.com/nuxt/nuxt/pull/21573",[2010],"better at deduplicating global CSS",", particularly added by libraries like tailwind or unocss.",[1147,18458,18460],{"id":18459},"animation-controls","🎬 Animation controls",[1143,18462,18463,18464,4363,18473,18482],{},"To give you more fine-grained control over your page/layout components, for example to create custom transitions with GSAP or other libraries, we now allow you to set ",[2006,18465,18468,9946,18471],{"href":18466,"rel":18467},"https://github.com/nuxt/nuxt/pull/19403",[2010],[1220,18469,18470],{},"pageRef",[1220,18472,385],{},[2006,18474,18477,9946,18480],{"href":18475,"rel":18476},"https://github.com/nuxt/nuxt/pull/19465",[2010],[1220,18478,18479],{},"layoutRef",[1220,18481,389],{},". These will get passed through to the underlying DOM elements.",[1147,18484,18486],{"id":18485},"automatic-static-preset-detection","✨ Automatic 'static' preset detection",[1143,18488,18489,18490,18492,18493,18498,18499,18501],{},"Up to now, running ",[1220,18491,15824],{}," produced the same output on every deployment provider, but with Nuxt 3.6 we now enable ",[2006,18494,18497],{"href":18495,"rel":18496},"https://github.com/nuxt/nuxt/pull/21655",[2010],"static provider presets"," automatically. That means if you are deploying a static build (produced with ",[1220,18500,15824],{},") to a supported provider (currently vercel and netlify with cloudflare and github pages coming soon) we'll prerender your pages with special support for that provider.",[1143,18503,18504,18505,18509],{},"This means we can configure any route rules (redirects/headers/etc) that do not require a server function. So you should get the best of both worlds when deploying a site that doesn't require runtime SSR. It also unblocks use of ",[2006,18506,16969],{"href":18507,"rel":18508},"https://github.com/nuxt/image",[2010]," on Vercel (with more potential for automatic provider integration coming soon).",[1147,18511,18513],{"id":18512},"increased-type-safety","💪 Increased type safety",[1143,18515,18516,18517,18520,18521,18524,18525,18527,18528,18530],{},"We now have better support for server-specific ",[1220,18518,18519],{},"#imports"," and augmentations if you are using the new ",[1220,18522,18523],{},"~/server/tsconfig.json"," we shipped in Nuxt 3.5. So when importing from ",[1220,18526,18519],{}," in your server directory, you'll get IDE auto-completion for the right import locations in Nitro, and won't see Vue auto-imports like ",[1220,18529,444],{}," that are unavailable within your server routes.",[1143,18532,18533,18534,2281],{},"You should now also have ",[2006,18535,18538],{"href":18536,"rel":18537},"https://github.com/nuxt/nuxt/pull/21666",[2010],"type support for runtime Nitro hooks",[1143,18540,18541,18542,18550],{},"Finally, we have ",[2006,18543,18546,18547,5537],{"href":18544,"rel":18545},"https://github.com/nuxt/nuxt/pull/21700",[2010],"removed more locations where objects had a default ",[1220,18548,18549],{},"any",". This should improve type safety within Nuxt in a number of locations where unspecified types fell back to any:",[1852,18552,18553,18558,18563,18573],{},[1855,18554,18555],{},[1220,18556,18557],{},"RuntimeConfig",[1855,18559,18560],{},[1220,18561,18562],{},"PageMeta",[1855,18564,18565,18568,18569,18572],{},[1220,18566,18567],{},"NuxtApp['payload']"," (accessible now from ",[1220,18570,18571],{},"NuxtPayload"," interface)",[1855,18574,18575],{},[1220,18576,18577],{},"ModuleMeta",[1143,18579,18580,18581,18585],{},"You can find out more about how to ",[2006,18582,18584],{"href":18544,"rel":18583},[2010],"update your code"," if this affects you in the original PR.",[1147,18587,18589],{"id":18588},"️-nitro-25-built-in","⚗️ Nitro 2.5 built-in",[1143,18591,18592,18593,18598],{},"This release ships with new Nitro 2.5, which has a ",[2006,18594,18597],{"href":18595,"rel":18596},"https://github.com/unjs/nitro/releases/tag/v2.5.0",[2010],"whole list of exciting improvements"," that are worth checking out.",[1143,18600,18601,18602,18607],{},"Of particular note is experimental support for streaming, which is also enabled by a ",[2006,18603,18606],{"href":18604,"rel":18605},"https://github.com/nuxt/nuxt/pull/21665",[2010],"couple of changes"," in Nuxt itself.",[1147,18609,18611],{"id":18610},"️-new-tools-for-module-authors","🛠️ New tools for module authors",[1143,18613,18614,18615,4363,18620,18625,18626,7989],{},"This release brings a number of utilities for modules authors to easily ",[2006,18616,18619],{"href":18617,"rel":18618},"https://github.com/nuxt/nuxt/pull/21331",[2010],"add type templates",[2006,18621,18624],{"href":18622,"rel":18623},"https://github.com/nuxt/nuxt/pull/21246",[2010],"assert compatibility"," with a given version of ",[3746,18627,18628],{},"another",[1143,18630,18631,18632,18635,18636,18641],{},"In addition, this release will finally unlock a new ",[1220,18633,18634],{},"nuxt/module-builder"," mode that should improve type support for module authors. If you're a module author, you might consider following ",[2006,18637,18640],{"href":18638,"rel":18639},"https://github.com/nuxt/starter/pull/392",[2010],"these migration steps"," to try it out in the coming days.",[1147,18643,3580],{"id":3579},[1143,18645,3583],{},[1213,18647,18648],{"className":3586,"code":14202,"language":3588,"meta":1218,"style":1218},[1220,18649,18650],{"__ignoreMap":1218},[1223,18651,18652,18654,18656,18658],{"class":1225,"line":1226},[1223,18653,2037],{"class":2036},[1223,18655,4554],{"class":1254},[1223,18657,3599],{"class":1254},[1223,18659,4019],{"class":1254},[1143,18661,4022],{},[1147,18663,17868],{"id":17867},[1143,18665,17871,18666],{},[2006,18667,18668],{"href":18668,"rel":18669},"https://github.com/nuxt/nuxt/releases/tag/v3.6.0",[2010],[2160,18671,4954],{},{"title":1218,"searchDepth":1233,"depth":1233,"links":18673},[18674,18675,18676,18677,18678,18679,18680,18681,18682,18683,18684],{"id":18358,"depth":1233,"text":18365},{"id":2474,"depth":1233,"text":18398},{"id":18420,"depth":1233,"text":18421},{"id":18442,"depth":1233,"text":18443},{"id":18459,"depth":1233,"text":18460},{"id":18485,"depth":1233,"text":18486},{"id":18512,"depth":1233,"text":18513},{"id":18588,"depth":1233,"text":18589},{"id":18610,"depth":1233,"text":18611},{"id":3579,"depth":1233,"text":3580},{"id":17867,"depth":1233,"text":17868},"2023-06-23","Nuxt 3.6 is out, bringing performance improvements, fully static server components, better style inlining, static presets, increased type safety - and much more.","/assets/blog/v3-6.png",{},{"title":1040,"description":18686},"J7HcSTj5z2",{"id":18692,"title":1036,"authors":18693,"body":18696,"category":2176,"date":19438,"description":19439,"draft":108,"extension":1954,"image":19440,"meta":19441,"navigation":1739,"path":1037,"seo":19442,"stem":1038,"tags":6,"__hash__":19443},"blog/blog/12.v3-5.md",[18694],{"name":2190,"avatar":18695,"to":2193},{"src":2192},{"type":1140,"value":18697,"toc":19424},[18698,18702,18705,18723,18741,18751,18755,18758,18761,18789,18798,18802,18819,18838,18847,18856,18859,18958,18965,18969,18980,18988,18992,18997,19086,19093,19101,19105,19120,19134,19158,19163,19207,19210,19221,19228,19300,19318,19322,19339,19345,19375,19381,19385,19392,19394,19396,19410,19412,19414,19421],[1147,18699,18701],{"id":18700},"️-vue-33-released","⚡️ Vue 3.3 released",[1143,18703,18704],{},"Vue 3.3 has been released, with lots of exciting features, particularly around type support.",[1852,18706,18707,18714,18717,18720],{},[1855,18708,18709,18710,18713],{},"new ",[1220,18711,18712],{},"defineOptions"," macro",[1855,18715,18716],{},"'generic' components",[1855,18718,18719],{},"typed slots and using external types in defineProps",[1855,18721,18722],{},"... and more",[1143,18724,18725,18726,18731,18732,4363,18736,2281],{},"This also brings a significant improvement to data fetching when navigating between nested pages (",[2006,18727,18730],{"href":18728,"rel":18729},"https://github.com/nuxt/nuxt/pull/20777",[2010],"#20777","), thanks to ",[2006,18733,18735],{"href":4069,"rel":18734},[2010],"@antfu",[2006,18737,18740],{"href":18738,"rel":18739},"https://github.com/baiwusanyu-c",[2010],"@baiwusanyu-c",[1143,18742,18743,18744,9588],{},"Read ",[1159,18745,18746],{},[2006,18747,18750],{"href":18748,"rel":18749},"https://blog.vuejs.org/posts/vue-3-3",[2010],"the full release announcement",[1155,18752,18754],{"id":18753},"nitropack-v24","🙌 Nitropack v2.4",[1143,18756,18757],{},"We've been working on lots of improvements to Nitro and these have landed already in Nitro v2.4 - you may already have this upgrade, which contains a lot of bug fixes, updates to the module worker format for Cloudflare, Vercel KV support and more.",[1143,18759,18760],{},"One note: if you're deploying to Vercel or Netlify and want to benefit from incremental static regeneration, you should now update your route rules:",[1213,18762,18764],{"className":16735,"code":18763,"language":16737,"meta":1218,"style":1218},"routeRules: {\n--  '/blog/**': { swr: 3000 },\n++  '/blog/**': { isr: 3000 },\n}\n",[1220,18765,18766,18771,18778,18785],{"__ignoreMap":1218},[1223,18767,18768],{"class":1225,"line":1226},[1223,18769,18770],{"class":1285},"routeRules: {\n",[1223,18772,18773,18775],{"class":1225,"line":1233},[1223,18774,5004],{"class":1236},[1223,18776,18777],{"class":1240},"-  '/blog/**': { swr: 3000 },\n",[1223,18779,18780,18782],{"class":1225,"line":1263},[1223,18781,16751],{"class":1236},[1223,18783,18784],{"class":1254},"+  '/blog/**': { isr: 3000 },\n",[1223,18786,18787],{"class":1225,"line":1296},[1223,18788,2407],{"class":1285},[1143,18790,18743,18791,2281],{},[1159,18792,18793],{},[2006,18794,18797],{"href":18795,"rel":18796},"https://github.com/unjs/nitro/releases/tag/v2.4.0",[2010],"the full release notes",[1155,18799,18801],{"id":18800},"rich-json-payloads","💖 Rich JSON payloads",[1143,18803,18804,18807,18808,5062,18813,18818],{},[1159,18805,18806],{},"Rich JSON payload serialisation"," is now enabled by default (",[2006,18809,18812],{"href":18810,"rel":18811},"https://github.com/nuxt/nuxt/pull/19205",[2010],"#19205",[2006,18814,18817],{"href":18815,"rel":18816},"https://github.com/nuxt/nuxt/pull/20770",[2010],"#20770","). This is both faster and allows serialising complex objects in the payload passed from the Nuxt server to client (and also when extracting payload data for prerendered sites).",[1143,18820,18821,18822,18825,18826,5062,18829,5062,18832,4363,18835,2281],{},"This now means that ",[1159,18823,18824],{},"various rich JS types are supported out-of-the-box",": regular expressions, dates, Map and Set and BigInt as well as NuxtError - and Vue-specific objects like ",[1220,18827,18828],{},"ref",[1220,18830,18831],{},"reactive",[1220,18833,18834],{},"shallowRef",[1220,18836,18837],{},"shallowReactive",[1143,18839,18840,18841,18846],{},"You can find ",[2006,18842,18845],{"href":18843,"rel":18844},"https://github.com/nuxt/nuxt/blob/main/test/fixtures/basic/pages/json-payload.vue",[2010],"an example"," in our test suite.",[1143,18848,18849,18850,18855],{},"This is all possible due to ",[2006,18851,18854],{"href":18852,"rel":18853},"https://github.com/Rich-Harris/devalue/pull/58",[2010],"Rich-Harris/devalue#58",". For a long time, Nuxt has been using our own fork of devalue owing to issues serialising Errors and other non-POJO objects, but we now have transitioned back to the original.",[1143,18857,18858],{},"You can even register your own custom types with a new object-syntax Nuxt plugin:",[1213,18860,18863],{"className":1669,"code":18861,"filename":18862,"language":1672,"meta":1218,"style":1218},"export default definePayloadPlugin(() => {\n  definePayloadReducer('BlinkingText', data => data === '\u003Coriginal-blink>' && '_')\n  definePayloadReviver('BlinkingText', () => '\u003Crevivified-blink>')\n})\n","plugins/custom-payload-type.ts",[1220,18864,18865,18882,18924,18952],{"__ignoreMap":1218},[1223,18866,18867,18869,18871,18874,18876,18878,18880],{"class":1225,"line":1226},[1223,18868,1745],{"class":1679},[1223,18870,1748],{"class":1679},[1223,18872,18873],{"class":1751}," definePayloadPlugin",[1223,18875,1754],{"class":1285},[1223,18877,1777],{"class":1236},[1223,18879,3125],{"class":1244},[1223,18881,1891],{"class":1236},[1223,18883,18884,18887,18889,18891,18894,18896,18898,18900,18902,18904,18906,18908,18911,18913,18915,18917,18920,18922],{"class":1225,"line":1233},[1223,18885,18886],{"class":1751},"  definePayloadReducer",[1223,18888,1754],{"class":1240},[1223,18890,1957],{"class":1236},[1223,18892,18893],{"class":1254},"BlinkingText",[1223,18895,1957],{"class":1236},[1223,18897,2333],{"class":1236},[1223,18899,10957],{"class":2329},[1223,18901,3125],{"class":1244},[1223,18903,10957],{"class":1285},[1223,18905,7076],{"class":1236},[1223,18907,1695],{"class":1236},[1223,18909,18910],{"class":1254},"\u003Coriginal-blink>",[1223,18912,1957],{"class":1236},[1223,18914,3905],{"class":1236},[1223,18916,1695],{"class":1236},[1223,18918,18919],{"class":1254},"_",[1223,18921,1957],{"class":1236},[1223,18923,1804],{"class":1240},[1223,18925,18926,18929,18931,18933,18935,18937,18939,18941,18943,18945,18948,18950],{"class":1225,"line":1263},[1223,18927,18928],{"class":1751},"  definePayloadReviver",[1223,18930,1754],{"class":1240},[1223,18932,1957],{"class":1236},[1223,18934,18893],{"class":1254},[1223,18936,1957],{"class":1236},[1223,18938,2333],{"class":1236},[1223,18940,3122],{"class":1236},[1223,18942,3125],{"class":1244},[1223,18944,1695],{"class":1236},[1223,18946,18947],{"class":1254},"\u003Crevivified-blink>",[1223,18949,1957],{"class":1236},[1223,18951,1804],{"class":1240},[1223,18953,18954,18956],{"class":1225,"line":1296},[1223,18955,1801],{"class":1236},[1223,18957,1804],{"class":1285},[1143,18959,18960,18961,2281],{},"You can read more about how this works ",[2006,18962,2274],{"href":18963,"rel":18964},"https://github.com/rich-harris/devalue#custom-types",[2010],[1147,18966,18968],{"id":18967},"interactive-server-components","🛝 Interactive server components",[1143,18970,18971,18972,3114,18975,3681],{},"This feature should be considered highly experimental, but thanks to some great work from @huang-julien we now support interactive content within server components via ",[3746,18973,18974],{},"slots",[2006,18976,18979],{"href":18977,"rel":18978},"https://github.com/nuxt/nuxt/pull/20284",[2010],"#20284",[1143,18981,18982,18983,2281],{},"You can follow the server component roadmap at ",[2006,18984,18987],{"href":18985,"rel":18986},"https://github.com/nuxt/nuxt/issues/19772",[2010],"#19772",[1147,18989,18991],{"id":18990},"environment-config","⏰ Environment config",[1143,18993,18994,18995,1765],{},"You can now configure fully typed, per-environment overrides in your ",[1220,18996,5357],{},[1213,18998,19000],{"className":9317,"code":18999,"language":9319,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  $production: {\n    routeRules: {\n      '/**': { isr: true }\n    }\n  },\n  $development: {\n    //\n  }\n})\n",[1220,19001,19002,19014,19023,19032,19054,19058,19062,19071,19076,19080],{"__ignoreMap":1218},[1223,19003,19004,19006,19008,19010,19012],{"class":1225,"line":1226},[1223,19005,1745],{"class":1679},[1223,19007,1748],{"class":1679},[1223,19009,2820],{"class":1751},[1223,19011,1754],{"class":1285},[1223,19013,1757],{"class":1236},[1223,19015,19016,19019,19021],{"class":1225,"line":1233},[1223,19017,19018],{"class":1240},"  $production",[1223,19020,1765],{"class":1236},[1223,19022,1891],{"class":1236},[1223,19024,19025,19028,19030],{"class":1225,"line":1263},[1223,19026,19027],{"class":1240},"    routeRules",[1223,19029,1765],{"class":1236},[1223,19031,1891],{"class":1236},[1223,19033,19034,19036,19039,19041,19043,19045,19048,19050,19052],{"class":1225,"line":1296},[1223,19035,9368],{"class":1236},[1223,19037,19038],{"class":1240},"/**",[1223,19040,1957],{"class":1236},[1223,19042,1765],{"class":1236},[1223,19044,1683],{"class":1236},[1223,19046,19047],{"class":1240}," isr",[1223,19049,1765],{"class":1236},[1223,19051,2929],{"class":2928},[1223,19053,5311],{"class":1236},[1223,19055,19056],{"class":1225,"line":1325},[1223,19057,1984],{"class":1236},[1223,19059,19060],{"class":1225,"line":1355},[1223,19061,3312],{"class":1236},[1223,19063,19064,19067,19069],{"class":1225,"line":1771},[1223,19065,19066],{"class":1240},"  $development",[1223,19068,1765],{"class":1236},[1223,19070,1891],{"class":1236},[1223,19072,19073],{"class":1225,"line":1783},[1223,19074,19075],{"class":1229},"    //\n",[1223,19077,19078],{"class":1225,"line":1792},[1223,19079,1990],{"class":1236},[1223,19081,19082,19084],{"class":1225,"line":1798},[1223,19083,1801],{"class":1236},[1223,19085,1804],{"class":1285},[1143,19087,19088,19089,19092],{},"If you're authoring layers, you can also use the ",[1220,19090,19091],{},"$meta"," key to provide metadata that you or the consumers of your layer might use.",[1143,19094,19095,19096,2281],{},"Read more ",[2006,19097,19100],{"href":19098,"rel":19099},"https://github.com/nuxt/nuxt/pull/20329",[2010],"about per-environment overrides",[1147,19102,19104],{"id":19103},"fully-typed-pages","💪 Fully typed pages",[1143,19106,19107,19108,19113,19114,19119],{},"You can benefit from fully typed routing within your Nuxt app via this experimental integration with ",[2006,19109,19112],{"href":19110,"rel":19111},"https://github.com/posva/unplugin-vue-router",[2010],"unplugin-vue-router"," - thanks to some great work from ",[2006,19115,19118],{"href":19116,"rel":19117},"https://github.com/posva",[2010],"@posva","!",[1143,19121,19122,19123,5062,19127,5062,19131,10010],{},"Out of the box, this will enable typed usage of ",[2006,19124,19125],{"href":596},[1220,19126,595],{},[2006,19128,19129],{"href":394},[1220,19130,393],{},[1220,19132,19133],{},"router.push()",[1143,19135,19136,19137,2281],{},"You can even get typed params within a page by using ",[1220,19138,19139,19141,19143,19145,19147,19149,19151,19154,19156],{"className":1669,"language":1672,"style":1218},[1223,19140,3214],{"class":1244},[1223,19142,10992],{"class":1285},[1223,19144,1248],{"class":1236},[1223,19146,5942],{"class":1751},[1223,19148,1754],{"class":1285},[1223,19150,1957],{"class":1236},[1223,19152,19153],{"class":1254},"route-name",[1223,19155,1957],{"class":1236},[1223,19157,2541],{"class":1285},[1143,19159,19160,19161,1765],{},"Enable this feature directly in your ",[1220,19162,5357],{},[1213,19164,19166],{"className":1669,"code":19165,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  experimental: {\n    typedPages: true\n  }\n})\n",[1220,19167,19168,19180,19188,19197,19201],{"__ignoreMap":1218},[1223,19169,19170,19172,19174,19176,19178],{"class":1225,"line":1226},[1223,19171,1745],{"class":1679},[1223,19173,1748],{"class":1679},[1223,19175,2820],{"class":1751},[1223,19177,1754],{"class":1285},[1223,19179,1757],{"class":1236},[1223,19181,19182,19184,19186],{"class":1225,"line":1233},[1223,19183,3074],{"class":1240},[1223,19185,1765],{"class":1236},[1223,19187,1891],{"class":1236},[1223,19189,19190,19193,19195],{"class":1225,"line":1263},[1223,19191,19192],{"class":1240},"    typedPages",[1223,19194,1765],{"class":1236},[1223,19196,3088],{"class":2928},[1223,19198,19199],{"class":1225,"line":1296},[1223,19200,1990],{"class":1236},[1223,19202,19203,19205],{"class":1225,"line":1325},[1223,19204,1801],{"class":1236},[1223,19206,1804],{"class":1285},[1147,19208,19209],{"id":14116},"🔎 'Bundler' module resolution",[1143,19211,19212,19213,19215,19216,2281],{},"We now have full support within Nuxt for the ",[1220,19214,14128],{}," strategy of ",[2006,19217,19220],{"href":19218,"rel":19219},"https://www.typescriptlang.org/docs/handbook/module-resolution.html",[2010],"module resolution",[1143,19222,19223,19224,19227],{},"We would recommend adopting this if possible. It has type support for subpath exports, for example, but more exactly matches the behaviour of build tools like Vite and Nuxt than ",[1220,19225,19226],{},"Node16"," resolution.",[1213,19229,19231],{"className":1669,"code":19230,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  typescript: {\n    tsConfig: {\n      compilerOptions: {\n        moduleResolution: 'bundler'\n      }\n    }\n  }\n})\n",[1220,19232,19233,19245,19253,19261,19269,19282,19286,19290,19294],{"__ignoreMap":1218},[1223,19234,19235,19237,19239,19241,19243],{"class":1225,"line":1226},[1223,19236,1745],{"class":1679},[1223,19238,1748],{"class":1679},[1223,19240,2820],{"class":1751},[1223,19242,1754],{"class":1285},[1223,19244,1757],{"class":1236},[1223,19246,19247,19249,19251],{"class":1225,"line":1233},[1223,19248,16789],{"class":1240},[1223,19250,1765],{"class":1236},[1223,19252,1891],{"class":1236},[1223,19254,19255,19257,19259],{"class":1225,"line":1263},[1223,19256,16798],{"class":1240},[1223,19258,1765],{"class":1236},[1223,19260,1891],{"class":1236},[1223,19262,19263,19265,19267],{"class":1225,"line":1296},[1223,19264,16807],{"class":1240},[1223,19266,1765],{"class":1236},[1223,19268,1891],{"class":1236},[1223,19270,19271,19274,19276,19278,19280],{"class":1225,"line":1325},[1223,19272,19273],{"class":1240},"        moduleResolution",[1223,19275,1765],{"class":1236},[1223,19277,1695],{"class":1236},[1223,19279,14128],{"class":1254},[1223,19281,1701],{"class":1236},[1223,19283,19284],{"class":1225,"line":1355},[1223,19285,1978],{"class":1236},[1223,19287,19288],{"class":1225,"line":1771},[1223,19289,1984],{"class":1236},[1223,19291,19292],{"class":1225,"line":1783},[1223,19293,1990],{"class":1236},[1223,19295,19296,19298],{"class":1225,"line":1792},[1223,19297,1801],{"class":1236},[1223,19299,1804],{"class":1285},[1143,19301,19302,19303,19306,19307,19310,19311,19314,19315,2281],{},"This turns on TypeScript's ability to 'follow' Node subpath exports. For example, if a library has a subpath export like ",[1220,19304,19305],{},"mylib/path"," that is mapped to ",[1220,19308,19309],{},"mylib/dist/path.mjs"," then the types for this can be pulled in from ",[1220,19312,19313],{},"mylib/dist/path.d.ts"," rather than requiring the library author to create ",[1220,19316,19317],{},"mylib/path.d.ts",[1147,19319,19321],{"id":19320},"️-separate-server-types","⚗️ Separate server types",[1143,19323,19324,19325,19327,19328,19333,19334,3681],{},"We plan to improve clarity within your IDE between the 'nitro' and 'vue' part of your app, we've shipped the first part of this via a separate generated ",[1220,19326,268],{}," for your ",[2006,19329,19330],{"href":220},[1220,19331,19332],{},"~/server"," directory (",[2006,19335,19338],{"href":19336,"rel":19337},"https://github.com/nuxt/nuxt/pull/20559",[2010],"#20559",[1143,19340,19341,19342,19344],{},"You can use by adding an additional ",[1220,19343,18523],{}," with the following content:",[1213,19346,19348],{"className":14313,"code":19347,"language":14315,"meta":1218,"style":1218},"{\n  \"extends\": \"../.nuxt/tsconfig.server.json\"\n}\n",[1220,19349,19350,19354,19371],{"__ignoreMap":1218},[1223,19351,19352],{"class":1225,"line":1226},[1223,19353,1757],{"class":1236},[1223,19355,19356,19358,19360,19362,19364,19366,19369],{"class":1225,"line":1233},[1223,19357,14326],{"class":1236},[1223,19359,8639],{"class":1244},[1223,19361,1251],{"class":1236},[1223,19363,1765],{"class":1236},[1223,19365,14349],{"class":1236},[1223,19367,19368],{"class":1254},"../.nuxt/tsconfig.server.json",[1223,19370,13485],{"class":1236},[1223,19372,19373],{"class":1225,"line":1263},[1223,19374,2407],{"class":1236},[1143,19376,19377,19378,19380],{},"Although right now these values won't be respected when type checking (",[1220,19379,714],{},"), you should get better type hints in your IDE.",[1147,19382,19384],{"id":19383},"deprecations","💀 Deprecations",[1143,19386,19387,19388,19391],{},"Although we have not typed or documented the ",[1220,19389,19390],{},"build.extend"," hook from Nuxt 2, we have been calling it within the webpack builder. We are now explicitly deprecating this and will remove it in a future minor version.",[1147,19393,3580],{"id":3579},[1143,19395,3583],{},[1213,19397,19398],{"className":3586,"code":14202,"language":3588,"meta":1218,"style":1218},[1220,19399,19400],{"__ignoreMap":1218},[1223,19401,19402,19404,19406,19408],{"class":1225,"line":1226},[1223,19403,2037],{"class":2036},[1223,19405,4554],{"class":1254},[1223,19407,3599],{"class":1254},[1223,19409,4019],{"class":1254},[1143,19411,4022],{},[1147,19413,17868],{"id":17867},[1143,19415,19416,19417],{},"Read the full release note on ",[2006,19418,19419],{"href":19419,"rel":19420},"https://github.com/nuxt/nuxt/releases/tag/v3.5.0",[2010],[2160,19422,19423],{},"html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}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 .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .ssYd4, html code.shiki .ssYd4{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sagxc, html code.shiki .sagxc{--shiki-light:#FF5370;--shiki-default:#FF5370;--shiki-dark:#FF9CAC}html pre.shiki code .svXlt, html code.shiki .svXlt{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}",{"title":1218,"searchDepth":1233,"depth":1233,"links":19425},[19426,19430,19431,19432,19433,19434,19435,19436,19437],{"id":18700,"depth":1233,"text":18701,"children":19427},[19428,19429],{"id":18753,"depth":1263,"text":18754},{"id":18800,"depth":1263,"text":18801},{"id":18967,"depth":1233,"text":18968},{"id":18990,"depth":1233,"text":18991},{"id":19103,"depth":1233,"text":19104},{"id":14116,"depth":1233,"text":19209},{"id":19320,"depth":1233,"text":19321},{"id":19383,"depth":1233,"text":19384},{"id":3579,"depth":1233,"text":3580},{"id":17867,"depth":1233,"text":17868},"2023-05-16","Nuxt 3.5.0 is out, bringing Vue 3.3, new defaults, interactive server components, typed pages, environment config - and much more.","/assets/blog/v3-5.png",{},{"title":1036,"description":19439},"kEPDW2j9jD",{"id":19445,"title":1032,"authors":19446,"body":19449,"category":2176,"date":20156,"description":20157,"draft":108,"extension":1954,"image":20158,"meta":20159,"navigation":1739,"path":1033,"seo":20160,"stem":1034,"tags":6,"__hash__":20161},"blog/blog/11.v3-4.md",[19447],{"name":2190,"avatar":19448,"to":2193},{"src":2192},{"type":1140,"value":19450,"toc":20145},[19451,19455,19458,19471,19482,19490,19533,19537,19547,19591,19604,19609,19614,19616,19706,19711,19732,19739,19750,19754,19760,19895,19898,19902,19911,19942,19945,19954,19958,19980,19989,19993,20024,20028,20041,20045,20048,20122,20124,20126,20140,20142],[1147,19452,19454],{"id":19453},"view-transitions-api-support","🪄 View Transitions API Support",[15117,19456],{"cloudinary":19457},"v1681229056/nuxt3/nuxt-view-transitions_cruvma",[1143,19459,19460,19461,19465,19466,2281],{},"You can check a demo on ",[2006,19462,19463],{"href":19463,"rel":19464},"https://nuxt-view-transitions.surge.sh",[2010]," and the ",[2006,19467,19470],{"href":19468,"rel":19469},"https://stackblitz.com/edit/nuxt-view-transitions",[2010],"source on StackBlitz",[1143,19472,19473,19474,19481],{},"You may have noticed that Chromium-based browsers now ship a new web platform API: the ",[2006,19475,19478],{"href":19476,"rel":19477},"https://developer.chrome.com/docs/web-platform/view-transitions/",[2010],[1159,19479,19480],{},"View Transitions API",". This is an exciting new ability for native browser transitions which (among other things) have the ability to transition between unrelated elements on different pages.",[1143,19483,19484,19485,2281],{},"Nuxt now ships with an experimental implementation, which will be under active development during the v3.4 release cycle. See the known issues in the ",[2006,19486,19489],{"href":19487,"rel":19488},"https://github.com/nuxt/nuxt/pull/20092",[2010],"linked PR",[1213,19491,19493],{"className":1669,"code":19492,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  experimental: {\n    viewTransition: true\n  }\n})\n",[1220,19494,19495,19507,19515,19523,19527],{"__ignoreMap":1218},[1223,19496,19497,19499,19501,19503,19505],{"class":1225,"line":1226},[1223,19498,1745],{"class":1679},[1223,19500,1748],{"class":1679},[1223,19502,2820],{"class":1751},[1223,19504,1754],{"class":1285},[1223,19506,1757],{"class":1236},[1223,19508,19509,19511,19513],{"class":1225,"line":1233},[1223,19510,3074],{"class":1240},[1223,19512,1765],{"class":1236},[1223,19514,1891],{"class":1236},[1223,19516,19517,19519,19521],{"class":1225,"line":1263},[1223,19518,13931],{"class":1240},[1223,19520,1765],{"class":1236},[1223,19522,3088],{"class":2928},[1223,19524,19525],{"class":1225,"line":1296},[1223,19526,1990],{"class":1236},[1223,19528,19529,19531],{"class":1225,"line":1325},[1223,19530,1801],{"class":1236},[1223,19532,1804],{"class":1285},[1147,19534,19536],{"id":19535},"payload-enhancements","✨ Payload Enhancements",[1143,19538,19539,19540,19546],{},"We've merged a ",[1159,19541,19542],{},[2006,19543,19545],{"href":18810,"rel":19544},[2010],"significant change to how Nuxt handles payloads"," (under an experimental flag). Payloads are used to send data from the server to the client when doing server-side rendering and avoid double data-fetching during the hydration phase.",[1213,19548,19550],{"className":1669,"code":19549,"filename":260,"language":1672,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  experimental: {\n    renderJsonPayloads: true\n  }\n})\n",[1220,19551,19552,19564,19572,19581,19585],{"__ignoreMap":1218},[1223,19553,19554,19556,19558,19560,19562],{"class":1225,"line":1226},[1223,19555,1745],{"class":1679},[1223,19557,1748],{"class":1679},[1223,19559,2820],{"class":1751},[1223,19561,1754],{"class":1285},[1223,19563,1757],{"class":1236},[1223,19565,19566,19568,19570],{"class":1225,"line":1233},[1223,19567,3074],{"class":1240},[1223,19569,1765],{"class":1236},[1223,19571,1891],{"class":1236},[1223,19573,19574,19577,19579],{"class":1225,"line":1263},[1223,19575,19576],{"class":1240},"    renderJsonPayloads",[1223,19578,1765],{"class":1236},[1223,19580,3088],{"class":2928},[1223,19582,19583],{"class":1225,"line":1296},[1223,19584,1990],{"class":1236},[1223,19586,19587,19589],{"class":1225,"line":1325},[1223,19588,1801],{"class":1236},[1223,19590,1804],{"class":1285},[1143,19592,19593,19594,18825,19596,5062,19598,5062,19600,4363,19602,2281],{},"With this new option enabled, this now means that ",[1159,19595,18824],{},[1220,19597,18828],{},[1220,19599,18831],{},[1220,19601,18834],{},[1220,19603,18837],{},[1143,19605,18840,19606,18846],{},[2006,19607,18845],{"href":18843,"rel":19608},[2010],[1143,19610,18849,19611,18855],{},[2006,19612,18854],{"href":18852,"rel":19613},[2010],[1143,19615,18858],{},[1213,19617,19618],{"className":1669,"code":18861,"filename":18862,"language":1672,"meta":1218,"style":1218},[1220,19619,19620,19636,19674,19700],{"__ignoreMap":1218},[1223,19621,19622,19624,19626,19628,19630,19632,19634],{"class":1225,"line":1226},[1223,19623,1745],{"class":1679},[1223,19625,1748],{"class":1679},[1223,19627,18873],{"class":1751},[1223,19629,1754],{"class":1285},[1223,19631,1777],{"class":1236},[1223,19633,3125],{"class":1244},[1223,19635,1891],{"class":1236},[1223,19637,19638,19640,19642,19644,19646,19648,19650,19652,19654,19656,19658,19660,19662,19664,19666,19668,19670,19672],{"class":1225,"line":1233},[1223,19639,18886],{"class":1751},[1223,19641,1754],{"class":1240},[1223,19643,1957],{"class":1236},[1223,19645,18893],{"class":1254},[1223,19647,1957],{"class":1236},[1223,19649,2333],{"class":1236},[1223,19651,10957],{"class":2329},[1223,19653,3125],{"class":1244},[1223,19655,10957],{"class":1285},[1223,19657,7076],{"class":1236},[1223,19659,1695],{"class":1236},[1223,19661,18910],{"class":1254},[1223,19663,1957],{"class":1236},[1223,19665,3905],{"class":1236},[1223,19667,1695],{"class":1236},[1223,19669,18919],{"class":1254},[1223,19671,1957],{"class":1236},[1223,19673,1804],{"class":1240},[1223,19675,19676,19678,19680,19682,19684,19686,19688,19690,19692,19694,19696,19698],{"class":1225,"line":1263},[1223,19677,18928],{"class":1751},[1223,19679,1754],{"class":1240},[1223,19681,1957],{"class":1236},[1223,19683,18893],{"class":1254},[1223,19685,1957],{"class":1236},[1223,19687,2333],{"class":1236},[1223,19689,3122],{"class":1236},[1223,19691,3125],{"class":1244},[1223,19693,1695],{"class":1236},[1223,19695,18947],{"class":1254},[1223,19697,1957],{"class":1236},[1223,19699,1804],{"class":1240},[1223,19701,19702,19704],{"class":1225,"line":1296},[1223,19703,1801],{"class":1236},[1223,19705,1804],{"class":1285},[1143,19707,18960,19708,2281],{},[2006,19709,2274],{"href":18963,"rel":19710},[2010],[1143,19712,19713,19716,19717,19719,19720,19722,19723,19726,19727,6381,19729,19731],{},[1159,19714,19715],{},"Note",": this only affects payloads of the Nuxt app, that is, data stored within ",[1220,19718,536],{},", returned from ",[1220,19721,432],{}," or manually injected via ",[1220,19724,19725],{},"nuxtApp.payload",". It does not affect data fetched from Nitro server routes via ",[1220,19728,547],{},[1220,19730,444],{}," although this is one area I am keen to explore further.",[1143,19733,19734,19735,19738],{},"Preliminary testing shows a significant speed-up: ",[1159,19736,19737],{},"25% faster in total server response time"," for a very minimal app with a large JSON payload, but I'd urge you to run your own tests and share the results with us.",[1143,19740,19741,19742,19745,19746,19749],{},"As mentioned, we're merging this behind a flag so we can test this broadly and gather feedback on the new approach. The most significant potential change is that the payload is now no longer available on ",[1220,19743,19744],{},"window.__NUXT__"," immediately. Instead, we now need to initialise the Nuxt app to parse the payload so any code that accesses ",[1220,19747,19748],{},"__NUXT__"," will need to be run in a plugin or later in the Nuxt app lifecycle. Please feel free to raise an issue if you foresee or encounter issues in your projects.",[1147,19751,19753],{"id":19752},"object-syntax-nuxt-plugins","🎁 Object-syntax Nuxt plugins",[1143,19755,19756,19757,19759],{},"We now support object-syntax Nuxt plugins for better control over plugin ",[3746,19758,17442],{}," and easier registration of hooks.",[1213,19761,19764],{"className":1669,"code":19762,"filename":19763,"language":1672,"meta":1218,"style":1218},"export default defineNuxtPlugin({\n  name: 'my-plugin',\n  enforce: 'pre', // or 'post'\n  async setup (nuxtApp) {\n    // this is the equivalent of a normal functional plugin\n  },\n  hooks: {\n    // You can directly register Nuxt app hooks here\n    'app:created'() {\n      const nuxtApp = useNuxtApp()\n      //\n    }\n  }\n})\n","plugins/my-plugin.ts",[1220,19765,19766,19778,19794,19812,19828,19833,19837,19845,19850,19863,19876,19881,19885,19889],{"__ignoreMap":1218},[1223,19767,19768,19770,19772,19774,19776],{"class":1225,"line":1226},[1223,19769,1745],{"class":1679},[1223,19771,1748],{"class":1679},[1223,19773,13791],{"class":1751},[1223,19775,1754],{"class":1285},[1223,19777,1757],{"class":1236},[1223,19779,19780,19783,19785,19787,19790,19792],{"class":1225,"line":1233},[1223,19781,19782],{"class":1240},"  name",[1223,19784,1765],{"class":1236},[1223,19786,1695],{"class":1236},[1223,19788,19789],{"class":1254},"my-plugin",[1223,19791,1957],{"class":1236},[1223,19793,1780],{"class":1236},[1223,19795,19796,19799,19801,19803,19805,19807,19809],{"class":1225,"line":1263},[1223,19797,19798],{"class":1240},"  enforce",[1223,19800,1765],{"class":1236},[1223,19802,1695],{"class":1236},[1223,19804,1213],{"class":1254},[1223,19806,1957],{"class":1236},[1223,19808,2333],{"class":1236},[1223,19810,19811],{"class":1229}," // or 'post'\n",[1223,19813,19814,19817,19819,19821,19824,19826],{"class":1225,"line":1296},[1223,19815,19816],{"class":1244},"  async",[1223,19818,5902],{"class":1240},[1223,19820,3114],{"class":1236},[1223,19822,19823],{"class":2329},"nuxtApp",[1223,19825,2541],{"class":1236},[1223,19827,1891],{"class":1236},[1223,19829,19830],{"class":1225,"line":1325},[1223,19831,19832],{"class":1229},"    // this is the equivalent of a normal functional plugin\n",[1223,19834,19835],{"class":1225,"line":1355},[1223,19836,3312],{"class":1236},[1223,19838,19839,19841,19843],{"class":1225,"line":1771},[1223,19840,14618],{"class":1240},[1223,19842,1765],{"class":1236},[1223,19844,1891],{"class":1236},[1223,19846,19847],{"class":1225,"line":1783},[1223,19848,19849],{"class":1229},"    // You can directly register Nuxt app hooks here\n",[1223,19851,19852,19854,19857,19859,19861],{"class":1225,"line":1792},[1223,19853,9188],{"class":1236},[1223,19855,19856],{"class":1254},"app:created",[1223,19858,1957],{"class":1236},[1223,19860,1777],{"class":1236},[1223,19862,1891],{"class":1236},[1223,19864,19865,19868,19870,19872,19874],{"class":1225,"line":1798},[1223,19866,19867],{"class":1244},"      const",[1223,19869,16372],{"class":1285},[1223,19871,2339],{"class":1236},[1223,19873,16318],{"class":1751},[1223,19875,1789],{"class":1240},[1223,19877,19878],{"class":1225,"line":1975},[1223,19879,19880],{"class":1229},"      //\n",[1223,19882,19883],{"class":1225,"line":1981},[1223,19884,1984],{"class":1236},[1223,19886,19887],{"class":1225,"line":1987},[1223,19888,1990],{"class":1236},[1223,19890,19891,19893],{"class":1225,"line":1993},[1223,19892,1801],{"class":1236},[1223,19894,1804],{"class":1285},[1143,19896,19897],{},"In future we plan to enable build optimizations based on the metadata you pass in your Nuxt plugins.",[1147,19899,19901],{"id":19900},"️-easier-devtools-configuration","🛠️ Easier Devtools Configuration",[1143,19903,19904,19905,2131,19908,19910],{},"It's even easier to enable Nuxt DevTools in your project: just set ",[1220,19906,19907],{},"devtools: true",[1220,19909,5357],{}," file to enable devtools.",[1213,19912,19914],{"className":9317,"code":19913,"filename":260,"language":9319,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  devtools: true\n})\n",[1220,19915,19916,19928,19936],{"__ignoreMap":1218},[1223,19917,19918,19920,19922,19924,19926],{"class":1225,"line":1226},[1223,19919,1745],{"class":1679},[1223,19921,1748],{"class":1679},[1223,19923,2820],{"class":1751},[1223,19925,1754],{"class":1285},[1223,19927,1757],{"class":1236},[1223,19929,19930,19932,19934],{"class":1225,"line":1233},[1223,19931,15005],{"class":1240},[1223,19933,1765],{"class":1236},[1223,19935,3088],{"class":2928},[1223,19937,19938,19940],{"class":1225,"line":1263},[1223,19939,1801],{"class":1236},[1223,19941,1804],{"class":1285},[1143,19943,19944],{},"If it's not already installed, Nuxt will prompt to install it locally. This means you no longer need to have Nuxt DevTools enabled globally.",[1143,19946,19947,19949,19950,19953],{},[1159,19948,19715],{},": the DevTools is still experimental and under active development, so do be prepared for occasional unexpected behaviour, and please report issues directly to ",[2006,19951,9558],{"href":9558,"rel":19952},[2010]," 🙏",[1147,19955,19957],{"id":19956},"layers-improvements","📚 Layers Improvements",[1143,19959,19960,19961,19979],{},"We now support ",[2006,19962,19965,19966,5061,19969,5061,19972,5061,19975,19978],{"href":19963,"rel":19964},"https://github.com/nuxt/nuxt/pull/19986",[2010],"transforming ",[1220,19967,19968],{},"~",[1220,19970,19971],{},"~~",[1220,19973,19974],{},"@",[1220,19976,19977],{},"@@"," aliases within layers",", meaning you now no longer need to use relative paths when importing within layers.",[1143,19981,19982,19983,19988],{},"This should mean it is much easier to use a 'normal' Nuxt project as a ",[2006,19984,19987],{"href":19985,"rel":19986},"https://nuxt.com/docs/getting-started/layers#layers",[2010],"layer"," without needing to specially write it as one.",[1147,19990,19992],{"id":19991},"better-context-transforms","🧸 Better Context Transforms",[1143,19994,19995,19996,20001,20002,4363,20004,20006,20007,20009,20010,4363,20012,20015,20016,4363,20018,2553,20021,20023],{},"We ",[2006,19997,20000],{"href":19998,"rel":19999},"https://github.com/nuxt/nuxt/pull/20182",[2010],"now transform certain keys"," of ",[1220,20003,587],{},[1220,20005,579],{}," which means you should have fewer issues with a missing Nuxt instance. This includes support accessing the Nuxt instance after an ",[1220,20008,3773],{}," within ",[1220,20011,13261],{},[1220,20013,20014],{},"setup"," functions for those still using the Options API. And you no longer need to wrap ",[1220,20017,195],{},[1220,20019,20020],{},"validate",[1220,20022,583],{}," when using async functions.",[1147,20025,20027],{"id":20026},"️-ecosystem-updates","♻️ Ecosystem Updates",[1143,20029,20030,20031,4363,20036,20040],{},"As usual, this release will pull in upstream improvements, including the new ",[2006,20032,20035],{"href":20033,"rel":20034},"https://github.com/unjs/consola",[2010],"Consola v3",[2006,20037,20039],{"href":17400,"rel":20038},[2010],"Nitropack v2.3.3"," (a new minor is expected shortly).",[1147,20042,20044],{"id":20043},"breaking-fixes","🚨 'Breaking fixes'",[1143,20046,20047],{},"We've also taken the opportunity to do some cleanup in this minor release.",[2412,20049,20050,20064,20090,20104,20114],{},[1855,20051,20052,20053,20056,20057,20059,20060,20063],{},"Previously it was possible to pass the ",[1220,20054,20055],{},"x-nuxt-no-ssr"," header (undocumented) to force SPA rendering. We've now disabled this behaviour by default but you can get it back by setting ",[1220,20058,8200],{}," to true. Alternatively, you can set ",[1220,20061,20062],{},"event.context.nuxt.noSSR"," on the server to force SPA rendering.",[1855,20065,20066,20067,20076,20077,20086,20087,20089],{},"We've ",[2006,20068,20071,20072,20075],{"href":20069,"rel":20070},"https://github.com/nuxt/nuxt/pull/20111",[2010],"removed the (deprecated) ",[1220,20073,20074],{},"#head"," alias"," and also disabled the ",[2006,20078,20081,20082,20085],{"href":20079,"rel":20080},"https://github.com/nuxt/nuxt/pull/20131",[2010],"polyfill for ",[1220,20083,20084],{},"@vueuse/head"," behaviour"," by default. (It can still be enabled with ",[1220,20088,8189],{},".)",[1855,20091,20066,20092,20100,20101,2281],{},[2006,20093,20071,20096,20099],{"href":20094,"rel":20095},"https://github.com/nuxt/nuxt/pull/20112",[2010],[1220,20097,20098],{},"experimental.viteNode"," option",". It can be configured instead with ",[1220,20102,20103],{},"vite.devBundler",[1855,20105,20066,20106,20113],{},[2006,20107,20110,20111,16367],{"href":20108,"rel":20109},"https://github.com/nuxt/nuxt/pull/20082",[2010],"deprecated accessing public runtime config without the ",[1220,20112,215],{},". This was an undocument compatibility measure with Nuxt 2 and we plan to remove it entirely in v3.5.",[1855,20115,20116,20117,20121],{},"To fix a bug with our vue-router integration, we now generate a slightly different path matching syntax. If you were relying on the exact path generated, have a look at ",[2006,20118,20119],{"href":20119,"rel":20120},"https://github.com/nuxt/nuxt/pull/19902",[2010]," for more information.",[1147,20123,3580],{"id":3579},[1143,20125,3583],{},[1213,20127,20128],{"className":3586,"code":14202,"language":3588,"meta":1218,"style":1218},[1220,20129,20130],{"__ignoreMap":1218},[1223,20131,20132,20134,20136,20138],{"class":1225,"line":1226},[1223,20133,2037],{"class":2036},[1223,20135,4554],{"class":1254},[1223,20137,3599],{"class":1254},[1223,20139,4019],{"class":1254},[1143,20141,4022],{},[2160,20143,20144],{},"html pre.shiki code .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .sagxc, html code.shiki .sagxc{--shiki-light:#FF5370;--shiki-default:#FF5370;--shiki-dark:#FF9CAC}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 .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}html pre.shiki code .ssYd4, html code.shiki .ssYd4{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .svXlt, html code.shiki .svXlt{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}",{"title":1218,"searchDepth":1233,"depth":1233,"links":20146},[20147,20148,20149,20150,20151,20152,20153,20154,20155],{"id":19453,"depth":1233,"text":19454},{"id":19535,"depth":1233,"text":19536},{"id":19752,"depth":1233,"text":19753},{"id":19900,"depth":1233,"text":19901},{"id":19956,"depth":1233,"text":19957},{"id":19991,"depth":1233,"text":19992},{"id":20026,"depth":1233,"text":20027},{"id":20043,"depth":1233,"text":20044},{"id":3579,"depth":1233,"text":3580},"2023-04-11","Nuxt 3.4.0 is the latest release of Nuxt 3, bringing exciting new features, including support for the View Transitions API, transferring rich JavaScript payloads from server to client - and much more.","/assets/blog/v3-4.png",{},{"title":1032,"description":20157},"zeZBlpod50",{"id":20163,"title":1072,"authors":20164,"body":20167,"category":2176,"date":20846,"description":20847,"draft":108,"extension":1954,"image":20848,"meta":20849,"navigation":1739,"path":1073,"seo":20850,"stem":1074,"tags":6,"__hash__":20851},"blog/blog/3.introducing-nuxt-devtools.md",[20165],{"name":4066,"avatar":20166,"to":4069,"twitter":4070},{"src":4068},{"type":1140,"value":20168,"toc":20823},[20169,20189,20195,20198,20202,20204,20238,20241,20281,20292,20302,20314,20327,20334,20336,20342,20345,20348,20354,20357,20363,20366,20374,20377,20383,20395,20397,20400,20412,20414,20417,20423,20425,20431,20437,20440,20446,20450,20453,20459,20461,20467,20473,20481,20487,20489,20497,20503,20505,20508,20514,20518,20521,20527,20531,20534,20540,20544,20565,20571,20575,20578,20584,20588,20591,20597,20601,20612,20618,20622,20635,20641,20645,20648,20652,20658,20662,20668,20675,20681,20688,20694,20698,20704,20707,20744,20753,20757,20760,20763,20769,20773,20777,20781,20785,20789,20793,20795,20808,20820],[1143,20170,20171,20172,9946,20175,20180,20181,20188],{},"We announced the preview of ",[2006,20173,9560],{"href":9558,"rel":20174},[2010],[2006,20176,20179],{"href":20177,"rel":20178},"https://vuejs.amsterdam/",[2010],"Vue Amsterdam 2023",", a new tool to help you understand your Nuxt app and improve the developer experience even further. Today we released a new minor version ",[2006,20182,20185],{"href":20183,"rel":20184},"https://github.com/nuxt/devtools/releases/tag/v0.3.0",[2010],[1220,20186,20187],{},"v0.3.0"," with a bunch of updates and improvements.",[1143,20190,20191],{},[2243,20192],{"alt":20193,"src":20194},"devtools-tab-overview","/assets/blog/devtools/tab-overview.png",[1143,20196,20197],{},"In this post, we will explore the reasons behind the creation of Nuxt DevTools, how it can enhance your development experience, and what you can expect in the future.",[1147,20199,20201],{"id":20200},"developer-experience","Developer Experience",[1143,20203,15035],{},[1143,20205,20206,20207,20211,20212,20215,20216,5062,20221,5062,20226,4363,20230,8602,20235,2281],{},"In Nuxt 3, we switched to ",[2006,20208,973],{"href":20209,"rel":20210},"https://vitejs.dev/",[2010]," as the default bundler for the instant hot module replacement (HMR) during developement, creating a faster feedback loop to your workflow. Additionally, we have introduced ",[2006,20213,738],{"href":17400,"rel":20214},[2010],", a new server engine that allows you to deploy your Nuxt app to any hosting service, such as ",[2006,20217,20220],{"href":20218,"rel":20219},"https://vercel.com",[2010],"Vercel",[2006,20222,20225],{"href":20223,"rel":20224},"https://netlify.com",[2010],"Netlify",[2006,20227,20229],{"href":20228},"https//cloudflare.com","Cloudflare",[2006,20231,20234],{"href":20232,"rel":20233},"https://nitro.unjs.io/deploy",[2010],"more",[1159,20236,20237],{},"with zero-config",[1143,20239,20240],{},"Nuxt offers many common practices built-in:",[1852,20242,20243,20246,20256,20268],{},[1855,20244,20245],{},"Write TypeScript and ESM out-of-the-box throughout your codebase.",[1855,20247,20248,20249,20255],{},"Build single-page applications (SPA), server-side rendering (SSR), static site generation (SSG), or ",[2006,20250,20251,20252],{"href":10878},"hybrid them ",[1159,20253,20254],{},"per routes"," - using the same codebase isomorphically without any explicit setup.",[1855,20257,20258,20259,4363,20263,20267],{},"Use several composables, like ",[2006,20260,20261],{"href":537},[1220,20262,536],{},[2006,20264,20265],{"href":433},[1220,20266,432],{}," for sharing states accessible across the server and client sides.",[1855,20269,20270,20271,4363,20275,20280],{},"Leverage SEO utilities, like ",[2006,20272,20273],{"href":449},[1220,20274,448],{},[2006,20276,20278],{"href":20277},"/docs/getting-started/seo-meta#useseometa",[1220,20279,528],{}," to make meta-tags management a breaze.",[1143,20282,20283,20284,5062,20286,20288,20289,20291],{},"Moreover, features such as the ",[2006,20285,15044],{"href":192},[2006,20287,211],{"href":212},", route ",[2006,20290,195],{"href":196},", and other tools make app creation easier and codebases more organized.",[1143,20293,20294,20295,4363,20297,20301],{},"Conventions like ",[2006,20296,15041],{"href":208},[2006,20298,15057],{"href":20299,"rel":20300},"https://nitro.unjs.io/guide/introduction/routing",[2010]," making the routing intuitive and effortless.",[1143,20303,20304,20307,20308,20310,20311,2281],{},[2006,20305,20306],{"href":180},"Components auto-imports"," makes it easy to create shared components that are directly available in any Vue file. Unlike global components, they are code-splitted. We also introduced ",[2006,20309,15052],{"href":124},", where all APIs from Vue are directly available. Nuxt modules can also provide their custom composables to be auto-imported, as well as your ",[2006,20312,20313],{"href":184},"local composables",[1143,20315,20316,20317,4363,20320,20323,20324],{},"Recently, we introduced client and server-only components, which can be used by adding ",[1220,20318,20319],{},".client",[1220,20321,20322],{},".server"," to the filename. All these conventions are fully typed and developers can even have type autocomplete when doing route navigation or fetching data from APIs. ",[1159,20325,20326],{},"These conventions significantly reduce boilerplate code, avoid duplications, and improve productivity.",[1143,20328,20329,20330,20333],{},"When it comes to ecosystem, Nuxt has a large community of developers building modules around it, ",[2006,20331,20332],{"href":15060},"with hundreds of high-quality modules"," available. Modules allow developers to get integrations for features they want without worrying about configuration or best practices.",[1147,20335,15076],{"id":15075},[1143,20337,20338,20339,2281],{},"Nuxt is capable of creating a large scale application at ease, however there is one problem: ",[1159,20340,20341],{},"the lack of transparency",[1143,20343,20344],{},"For every new feature and convention we introduce, we are adding a bit more abstraction to the framework.",[1143,20346,20347],{},"Abstractions are great things to transfer implementation complexity and make things easier to get more focus when building. On the other hand, they can also add extra burden for users to learn and understand what's going on under the hood. Leading also to implicitness, like where a auto-imported component is from, or how many modules is using a certain component, etc. It can also make things hard to debug.",[1143,20349,20350,20351,2281],{},"This might be considered as a trade-off of any tools, you have to learn and understand the tool to use it with efficiency. Despite improving the documentation and providing more examples, ",[1159,20352,20353],{},"we believe of an opportunity to improve the lack of transparency",[1147,20355,1072],{"id":20356},"introducing-nuxt-devtools",[1143,20358,20359,20362],{},[2006,20360,9560],{"href":9558,"rel":20361},[2010]," is a visual tool to help you understand your Nuxt app and improve the developer experience even further. It's created to provide a better transparency of Nuxt and your app, find performance bottlenecks and help you manage your app and configuration.",[1143,20364,20365],{},"It is shipped as an experimental module and provide the views right inside your app. Once installed, it will add a small icon on the bottom of your app. Clicking it will open the DevTools panel.",[1143,20367,20368,20369,2281],{},"To try it, please refer to the ",[2006,20370,20373],{"href":20371,"rel":20372},"https://devtools.nuxtjs.org/guide",[2010],"installation guide",[1155,20375,942],{"id":20376},"overview",[1143,20378,20379,20380],{},"Shows a quick overview of your app, including the Nuxt version, pages, components, modules, and plugins you are using. ",[1159,20381,20382],{},"It also check your Nuxt version and allow you to upgrade with a single click.",[7119,20384,20386,20389,20392],{":autoplay":9655,":controls":9655,"autoPlay":1739,"controls":1739,"poster":20385},"https://res.cloudinary.com/nuxt/video/upload/v1679922926/nuxt3/nuxt-devtools-upgrade_dnfghq.jpg",[15705,20387],{"src":20388,"type":15708},"https://res.cloudinary.com/nuxt/video/upload/v1679922926/nuxt3/nuxt-devtools-upgrade_dnfghq.webm",[15705,20390],{"src":20391,"type":15712},"https://res.cloudinary.com/nuxt/video/upload/v1679922926/nuxt3/nuxt-devtools-upgrade_dnfghq.mp4",[15705,20393],{"src":20394,"type":15716},"https://res.cloudinary.com/nuxt/video/upload/v1679922926/nuxt3/nuxt-devtools-upgrade_dnfghq.ogg",[1155,20396,776],{"id":207},[1143,20398,20399],{},"The pages tab shows your current routes and provide a quick way to navigate to them. For dynamic routes, it also provide a form to fill with each params interactively. You can also use the textbox to play and test how each route is matched.",[7119,20401,20403,20406,20409],{":autoplay":9655,":controls":9655,"autoPlay":1739,"controls":1739,"poster":20402},"https://res.cloudinary.com/nuxt/video/upload/v1679923373/nuxt3/nuxt-devtools-pages_csjoh0.jpg",[15705,20404],{"src":20405,"type":15708},"https://res.cloudinary.com/nuxt/video/upload/v1679923373/nuxt3/nuxt-devtools-pages_csjoh0.webm",[15705,20407],{"src":20408,"type":15712},"https://res.cloudinary.com/nuxt/video/upload/v1679923373/nuxt3/nuxt-devtools-pages_csjoh0.mp4",[15705,20410],{"src":20411,"type":15716},"https://res.cloudinary.com/nuxt/video/upload/v1679923373/nuxt3/nuxt-devtools-pages_csjoh0.ogg",[1155,20413,353],{"id":179},[1143,20415,20416],{},"Components tab show all the components you are using in your app and where they are from. You can also search for them and go to the source code.",[1143,20418,20419],{},[2243,20420],{"alt":20421,"src":20422},"nuxt-devtools-tab-components","/assets/blog/devtools/tab-components.png",[1143,20424,15162],{},[1143,20426,20427],{},[2243,20428],{"alt":20429,"src":20430},"nuxt-devtools-components-graph","/assets/blog/devtools/tab-components-graph-all.png",[1143,20432,20433],{},[2243,20434],{"alt":20435,"src":20436},"nuxt-devtools-components-graph-filtered","/assets/blog/devtools/tab-components-graph-filtered.png",[1143,20438,20439],{},"You can also use the \"Inspector\" feature to inspect the DOM tree and see which component is rendering it. Click to go to your editor of the specific line. Making it much easier to make changes, without the requirement of understanding the project structure thoroughly.",[1143,20441,20442],{},[2243,20443],{"alt":20444,"src":20445},"nuxt-devtools-tab-components-inspector","/assets/blog/devtools/tab-components-inspector.png",[1155,20447,20449],{"id":20448},"imports","Imports",[1143,20451,20452],{},"Imports tab shows all the auto-imports registered to Nuxt. You can see which files are importing them, and where they are from. Some entries can also provide short descriptions and documentation links.",[1143,20454,20455],{},[2243,20456],{"alt":20457,"src":20458},"nuxt-devtools-tab-imports","/assets/blog/devtools/tab-imports.png",[1155,20460,143],{"id":199},[1143,20462,20463,20464,2281],{},"Modules tab shows all the modules you have installed and providing the links to their documentation and source code. You can find more modules available in ",[2006,20465,20466],{"href":15060},"Nuxt Modules",[1143,20468,20469],{},[2243,20470],{"alt":20471,"src":20472},"nuxt-devtools-tab-modules","/assets/blog/devtools/tab-modules.png",[1143,20474,20475,20476,20480],{},"Recently we introduce the experimental upgrade feature, which allows you to upgrade your Nuxt or modules with ease. With the ",[2006,20477,20479],{"href":20478},"#terminals","Terminal tab",", it shows the output of the upgrade process transparently.",[1143,20482,20483],{},[2243,20484],{"alt":20485,"src":20486},"nuxt-devtools-tab-modules-upgrade","/assets/blog/devtools/tab-modules-upgrade.png",[1155,20488,39],{"id":175},[1143,20490,20491,20492,20496],{},"The assets tab that shows all your static assets and their information. You can copy the paths of the assets, or the code snippets of using them. In the future, with the integrations of ",[2006,20493,16969],{"href":20494,"rel":20495},"https://image.nuxtjs.org/",[2010],", you can even optimize images with a single click.",[1143,20498,20499],{},[2243,20500],{"alt":20501,"src":20502},"nuxt-devtools-tab-assets","/assets/blog/devtools/tab-assets.png",[1155,20504,784],{"id":211},[1143,20506,20507],{},"Plugins tab shows all the plugins you are using in your app. As plugins runs before the app is mounted,the time spent in each plugin should be minimal to avoid blocking the app from rendering. The time cost of each plugin provided can be helpful to find performance bottlenecks.",[1143,20509,20510],{},[2243,20511],{"alt":20512,"src":20513},"nuxt-devtools-tab-plugins","/assets/blog/devtools/tab-plugins.png",[1155,20515,20517],{"id":20516},"hooks","Hooks",[1143,20519,20520],{},"Hooks tab can help you to monitor the time spent in each hook from both client and server side. You can also see how many lisenters registed to each hook, and how many times they have been invoked. This can be helpful to find performance bottlenecks.",[1143,20522,20523],{},[2243,20524],{"alt":20525,"src":20526},"nuxt-devtools-tab-hooks","/assets/blog/devtools/tab-hooks.png",[1155,20528,20530],{"id":20529},"app-config","App Config",[1143,20532,20533],{},"You can inspect and modify the app config in DevTools, try different configurations and see the effects immediately.",[1143,20535,20536],{},[2243,20537],{"alt":20538,"src":20539},"nuxt-devtools-app-config","/assets/blog/devtools/tab-app-config.png",[1155,20541,20543],{"id":20542},"payload-data","Payload & Data",[1143,20545,20546,20547,5062,20551,4363,20555,20559,20560,4363,20562,20564],{},"This tab shows the state created by ",[2006,20548,20549],{"href":537},[1220,20550,536],{},[2006,20552,20553],{"href":433},[1220,20554,432],{},[2006,20556,20557],{"href":445},[1220,20558,444],{},". It can be helpful to understand how the data is fetched and how the state is managed, or change them reactively to see it they affects your app. For ",[1220,20561,432],{},[1220,20563,444],{},", you can also manually the trigger the refetch.",[1143,20566,20567],{},[2243,20568],{"alt":20569,"src":20570},"nuxt-devtools-tab-payload","/assets/blog/devtools/tab-payload.png",[1155,20572,20574],{"id":20573},"terminals","Terminals",[1143,20576,20577],{},"In some integrations, they might require to have subprocesses running to do certain jobs. Before DevTools, you either hide the output of the subprocess entirely and swallow the potential warnings/errors, or pipe to stdout and pollute your terminal with multiple outputs. Now you can now have the outputs in DevTools for each process and clearly isolated.",[1143,20579,20580],{},[2243,20581],{"alt":20582,"src":20583},"nuxt-devtools-tab-terminals","/assets/blog/devtools/tab-terminals.png",[1155,20585,20587],{"id":20586},"virtual-files","Virtual Files",[1143,20589,20590],{},"Virtual Files tab shows the virtual files generated by Nuxt and Nitro to support the conventions. This can be helpful for advanced debugging.",[1143,20592,20593],{},[2243,20594],{"alt":20595,"src":20596},"nuxt-devtools-tab-virtual-files","/assets/blog/devtools/tab-virtual-files.png",[1155,20598,20600],{"id":20599},"inspect","Inspect",[1143,20602,20603,20604,20611],{},"Inspect expose the ",[2006,20605,20608],{"href":20606,"rel":20607},"https://github.com/antfu/vite-plugin-inspect",[2010],[1220,20609,20610],{},"vite-plugin-inspect"," integration, allowing you to inspect transformation steps of Vite. It can be helpful to understand how each plugin is transforming your code and spot potential issues.",[1143,20613,20614],{},[2243,20615],{"alt":20616,"src":20617},"nuxt-devtools-vite-plugin-inspect","/assets/blog/devtools/tab-inspect.png",[1155,20619,20621],{"id":20620},"vs-code","VS Code",[1143,20623,20624,20625,20630,20631,20634],{},"Thanks to ",[2006,20626,20629],{"href":20627,"rel":20628},"https://code.visualstudio.com/docs/remote/vscode-server",[2010],"VS Code Server",", we are able to integrate a ",[1159,20632,20633],{},"full-featured"," VS Code instance into DevTools. You can install extensions and sync your settings. This allows you to get closer feedback loop where you can change the code and see the result immediately without leaving the browser.",[1143,20636,20637],{},[2243,20638],{"alt":20639,"src":20640},"nuxt-devtools-tab-vscode","/assets/blog/devtools/tab-vscode.png",[1155,20642,20644],{"id":20643},"module-contributed-view","Module Contributed View",[1143,20646,20647],{},"With the ecosystem in mind, Nuxt DevTools to designed to be flexible and extendable. Modules could contribute their own views to DevTools, to provide interactive data and playgrounds for their integrations. The following are a few examples:",[1143,20649,20650,15381],{},[2006,20651,15380],{"href":15379},[1143,20653,20654],{},[2243,20655],{"alt":20656,"src":20657},"nuxt-devtools-tab-vueuse","/assets/blog/devtools/tab-vueuse.png",[1143,20659,20660,15411],{},[2006,20661,15410],{"href":15409},[1143,20663,20664],{},[2243,20665],{"alt":20666,"src":20667},"nuxt-devtools-tab-unocss","/assets/blog/devtools/tab-unocss.png",[1143,20669,20670,20674],{},[2006,20671,20673],{"href":20672},"/modules/icon","Nuxt Icon module"," provides a search engine for all icons available.",[1143,20676,20677],{},[2243,20678],{"alt":20679,"src":20680},"nuxt-devtools-tab-nuxt-icon","/assets/blog/devtools/tab-icones.png",[1143,20682,20683,20687],{},[2006,20684,20686],{"href":15368,"rel":20685},[2010],"Nuxt Vitest module"," provides Vitest UI for tests runing with the same pipeline as your Nuxt app.",[1143,20689,20690],{},[2243,20691],{"alt":20692,"src":20693},"nuxt-devtools-tab-vitest","/assets/blog/devtools/tab-vitest.png",[1155,20695,20697],{"id":20696},"for-module-authors","For Module Authors",[1143,20699,20700,20701,20703],{},"With the release of ",[1220,20702,20187],{},", we improved the ability for module authors to contribute to the DevTools.",[1143,20705,20706],{},"It includes:",[1852,20708,20709,20712,20715,20718,20721,20731,20741],{},[1855,20710,20711],{},"Module contributed views",[1855,20713,20714],{},"Access to client app's context and devtools' utils",[1855,20716,20717],{},"Custom RPC functions to communicate between server and client",[1855,20719,20720],{},"Subprocesses spawning and output steaming",[1855,20722,20723,20730],{},[2006,20724,20727],{"href":20725,"rel":20726},"https://devtools.nuxtjs.org/module/utils-kit",[2010],[1220,20728,20729],{},"@nuxt/devtools-kit"," - a set of utilities help you integrate your module with DevTools",[1855,20732,20733,20740],{},[2006,20734,20737],{"href":20735,"rel":20736},"https://devtools.nuxtjs.org/module/ui-kit",[2010],[1220,20738,20739],{},"@nuxt/devtools-ui-kit"," - the UI components used in DevTools, to make your module's view consistent with the rest of DevTools",[1855,20742,20743],{},"Starter template to create module with DevTools integration",[1143,20745,20746,20747,20752],{},"Please check out the ",[2006,20748,20751],{"href":20749,"rel":20750},"https://devtools.nuxtjs.org/module/guide",[2010],"Devtools Module Authors Guide"," to learn more.",[1147,20754,20756],{"id":20755},"what-to-expect-next","What to Expect Next?",[1143,20758,20759],{},"This is just the beginning of the journey. We are planning to add more features to DevTools, while exploring the ways to present the data in more intuitive and playful ways.",[1143,20761,20762],{},"The goals of Nuxt DevTools are to:",[20764,20765,20768],"list",{"icon":20766,"type":20767},"uil:pathfinder","default","Improve transparency for conventions",[20764,20770,20772],{"icon":20771,"type":20767},"uil:tachometer-fast","Inspecting performance & analysis",[20764,20774,20776],{"icon":20775,"type":20767},"uil:swatchbook","Interactive & playful",[20764,20778,20780],{"icon":20779,"type":20767},"uil:file-bookmark-alt","Personalized documentations",[20764,20782,20784],{"icon":20783,"type":20767},"uil:create-dashboard","Manage and scaffold apps with ease",[20764,20786,20788],{"icon":20787,"type":20767},"uil:lightbulb-alt","Provide insights and improvements",[20764,20790,20792],{"icon":20791,"type":20767},"uil:user-check","Make the development experience more enjoyable",[4087,20794],{},[1143,20796,20797,20798,20803,20804,20807],{},"You can check our ",[2006,20799,20802],{"href":20800,"rel":20801},"https://github.com/nuxt/devtools/discussions/31",[2010],"Project Roadmap"," and share your ",[2006,20805,15569],{"href":15503,"rel":20806},[2010],", helping us to make the DevTools better.",[1143,20809,20810,20811,20815,20816,2281],{},"You can follow the latest updates by staring the ",[2006,20812,20814],{"href":9558,"rel":20813},[2010],"GitHub repository",", and following ",[2006,20817,20819],{"href":10289,"rel":20818},[2010],"Nuxt's official Twitter",[1143,20821,20822],{},"Thank you for reading, and we are looking forward to your feedback and contributions!",{"title":1218,"searchDepth":1233,"depth":1233,"links":20824},[20825,20826,20827,20845],{"id":20200,"depth":1233,"text":20201},{"id":15075,"depth":1233,"text":15076},{"id":20356,"depth":1233,"text":1072,"children":20828},[20829,20830,20831,20832,20833,20834,20835,20836,20837,20838,20839,20840,20841,20842,20843,20844],{"id":20376,"depth":1263,"text":942},{"id":207,"depth":1263,"text":776},{"id":179,"depth":1263,"text":353},{"id":20448,"depth":1263,"text":20449},{"id":199,"depth":1263,"text":143},{"id":175,"depth":1263,"text":39},{"id":211,"depth":1263,"text":784},{"id":20516,"depth":1263,"text":20517},{"id":20529,"depth":1263,"text":20530},{"id":20542,"depth":1263,"text":20543},{"id":20573,"depth":1263,"text":20574},{"id":20586,"depth":1263,"text":20587},{"id":20599,"depth":1263,"text":20600},{"id":20620,"depth":1263,"text":20621},{"id":20643,"depth":1263,"text":20644},{"id":20696,"depth":1263,"text":20697},{"id":20755,"depth":1233,"text":20756},"2023-03-27","Unleash the Developer Experience with Nuxt and understand your app better than ever.","/assets/blog/nuxt-devtools.png",{},{"title":1072,"description":20847},"O6MKulDhEb",{"id":20853,"title":1028,"authors":20854,"body":20857,"category":2176,"date":21535,"description":21536,"draft":108,"extension":1954,"image":21537,"meta":21538,"navigation":1739,"path":1029,"seo":21539,"stem":1030,"tags":6,"__hash__":21540},"blog/blog/10.v3-3.md",[20855],{"name":2190,"avatar":20856,"to":2193},{"src":2192},{"type":1140,"value":20858,"toc":21522},[20859,20863,20866,20879,20882,20918,20933,20938,20942,20963,20965,20979,20985,20998,21032,21043,21130,21144,21148,21160,21182,21189,21230,21247,21251,21275,21287,21291,21318,21348,21350,21358,21369,21384,21388,21396,21414,21425,21429,21451,21459,21479,21483,21498,21502,21516,21519],[1147,20860,20862],{"id":20861},"local-module-development-dx","✨ Local module development DX",[1143,20864,20865],{},"We've landed a raft of changes to enable local modules and improve DX.",[1143,20867,20868,20869,20873,20874,3681],{},"We now auto-scan your ",[2006,20870,20871],{"href":200},[1220,20872,8002],{}," folder and register top level files there as modules in your project (",[2006,20875,20878],{"href":20876,"rel":20877},"https://github.com/nuxt/nuxt/pull/19394",[2010],"#19394",[1143,20880,20881],{},"When these files are changed, we'll automatically restart the nuxt server.",[1213,20883,20885],{"className":16735,"code":20884,"language":16737,"meta":1218,"style":1218},"export default defineNuxtConfig({\n  modules: [\n    '@nuxtjs/tailwindcss',\n-   '~/modules/purge-comments'\n  ]\n})\n",[1220,20886,20887,20892,20897,20902,20909,20913],{"__ignoreMap":1218},[1223,20888,20889],{"class":1225,"line":1226},[1223,20890,20891],{"class":1285},"export default defineNuxtConfig({\n",[1223,20893,20894],{"class":1225,"line":1233},[1223,20895,20896],{"class":1285},"  modules: [\n",[1223,20898,20899],{"class":1225,"line":1263},[1223,20900,20901],{"class":1285},"    '@nuxtjs/tailwindcss',\n",[1223,20903,20904,20906],{"class":1225,"line":1296},[1223,20905,5004],{"class":1236},[1223,20907,20908],{"class":1240},"   '~/modules/purge-comments'\n",[1223,20910,20911],{"class":1225,"line":1325},[1223,20912,1795],{"class":1285},[1223,20914,20915],{"class":1225,"line":1355},[1223,20916,20917],{"class":1285},"})\n",[1143,20919,20920,20921,20924,20925,3114,20928,3681],{},"We also now expose ",[1220,20922,20923],{},"nuxt/kit"," for easy access to kit composables in your local project without having to install ",[1220,20926,20927],{},"@nuxt/kit",[2006,20929,20932],{"href":20930,"rel":20931},"https://github.com/nuxt/nuxt/pull/19422",[2010],"#19422",[1143,20934,20935,2281],{},[2006,20936,20937],{"href":200},"Read the documentation about local modules",[1147,20939,20941],{"id":20940},"️-restarting-nuxt","♻️ Restarting Nuxt",[1143,20943,20944,20945,20947,20948,20953,20954,20957,20958,3681],{},"You can add files to the ",[1220,20946,11003],{}," array to automatically restart the server (",[2006,20949,20952],{"href":20950,"rel":20951},"https://github.com/nuxt/nuxt/pull/19530",[2010],"#19530","). This is likely to be particularly useful for module authors. You can also trigger a restart of the Nuxt server with the new ",[1220,20955,20956],{},"restart"," hook (",[2006,20959,20962],{"href":20960,"rel":20961},"https://github.com/nuxt/nuxt/pull/19084",[2010],"#19084",[1147,20964,3968],{"id":3967},[1143,20966,20967,20968,20973,20974,3681],{},"We've increased static asset maxAge to 1 year as a matter of best practice (",[2006,20969,20972],{"href":20970,"rel":20971},"https://github.com/nuxt/nuxt/pull/19335",[2010],"#19335","), and support tree-shaking more of your build (",[2006,20975,20978],{"href":20976,"rel":20977},"https://github.com/nuxt/nuxt/pull/19508",[2010],"#19508",[1143,20980,20981],{},[2243,20982],{"alt":20983,"src":20984},"nuxt-performance-improvements","https://user-images.githubusercontent.com/28706372/224999169-6c047cca-9a5c-4637-8e4d-be6268964e08.png",[1143,20986,20987,20988,20992,20993,2887],{},"We also now support preloading ",[2006,20989,20990],{"href":394},[1220,20991,393],{}," with a route in object-syntax (",[2006,20994,20997],{"href":20995,"rel":20996},"https://github.com/nuxt/nuxt/pull/19120",[2010],"#19120",[1213,20999,21001],{"className":1215,"code":21000,"language":1217,"meta":1218,"style":1218},"\u003CNuxtLink :to=\"{ name: 'home', query: { year: '2023' } }\">Home\u003C/NuxtLink>\n",[1220,21002,21003],{"__ignoreMap":1218},[1223,21004,21005,21007,21009,21012,21014,21016,21019,21021,21023,21026,21028,21030],{"class":1225,"line":1226},[1223,21006,1237],{"class":1236},[1223,21008,5104],{"class":1240},[1223,21010,21011],{"class":1244}," :to",[1223,21013,1248],{"class":1236},[1223,21015,1251],{"class":1236},[1223,21017,21018],{"class":1254},"{ name: 'home', query: { year: '2023' } }",[1223,21020,1251],{"class":1236},[1223,21022,1282],{"class":1236},[1223,21024,21025],{"class":1285},"Home",[1223,21027,1289],{"class":1236},[1223,21029,5104],{"class":1240},[1223,21031,1260],{"class":1236},[1143,21033,21034,21035,3114,21038,3681],{},"We also track how long it takes each module you use to perform its setup, and warn if it takes too long. You can see all these values by running your dev server with ",[1220,21036,21037],{},"DEBUG=1",[2006,21039,21042],{"href":21040,"rel":21041},"https://github.com/nuxt/nuxt/pull/18648",[2010],"#18648",[1213,21044,21046],{"className":3586,"code":21045,"language":3588,"meta":1218,"style":1218},"DEBUG=1 npx nuxt dev\nℹ Module pages took 1.5ms to setup.\nℹ Module meta took 3.15ms to setup\nℹ Module components took 4.5ms to setup.\n...\n",[1220,21047,21048,21066,21088,21107,21125],{"__ignoreMap":1218},[1223,21049,21050,21053,21055,21058,21061,21063],{"class":1225,"line":1226},[1223,21051,21052],{"class":1285},"DEBUG",[1223,21054,1248],{"class":1236},[1223,21056,21057],{"class":1254},"1",[1223,21059,21060],{"class":2036}," npx",[1223,21062,3417],{"class":1254},[1223,21064,21065],{"class":1254}," dev\n",[1223,21067,21068,21071,21074,21077,21080,21083,21085],{"class":1225,"line":1233},[1223,21069,21070],{"class":2036},"ℹ",[1223,21072,21073],{"class":1254}," Module",[1223,21075,21076],{"class":1254}," pages",[1223,21078,21079],{"class":1254}," took",[1223,21081,21082],{"class":1254}," 1.5ms",[1223,21084,11109],{"class":1254},[1223,21086,21087],{"class":1254}," setup.\n",[1223,21089,21090,21092,21094,21097,21099,21102,21104],{"class":1225,"line":1263},[1223,21091,21070],{"class":2036},[1223,21093,21073],{"class":1254},[1223,21095,21096],{"class":1254}," meta",[1223,21098,21079],{"class":1254},[1223,21100,21101],{"class":1254}," 3.15ms",[1223,21103,11109],{"class":1254},[1223,21105,21106],{"class":1254}," setup\n",[1223,21108,21109,21111,21113,21116,21118,21121,21123],{"class":1225,"line":1296},[1223,21110,21070],{"class":2036},[1223,21112,21073],{"class":1254},[1223,21114,21115],{"class":1254}," components",[1223,21117,21079],{"class":1254},[1223,21119,21120],{"class":1254}," 4.5ms",[1223,21122,11109],{"class":1254},[1223,21124,21087],{"class":1254},[1223,21126,21127],{"class":1225,"line":1325},[1223,21128,21129],{"class":1751},"...\n",[1143,21131,21132,21133,21138,21139,3681],{},"You can also opt-in to some of Nuxt's internal optimisations by configuring composables to be treeshaken in a particular environment (",[2006,21134,21137],{"href":21135,"rel":21136},"https://github.com/nuxt/nuxt/pull/19383",[2010],"#19383",") or to have magic keys automatically injected (",[2006,21140,21143],{"href":21141,"rel":21142},"https://github.com/nuxt/nuxt/pull/19490",[2010],"#19490",[1147,21145,21147],{"id":21146},"error-handling","🐛 Error handling",[1143,21149,21150,21151,21156,21157,2281],{},"We now handle chunk errors by default (",[2006,21152,21155],{"href":21153,"rel":21154},"https://github.com/nuxt/nuxt/pull/19086",[2010],"#19086","), meaning if your site updates with a redeploy, ",[1159,21158,21159],{},"we automatically handle reloading it on navigation",[1143,21161,21162,21163,9652,21166,21169,21170,21176,21177,2281],{},"To disable this behavior, set ",[1220,21164,21165],{},"experimental.emitRouteChunkError",[1220,21167,21168],{},"'manual'"," and handle it yourself with the new ",[2006,21171,21174],{"href":21172,"rel":21173},"https://nuxt.com/docs/api/utils/reload-nuxt-app",[2010],[1220,21175,635],{}," composable. Learn more how we implemented in our ",[2006,21178,21181],{"href":21179,"rel":21180},"https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/plugins/chunk-reload.client.ts",[2010],"chunk-reload.client.ts plugin",[1143,21183,21184,21185,21188],{},"You can also set ",[1220,21186,21187],{},"experimental.restoreState"," to preserve some of your app state across reloads:",[1213,21190,21192],{"className":1669,"code":21191,"filename":260,"language":1672,"meta":1218,"style":1218},"defineNuxtConfig({\n  experimental: {\n    restoreState: true\n  }\n})\n",[1220,21193,21194,21203,21211,21220,21224],{"__ignoreMap":1218},[1223,21195,21196,21199,21201],{"class":1225,"line":1226},[1223,21197,21198],{"class":1751},"defineNuxtConfig",[1223,21200,1754],{"class":1285},[1223,21202,1757],{"class":1236},[1223,21204,21205,21207,21209],{"class":1225,"line":1233},[1223,21206,3074],{"class":1240},[1223,21208,1765],{"class":1236},[1223,21210,1891],{"class":1236},[1223,21212,21213,21216,21218],{"class":1225,"line":1263},[1223,21214,21215],{"class":1240},"    restoreState",[1223,21217,1765],{"class":1236},[1223,21219,3088],{"class":2928},[1223,21221,21222],{"class":1225,"line":1296},[1223,21223,1990],{"class":1236},[1223,21225,21226,21228],{"class":1225,"line":1325},[1223,21227,1801],{"class":1236},[1223,21229,1804],{"class":1285},[1143,21231,21232,21233,3114,21237,21242,21243,21246],{},"We also have a new experimental error handling component: ",[2006,21234,21235],{"href":369},[1220,21236,368],{},[2006,21238,21241],{"href":21239,"rel":21240},"https://github.com/nuxt/framework/pull/8216",[2010],"#8216",") which can capture errors rendering on server, replace them with fallback content, and granularly trigger rerendering the part with an error on the client. This can be enabled with ",[1220,21244,21245],{},"experimental.clientFallback"," - feedback very welcome!",[1147,21248,21250],{"id":21249},"️-head-improvements","⚡️ Head improvements",[1143,21252,21253,21254,21258,21259,21264,21265,21268,21269,21274],{},"We've migrated to use ",[2006,21255,2291],{"href":21256,"rel":21257},"https://github.com/unjs/unhead",[2010]," directly (",[2006,21260,21263],{"href":21261,"rel":21262},"https://github.com/nuxt/nuxt/pull/19519",[2010],"#19519",") - and automatically tree-shake server-only head composables like ",[1220,21266,21267],{},"useServerHead"," from your client build (",[2006,21270,21273],{"href":21271,"rel":21272},"https://github.com/nuxt/nuxt/pull/19576",[2010],"#19576","), meaning you can have great SEO without needing to include meta tag logic that's relevant only for crawlers in your client build.",[1143,21276,11175,21277,21281,21282,3681],{},[2006,21278,21279],{"href":453},[1220,21280,452],{}," composable that handles sanitising untrusted user input (",[2006,21283,21286],{"href":21284,"rel":21285},"https://github.com/nuxt/nuxt/pull/19548",[2010],"#19548",[1147,21288,21290],{"id":21289},"better-logging-in-browser-devtools","🪵 Better logging in browser DevTools",[1143,21292,21293,21294,21299,21300,4363,21305,21310,21311,2281],{},"Working with the Chrome DevTools team, we've landed a couple of features across the unjs + Nuxt ecosystem meaning we now have first-class support for hiding Nuxt internal stack traces from logs in your (Chromium-based, for now) browser ",[2006,21295,21298],{"href":21296,"rel":21297},"https://github.com/nuxt/nuxt/pull/19243",[2010],"#19243",". We also landed a couple of improvements with stacktraces involving Nuxt hooks (",[2006,21301,21304],{"href":21302,"rel":21303},"https://github.com/unjs/hookable/pull/69",[2010],"unjs/hookable#69",[2006,21306,21309],{"href":21307,"rel":21308},"https://github.com/unjs/hookable/pull/68",[2010],"unjs/hookable#68",") implementing ",[2006,21312,21315],{"href":21313,"rel":21314},"https://developer.chrome.com/blog/devtools-modern-web-debugging/#linked-stack-traces",[2010],[1220,21316,21317],{},"console.createTask",[1509,21319,21320,21330],{},[1512,21321,21322],{},[1515,21323,21324,21327],{},[1518,21325,21326],{},"Before",[1518,21328,21329],{},"After",[1528,21331,21332],{},[1515,21333,21334,21341],{},[1533,21335,21336],{},[2243,21337],{"width":21338,"alt":21339,"src":21340},529,"before-nuxt-console-improvements","https://user-images.githubusercontent.com/28706372/220933126-56d9a0e5-e846-4958-a40a-e528a48bcb32.png",[1533,21342,21343],{},[2243,21344],{"width":21345,"alt":21346,"src":21347},534,"after-nuxt-console-improvements","https://user-images.githubusercontent.com/28706372/220932932-932f193b-59a6-4385-8796-a62dcfd59c20.png",[1147,21349,8232],{"id":8231},[1143,21351,21352,21353,3681],{},"Types for server API routes are now more correct - with non-serialisable types stripped out of the return type (",[2006,21354,21357],{"href":21355,"rel":21356},"https://github.com/unjs/nitro/pull/1002",[2010],"unjs/nitro#1002",[1143,21359,21360,21361,21363,21364,3681],{},"We also now type more of ",[1220,21362,311],{}," and correctly type unknown injections for greater type-safety (",[2006,21365,21368],{"href":21366,"rel":21367},"https://github.com/nuxt/nuxt/pull/19643",[2010],"#19643",[1143,21370,21371,21372,21375,21376,21378,21379,3681],{},"And if you were struggling with correct types when using ",[1220,21373,21374],{},"transform"," + ",[1220,21377,20767],{}," with Nuxt data fetching composables, fear no more - we now infer the types correctly (",[2006,21380,21383],{"href":21381,"rel":21382},"https://github.com/nuxt/nuxt/pull/19487",[2010],"#19487",[1147,21385,21387],{"id":21386},"️-nitro-enhancements","⚗️ Nitro enhancements",[1143,21389,21390,21391,14288],{},"This release comes with Nitro v2.3, which brings lots of improvements of its own. Check out ",[2006,21392,21395],{"href":21393,"rel":21394},"https://github.com/unjs/nitro/releases/tag/v2.3.0",[2010],"the release",[1143,21397,19960,21398,21402,21403,21408,21409,21413],{},[2006,21399,21400],{"href":429},[1220,21401,428],{}," in nitro server routes (",[2006,21404,21407],{"href":21405,"rel":21406},"https://github.com/nuxt/nuxt/pull/19489",[2010],"#19489",") - a long-awaited change. Now ",[2006,21410,21411],{"href":429},[1220,21412,428],{}," is consistently available throughout your app for non-runtime configuration from layers, modules, etc.",[1143,21415,10623,21416,21419,21420,3681],{},[1220,21417,21418],{},"nitro:build:public-assets"," hook to allow modifying assets output from nitro's prerender/build phase (",[2006,21421,21424],{"href":21422,"rel":21423},"https://github.com/nuxt/nuxt/pull/19638",[2010],"#19638",[1147,21426,21428],{"id":21427},"️-build-changes","🛠️ Build changes",[1143,21430,21431,21432,21440,21441,4363,21446,3681],{},"As part of moving towards ",[2006,21433,21436,21437],{"href":21434,"rel":21435},"https://github.com/nuxt/nuxt/issues/14146",[2010],"first-class support for PNP and pnpm support without ",[1220,21438,21439],{},"--shamefully-hoist",", we've dropped support for some internal (deprecated) utilities using CJS resolve patterns (",[2006,21442,21445],{"href":21443,"rel":21444},"https://github.com/nuxt/nuxt/pull/19537",[2010],"#19537",[2006,21447,21450],{"href":21448,"rel":21449},"https://github.com/nuxt/nuxt/pull/19608",[2010],"#19608",[1143,21452,21453,21454,5062,21456,21458],{},"We also now resolve dependencies like ",[1220,21455,2367],{},[1220,21457,20927],{}," and more using ESM search-paths. We'll be keeping a close eye on this.",[1143,21460,21461,21462,21467,21468,2420,21471,21474,21475,21478],{},"We're also preparing the groundwork for support of new TypeScript Node16 module resolution (",[2006,21463,21466],{"href":21464,"rel":21465},"https://github.com/nuxt/nuxt/issues/19606",[2010],"#19606","), and as part of this have changed the format of our runtime output (using ",[1220,21469,21470],{},".js",[1220,21472,21473],{},".mjs"," extensions, providing ",[1220,21476,21477],{},"types"," fields for subpath exports, and more).",[1147,21480,21482],{"id":21481},"️-custom-config-schema-advanced","🗺️ Custom config schema (advanced)",[1143,21484,21485,21486,21491,21492,21497],{},"We've been testing out an experimental feature to allow modules and users to extend the Nuxt config schema (",[2006,21487,21490],{"href":21488,"rel":21489},"https://github.com/nuxt/nuxt/issues/15592",[2010],"#15592","), and we've now enabled this by default (",[2006,21493,21496],{"href":21494,"rel":21495},"https://github.com/nuxt/nuxt/pull/19172",[2010],"#19172","). We expect this will be particularly useful for module and layer/theme authors, and should result in some nicer DX for their users.",[1147,21499,21501],{"id":21500},"changelog","Changelog",[1143,21503,21504,21505,21510,21511,2281],{},"See the full changelog by ",[2006,21506,21509],{"href":21507,"rel":21508},"https://github.com/nuxt/nuxt/compare/v3.2.3...v3.3.0",[2010],"comparing the changes"," or checkout the ",[2006,21512,21515],{"href":21513,"rel":21514},"https://github.com/nuxt/nuxt/releases/tag/v3.3.0",[2010],"release on GitHub",[1143,21517,21518],{},"We would like to thank all the 28 contributors who helped on this release 💚",[2160,21520,21521],{},"html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}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 .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .sagxc, html code.shiki .sagxc{--shiki-light:#FF5370;--shiki-default:#FF5370;--shiki-dark:#FF9CAC}",{"title":1218,"searchDepth":1233,"depth":1233,"links":21523},[21524,21525,21526,21527,21528,21529,21530,21531,21532,21533,21534],{"id":20861,"depth":1233,"text":20862},{"id":20940,"depth":1233,"text":20941},{"id":3967,"depth":1233,"text":3968},{"id":21146,"depth":1233,"text":21147},{"id":21249,"depth":1233,"text":21250},{"id":21289,"depth":1233,"text":21290},{"id":8231,"depth":1233,"text":8232},{"id":21386,"depth":1233,"text":21387},{"id":21427,"depth":1233,"text":21428},{"id":21481,"depth":1233,"text":21482},{"id":21500,"depth":1233,"text":21501},"2023-03-14","The 3.3.0 is a minor (feature) release with lots of performance and DX improvements, bug fixes and new features to play with.","/assets/blog/v3-3.png",{},{"title":1028,"description":21536},"zEUfwJOgrf",{"id":21542,"title":1052,"authors":21543,"body":21546,"category":2176,"date":21759,"description":21760,"draft":108,"extension":1954,"image":21761,"meta":21762,"navigation":1739,"path":1053,"seo":21763,"stem":1054,"tags":6,"__hash__":21764},"blog/blog/2.vision-2023.md",[21544],{"name":2190,"avatar":21545,"to":2193},{"src":2192},{"type":1140,"value":21547,"toc":21751},[21548,21552,21555,21571,21578,21585,21588,21591,21595,21598,21615,21621,21625,21635,21641,21644,21659,21662,21666,21669,21678,21688,21692,21695,21698,21702,21705,21717,21720,21723,21731,21735,21738,21741,21744,21746,21749],[21549,21550,1052],"h1",{"id":21551},"nuxt-a-vision-for-2023",[1143,21553,21554],{},"This past year has been an exciting one. Looking into the new year, there is a lot we have planned as a team and we'd love to share it with you. ✨",[1143,21556,21557,21558,21562,21563,21566,21567,3681],{},"This past year has been an exciting one, with the release of Nuxt 3 and Nitro and the launch of the new ",[2006,21559,2573],{"href":21560,"rel":21561},"http://nuxt.com/",[2010]," website. It's been the culmination of years of work, and has not only resulted in a new major version of Nuxt, but a new Nuxt architecture, a full-stack server framework (",[2006,21564,738],{"href":18002,"rel":21565},[2010],"), and a new GitHub organisation and ecosystem (",[2006,21568,10247],{"href":21569,"rel":21570},"https://github.com/unjs/",[2010],[1143,21572,21573,21574,21577],{},"Throughout that whole time, ",[2006,21575,10194],{"href":10192,"rel":21576},[2010]," has led the Nuxt team, putting in countless hours of work and thought into building Nuxt 3.",[1143,21579,21580,21581,21584],{},"Now, at the start of 2023, he's handing over the helm of the Nuxt open-source work to me (",[2006,21582,2190],{"href":7669,"rel":21583},[2010],"). Pooya will continue to be actively contributing to the Nuxt project and of course driving the development of UnJS ecosystem and Nitro project.",[1143,21586,21587],{},"This is a real honour and I'm hugely pleased to be able to work with the rest of the team and the community to continue to drive Nuxt forward to be the intuitive way to build a web application using Vue. 😊",[1143,21589,21590],{},"Looking into the new year, there is a lot we have planned as a team and we'd love to share it with you.",[1147,21592,21594],{"id":21593},"unifying-nuxt","Unifying Nuxt",[1143,21596,21597],{},"One important change will be unifying Nuxt into a single repository.",[1143,21599,21600,21601,21604,21605,21608,21609,21614],{},"As a complete rewrite of Nuxt 2, Nuxt 3 has been developed in a separate repository: ",[1220,21602,21603],{},"nuxt/framework",". Nuxt 3 even has its own documentation on ",[2006,21606,2573],{"href":21560,"rel":21607},[2010],", versus the Nuxt 2 documentation on ",[2006,21610,21613],{"href":21611,"rel":21612},"https://v2.nuxt.com",[2010],"v2.nuxt.com",". In development, this helped us move faster but meant less attention on issues for Nuxt 2. It's also a bit confusing.",[1143,21616,21617,21618,21620],{},"So in the coming days, we'll be unifying the Nuxt repos into a single repository, ",[1220,21619,8349],{},". We'll transfer all issues and discussions across, of course, clearly labeling them as to which version of Nuxt they affect. This will also provide us an opportunity to close out issues and RFCs that we've resolved or implemented in Nuxt 3.",[1147,21622,21624],{"id":21623},"new-website","New Website",[1143,21626,21627,21628,21631,21632,2281],{},"This last year brought us the launch of ",[2006,21629,2573],{"href":21560,"rel":21630},[2010]," and the unveiling of Nuxt's ",[2006,21633,21634],{"href":16942},"new logo",[1143,21636,21637],{},[2243,21638],{"alt":21639,"src":21640},"Screenshot of the new nuxt.com","https://user-images.githubusercontent.com/28706372/212973698-91fce9a6-e9ef-4fdc-ad63-9b3924c41704.png",[1143,21642,21643],{},"We'd like to make this website the central place for everything Nuxt. That includes:",[1852,21645,21646,21649,21652],{},[1855,21647,21648],{},"migrating Nuxt 2 documentation so there's a single website to check (with a version switcher)",[1855,21650,21651],{},"documentation for community modules (using multi-source to pull them from their own repositories)",[1855,21653,21654,21655,21658],{},"revamped ",[2006,21656,21657],{"href":813},"examples"," that show off more real use cases, including authentication, monorepos and more",[1143,21660,21661],{},"We have some other exciting plans for the website, but I don't want to reveal too much, other than to say that we'll also (of course!) be open-sourcing the website soon.",[1147,21663,21665],{"id":21664},"key-modules","Key Modules",[1143,21667,21668],{},"The modules ecosystem is an incredibly powerful one, and we are grateful to all the module authors who extend Nuxt with so many features. Today we have more than 60 modules compatible with Nuxt 3. Our goal is to continue to empower module development as well as make sure that the most used modules in Nuxt 2 are updated or have a straightforward migration path.",[1143,21670,21671,21672,21675,21676,2281],{},"The main priorities at the start of the year are ",[1220,21673,21674],{},"nuxt/image",", PWA and ",[1220,21677,10158],{},[1143,21679,21680,21681,4363,21684,21687],{},"We're also developing RFCs for ",[1220,21682,21683],{},"nuxt/font",[1220,21685,21686],{},"nuxt/script"," in conjunction with the Google Aurora team, which will make it much easier to apply best performance practices to your Nuxt apps. Watch this space!",[1147,21689,21691],{"id":21690},"dx-and-performance","DX and Performance",[1143,21693,21694],{},"We particularly care a lot about making Nuxt a joy to use, and we'd like to keep pushing the boundary of great developer experience, which we believe results in the best experience for users of the apps we write too.",[1143,21696,21697],{},"In the coming months, there will be a continued focus on developer experience and performance. Expect to see Nuxt DevTools and CLI improvements for scaffolding - and more. On the performance side, Nuxt 3 + Nitro is a game-changer for speed, performance, and customisability, and we’ll be building on top of that to enable some amazing features. 🚀",[1147,21699,21701],{"id":21700},"a-new-release-cycle","A New Release Cycle",[1143,21703,21704],{},"It's important to know what's coming, and we're going to be spending some time making sure we communicate clearly about what's happening with Nuxt through regular updates like this one.",[1143,21706,21707,21708,21713,21714,2281],{},"On top of that, we're planning a consistent release cycle, following ",[2006,21709,21712],{"href":21710,"rel":21711},"https://semver.org/",[2010],"semver",". We'll aim for major framework releases every year, with an expectation of patch releases every week or so and minor releases every month or so. They should never contain breaking changes except within options clearly marked as ",[1220,21715,21716],{},"experimental",[1143,21718,21719],{},"One comment: We don't want there to be as big a gap (either in time or in breaking changes) between 3 -> 4 as there was between 2 -> 3, so, when the time comes for Nuxt 4, expect a much more gentle upgrade!",[1143,21721,21722],{},"In the upcoming 3.1.0 release, you can already find a host of bug fixes as well as:",[1852,21724,21725,21728],{},[1855,21726,21727],{},"experimental server-only components and a component island renderer",[1855,21729,21730],{},"Nitro 2, Vite 4 and Rollup 3 support",[1147,21732,21734],{"id":21733},"migrating-to-nuxt-3","Migrating to Nuxt 3",[1143,21736,21737],{},"On December 31st, 2023, Vue 2 will reach End of Life (EOL), and with it Nuxt 2. Both Vue and Nuxt will continue being available and working for many people, but at the same time, many companies and users will want to transition to Nuxt 3 (and we'd encourage this!).",[1143,21739,21740],{},"Part of our focus this year therefore will be supporting everyone who wants to migrate their apps to Nuxt 3. We'll also be working to backport key bug fixes and security fixes to Nuxt 2.",[1143,21742,21743],{},"In addition, there is Nuxt Bridge. It was built as a module to bring features and bug fixes from Nuxt 3 back to Nuxt 2, although it has not yet been released in a stable version. We plan to stabilise and release it in the next month or so, but our main focus over the course of the year will be on helping people transition to Nuxt 3.",[4087,21745],{},[1143,21747,21748],{},"It’s a privilege to be part of this community, and we wish you a very Happy New Year! 💚",[1143,21750,10400],{},{"title":1218,"searchDepth":1233,"depth":1233,"links":21752},[21753,21754,21755,21756,21757,21758],{"id":21593,"depth":1233,"text":21594},{"id":21623,"depth":1233,"text":21624},{"id":21664,"depth":1233,"text":21665},{"id":21690,"depth":1233,"text":21691},{"id":21700,"depth":1233,"text":21701},{"id":21733,"depth":1233,"text":21734},"2023-01-17","This past year has been an exciting one. Looking into the new year, there is a lot we have planned as a team and we'd love to share it with you.","/assets/blog/nuxt-a-vision-for-2023.png",{},{"title":1052,"description":21760},"pnqvDcI7MI",{"id":21766,"title":1024,"authors":21767,"body":21773,"category":2176,"date":21911,"description":21912,"draft":108,"extension":1954,"image":21913,"meta":21914,"navigation":1739,"path":1025,"seo":21915,"stem":1026,"tags":6,"__hash__":21916},"blog/blog/1.v3.md",[21768],{"name":10194,"avatar":21769,"to":21771,"twitter":21772},{"src":21770},"https://github.com/pi0.png","https://x.com/_pi0_","_pi0_",{"type":1140,"value":21774,"toc":21905},[21775,21779,21782,21797,21802,21806,21816,21819,21823,21853,21860,21864,21873,21877,21880,21894,21902],[21549,21776,21778],{"id":21777},"announcing-nuxt-30-stable","Announcing Nuxt 3.0 stable",[1143,21780,21781],{},"We are thrilled to announce the first stable version of Nuxt 3.0.0 ✨",[1143,21783,21784,21785,5062,21788,7856,21793,21796],{},"Nuxt 3 is a modern rewrite of the Nuxt framework based on ",[2006,21786,973],{"href":20209,"rel":21787},[2010],[2006,21789,21792],{"href":21790,"rel":21791},"https://vuejs.org/",[2010],"Vue3",[2006,21794,738],{"href":18002,"rel":21795},[2010]," with first-class TypeScript support and the result of more than two years of research, community feedback, innovation, and experiment to make a pleasant full-stack Developer Experience for Vue development to everyone.",[1143,21798,21799],{},[2006,21800,21801],{"href":20},"[Read More In the Documentation]",[1147,21803,21805],{"id":21804},"api-stability","API Stability",[1143,21807,21808,21809,21812,21813,21815],{},"Nuxt 3.0.0 comes with a stable, production-ready API and 50+ ",[2006,21810,21811],{"href":15060},"supported modules"," built using ",[2006,21814,307],{"href":304}," by the community and Nuxt team.",[1143,21817,21818],{},"All composables, filesystem conventions, and configurations are guaranteed to be backward compatible with Nuxt 3.0.0. Due to the nature of the meta-frameworks, some changes happen when we upgrade the underlying dependencies (vite, rollup, and nitropack). Thanks to the new Nuxt Kit and Schema tools, such upgrades will be backward compatible as long as you are using documented features. Kit and Schema also guarantee better future compatibility. This makes it faster for us to iterate and plan the next major versions of Nuxt.",[1147,21820,21822],{"id":21821},"the-browser-and-nodejs-support","The browser and Node.js support",[1143,21824,21825,21826,21831,21832,21837,21838,8602,21843,21848,21849,21852],{},"Nuxt 3 officially supports evergreen browsers only. The \"core browser set\" is what we (And ",[2006,21827,21830],{"href":21828,"rel":21829},"http://web.dev",[2010],"web.dev"," team) believe most developers need to support most of the time in the absence of specific constraints. It takes into account ",[2006,21833,21836],{"href":21834,"rel":21835},"https://caniuse.com/usage-table",[2010],"usage numbers",", developer expectations, and ",[2006,21839,21842],{"href":21840,"rel":21841},"https://make.wordpress.org/core/handbook/best-practices/browser-support/",[2010],"existing support in",[2006,21844,21847],{"href":21845,"rel":21846},"https://angular.io/guide/browser-support",[2010],"the ecosystem",". The core browser set targets the ",[1159,21850,21851],{},"2 most recent major versions"," of Chrome, Firefox, and Edge on a monthly basis and Safari on a yearly basis.",[1143,21854,21855,21856,21859],{},"On the server side, Nuxt 3 supports Node.js 14, 16, 18, and 19 at the moment. We encourage everyone to use the latest LTS releases of Node.js, we push them once ",[1159,21857,21858],{},"widely adopted by major deployment platforms",". This means we keep supporting Node.js versions as long as they are supported by the Node.js team on a rolling basis in non-major releases of Nuxt. Since 14.x is being end-of-life soon, we highly encourage you to update to the latest 18.x whenever possible.",[1147,21861,21863],{"id":21862},"we-love-community","We Love Community",[1143,21865,21866,21867,21872],{},"Nuxt wouldn’t be possible today without an amazing community making amazing modules, feedback, and contributions every day. Check our ",[2006,21868,21871],{"href":21869,"rel":21870},"https://nuxt.com/docs/community/getting-help",[2010],"Community Documentation"," to be involved!",[1147,21874,21876],{"id":21875},"to-the-future","To the Future",[1143,21878,21879],{},"Releasing Nuxt 3 is a big milestone for us and opens a future-proof basis for new ideas and trust for the users to build their enterprise projects with Nuxt 3.",[1143,21881,21882,21883,4363,21888,21893],{},"Server Component Islands, WebSocket layer, new Deployment presets, improved CLI and DevTools and Testing infra are a few to mention. Keep an eye on the ",[2006,21884,21887],{"href":21885,"rel":21886},"https://nuxt.com/docs/community/roadmap",[2010],"roadmap page",[2006,21889,21892],{"href":21890,"rel":21891},"https://github.com/nuxt/nuxt/discussions",[2010],"GitHub discussions"," for updates.",[1143,21895,21896,21897,21901],{},"NuxtLabs is working on ",[2006,21898,21900],{"href":10040,"rel":21899},[2010],"new product"," and solutions on top of Nuxt 3 at the time of writing this article.",[1143,21903,21904],{},"Stay tuned for more exciting news and Happy Nuxting 💚",{"title":1218,"searchDepth":1233,"depth":1233,"links":21906},[21907,21908,21909,21910],{"id":21804,"depth":1233,"text":21805},{"id":21821,"depth":1233,"text":21822},{"id":21862,"depth":1233,"text":21863},{"id":21875,"depth":1233,"text":21876},"2022-11-16","We are thrilled to announce the first stable version of Nuxt 3.0.0","/assets/blog/v3.png",{},{"title":1024,"description":21912},"HsNEUvNbBe",{"id":21918,"title":1076,"authors":21919,"body":21936,"category":2176,"date":22273,"description":22274,"draft":108,"extension":1954,"image":22275,"meta":22276,"navigation":1739,"path":1077,"seo":22277,"stem":1078,"tags":6,"__hash__":22278},"blog/blog/3.nuxt3-rc.md",[21920,21922,21924,21926,21931],{"name":1130,"avatar":21921,"to":1133,"twitter":7721},{"src":7720},{"name":2190,"avatar":21923,"to":2193},{"src":2192},{"name":4066,"avatar":21925,"to":4069},{"src":4068},{"name":21927,"avatar":21928,"to":21930},"Alexandre Chopin",{"src":21929},"https://github.com/alexchopin.png","https://x.com/thewikeo",{"name":21932,"avatar":21933,"to":21935},"Clement Ollivier",{"src":21934},"https://github.com/clemcode.png","https://x.com/clemcodes",{"type":1140,"value":21937,"toc":22268},[21938,21952,21961,21965,21984,21990,22002,22010,22014,22023,22028,22043,22046,22063,22065,22068,22231,22250,22253,22261],[1143,21939,21940,21941,21945,21946,21951],{},"We are excited to open source Nuxt 3 after more than a year of intense development. The repository is available on GitHub on ",[2006,21942,8349],{"href":21943,"rel":21944},"https://go.nuxt.com/github",[2010]," under the ",[2006,21947,21950],{"href":21948,"rel":21949},"https://go.nuxt.com/license",[2010],"MIT"," license.",[7733,21953,21954],{},[1143,21955,21956,21957,2281],{},"The documentation is available on ",[2006,21958,21959],{"href":21959,"rel":21960},"https://nuxt.com",[2010],[1147,21962,21964],{"id":21963},"a-new-foundation","A new foundation",[1143,21966,21967,21968,6381,21973,21977,21978,21983],{},"On top of supporting ",[2006,21969,21972],{"href":21970,"rel":21971},"https://vuejs.org",[2010],"Vue 3",[2006,21974,973],{"href":21975,"rel":21976},"https://vitejs.dev",[2010],", Nuxt 3 contains a new ",[2006,21979,21982],{"href":21980,"rel":21981},"https://nuxt.com/docs/guide/concepts/server-engine",[2010],"server engine",", unlocking new full-stack capabilities to Nuxt server and beyond. It's the first JavaScript application server that is portable across a variety of modern cloud hosting providers.",[1143,21985,21986,21987,21989],{},"In production, it builds your Vue application and server into one universal ",[1220,21988,171],{}," directory. This output is light: minified and without any other Node.js dependencies (except polyfills). You can deploy this output on any system supporting JavaScript, whether Node.js, Serverless, Workers, Edge-side rendering or purely static.",[1143,21991,21992,21995,21996,22001],{},[1159,21993,21994],{},"Bonus:"," this server engine can be used on existing Nuxt 2 projects with ",[2006,21997,22000],{"href":21998,"rel":21999},"https://nuxt.com/docs/getting-started/bridge",[2010],"Nuxt Bridge"," 🚀",[1143,22003,22004,22005,22009],{},"Head over the ",[2006,22006,22008],{"href":21959,"rel":22007},[2010],"Nuxt 3 homepage"," to learn more about Nuxt Nitro and Nuxt Bridge.",[1147,22011,22013],{"id":22012},"important-notes","Important notes",[1143,22015,22016,22017,22022],{},"Nuxt 3 is currently in beta, so expect things to break (and be fixed quickly). We have ",[2006,22018,22021],{"href":22019,"rel":22020},"https://github.com/nuxt/nuxt/issues",[2010],"plenty of work left"," but we want to open it publicly to gather feedback and contributions from the community 💚",[1143,22024,22025],{},[1159,22026,22027],{},"Do not use it for production until we reach the first release candidate.",[1143,22029,22030,22031,22036,22037,22042],{},"During the beta, almost every commit will ",[2006,22032,22035],{"href":22033,"rel":22034},"https://github.com/nuxt/nuxt/blob/main/.github/workflows/ci.yml#L111-L119",[2010],"trigger a new npm release","; you may want to look at the ",[2006,22038,22041],{"href":22039,"rel":22040},"https://github.com/nuxt/nuxt/pulls?q=is%3Apr+is%3Amerged",[2010],"merged pull requests"," until we begin generating automated changelogs in the documentation.",[1143,22044,22045],{},"We are working every day to improve the documentation, explaining as much as possible all the concepts, features and usage of Nuxt 3.",[1143,22047,22048,22049,5062,22053,6381,22058,2281],{},"Check out the community section of the Nuxt 3 website for ",[2006,22050,22052],{"href":21869,"rel":22051},[2010],"getting help",[2006,22054,22057],{"href":22055,"rel":22056},"https://nuxt.com/docs/community/reporting-bugs",[2010],"reporting bugs",[2006,22059,22062],{"href":22060,"rel":22061},"https://nuxt.com/docs/community/contribution",[2010],"contributing to the framework",[1147,22064,15271],{"id":15270},[1143,22066,22067],{},"Here some major milestones we've achieved on the way to Nuxt 3:",[20764,22069,22070],{},[1852,22071,22072,22078,22084,22097,22106,22117,22126,22137,22146,22156,22171,22183,22189,22195,22206,22212],{},[1855,22073,22074,22077],{},[1159,22075,22076],{},"Jul 2, 2020",": Nuxt 3 first commit with full TypeScript rewrite",[1855,22079,22080,22083],{},[1159,22081,22082],{},"Aug 7, 2020",": Webpack 5 support",[1855,22085,22086,8598,22089,22096],{},[1159,22087,22088],{},"Sep 15, 2020",[2006,22090,22093],{"href":22091,"rel":22092},"https://nuxt.com/docs/guide/directory-structure/pages",[2010],[1220,22094,22095],{},"pages/"," support",[1855,22098,22099,8598,22102,22105],{},[1159,22100,22101],{},"Oct 29, 2020",[2006,22103,21972],{"href":21970,"rel":22104},[2010]," support with bundle-renderer",[1855,22107,22108,8598,22111,22116],{},[1159,22109,22110],{},"Nov 2, 2020",[2006,22112,22115],{"href":22113,"rel":22114},"https://nuxt.com/guide/concepts/server-engine",[2010],"Nuxt Nitro"," initial work",[1855,22118,22119,22122,22123,22096],{},[1159,22120,22121],{},"Jan 22, 2021",": Initial ",[2006,22124,973],{"href":21975,"rel":22125},[2010],[1855,22127,22128,22131,22132],{},[1159,22129,22130],{},"Feb 4, 2021",": Nuxt can deploy on ",[2006,22133,22136],{"href":22134,"rel":22135},"https://nuxt.com/docs/getting-started/deployment",[2010],"major serverless platforms",[1855,22138,22139,8598,22142,22145],{},[1159,22140,22141],{},"Mar 6, 2021",[2006,22143,10247],{"href":12553,"rel":22144},[2010]," organisation created on GitHub",[1855,22147,22148,22151,22152,2541],{},[1159,22149,22150],{},"Mar 28, 2021",": Init Nuxt Kit and Nuxt CLI (",[2006,22153,11566],{"href":22154,"rel":22155},"https://nuxt.com/docs/api/commands/add",[2010],[1855,22157,22158,8598,22161,22167,22168,22170],{},[1159,22159,22160],{},"May 20, 2021",[2006,22162,22165],{"href":22163,"rel":22164},"https://nuxt.com/docs/guide/directory-structure/app",[2010],[1220,22166,248],{}," support (",[1220,22169,22095],{}," becomes optional)",[1855,22172,22173,8598,22176,22096],{},[1159,22174,22175],{},"Jun 30, 2021",[2006,22177,22180],{"href":22178,"rel":22179},"https://nuxt.com/docs/guide/directory-structure/layouts",[2010],[1220,22181,22182],{},"layouts/",[1855,22184,22185,22188],{},[1159,22186,22187],{},"Jul 15, 2021",": Native ESM support",[1855,22190,22191,22194],{},[1159,22192,22193],{},"Aug 10, 2021",": Auto import of composables and components",[1855,22196,22197,22200,22201,22205],{},[1159,22198,22199],{},"Sep 5, 2021",": Init ",[2006,22202,22000],{"href":22203,"rel":22204},"https://nuxt.com/docs/bridge/overview",[2010]," for improving Nuxt 2 experience",[1855,22207,22208,22211],{},[1159,22209,22210],{},"Sep 7, 2021",": Support Vite build for production",[1855,22213,22214,22217,22218,4363,22224,22230],{},[1159,22215,22216],{},"Oct 11, 2021",": Add ",[2006,22219,22222],{"href":22220,"rel":22221},"https://nuxt.com/docs/getting-started/state-management",[2010],[1220,22223,536],{},[2006,22225,22228],{"href":22226,"rel":22227},"https://nuxt.com/docs/api/composables/use-fetch",[2010],[1220,22229,444],{}," composables",[1143,22232,22233,22234,22238,22239,22244,22245,2281],{},"So far, we've merged ",[2006,22235,22237],{"href":22039,"rel":22236},[2010],"385 pull requests",", closed ",[2006,22240,22243],{"href":22241,"rel":22242},"https://github.com/nuxt/nuxt/issues?q=is%3Aissue+is%3Aclosed",[2010],"229 issues"," and made ",[2006,22246,22249],{"href":22247,"rel":22248},"https://github.com/nuxt/nuxt/commits/main",[2010],"925+ commits",[1143,22251,22252],{},"We are excited to hear your thoughts and we thank you for your patience.",[1143,22254,22255,22256,22260],{},"Now you can go over the ",[2006,22257,22259],{"href":21959,"rel":22258},[2010],"Nuxt 3 documentation"," 😊",[1143,22262,22263,22264,22267],{},"Don't forget to follow us on ",[2006,22265,10291],{"href":10289,"rel":22266},[2010]," to get the latest news about Nuxt!",{"title":1218,"searchDepth":1233,"depth":1233,"links":22269},[22270,22271,22272],{"id":21963,"depth":1233,"text":21964},{"id":22012,"depth":1233,"text":22013},{"id":15270,"depth":1233,"text":15271},"2022-04-12","Nuxt 3 beta was announced on October 12, 2021 after 16 months of work, introducing a new foundation based on Vue 3, Vite and Nitro. Six months later, we are happy to announce the first release candidate of Nuxt 3, code named “Mount Hope“ 🚀","/assets/blog/announcing-nuxt-3-release-candidate.png",{},{"title":1076,"description":22274},"WdNVCe9wV0",{"id":22280,"title":1084,"authors":22281,"body":22290,"category":2176,"date":22517,"description":22518,"draft":108,"extension":1954,"image":22519,"meta":22520,"navigation":1739,"path":1085,"seo":22521,"stem":1086,"tags":6,"__hash__":22522},"blog/blog/4.nuxt3-beta.md",[22282,22284,22286,22288],{"name":1130,"avatar":22283,"to":1133},{"src":7720},{"name":10194,"avatar":22285,"to":21771,"twitter":21772},{"src":21770},{"name":2190,"avatar":22287,"to":2193},{"src":2192},{"name":21927,"avatar":22289,"to":21930},{"src":21929},{"type":1140,"value":22291,"toc":22512},[22292,22301,22308,22310,22321,22325,22332,22337,22339,22344,22348,22356,22358,22369,22371,22373,22489,22500,22502,22507],[1143,22293,21940,22294,21945,22297,21951],{},[2006,22295,8349],{"href":8347,"rel":22296},[2010],[2006,22298,21950],{"href":22299,"rel":22300},"https://github.com/nuxt/nuxt/blob/main/LICENSE",[2010],[7733,22302,22303],{},[1143,22304,21956,22305,2281],{},[2006,22306,21959],{"href":21959,"rel":22307},[2010],[1147,22309,21964],{"id":21963},[1143,22311,21967,22312,6381,22315,21977,22318,21983],{},[2006,22313,21972],{"href":21970,"rel":22314},[2010],[2006,22316,973],{"href":21975,"rel":22317},[2010],[2006,22319,21982],{"href":21980,"rel":22320},[2010],[1143,22322,21986,22323,21989],{},[1220,22324,171],{},[1143,22326,22327,21995,22329,22001],{},[1159,22328,21994],{},[2006,22330,22000],{"href":21998,"rel":22331},[2010],[1143,22333,22004,22334,22009],{},[2006,22335,22008],{"href":21959,"rel":22336},[2010],[1147,22338,22013],{"id":22012},[1143,22340,22016,22341,22022],{},[2006,22342,22021],{"href":22019,"rel":22343},[2010],[1143,22345,22346],{},[1159,22347,22027],{},[1143,22349,22030,22350,22036,22353,22042],{},[2006,22351,22035],{"href":22033,"rel":22352},[2010],[2006,22354,22041],{"href":22039,"rel":22355},[2010],[1143,22357,22045],{},[1143,22359,22048,22360,5062,22363,6381,22366,2281],{},[2006,22361,22052],{"href":21869,"rel":22362},[2010],[2006,22364,22057],{"href":22055,"rel":22365},[2010],[2006,22367,22062],{"href":22060,"rel":22368},[2010],[1147,22370,15271],{"id":15270},[1143,22372,22067],{},[20764,22374,22375],{},[1852,22376,22377,22381,22385,22394,22401,22408,22415,22422,22429,22436,22447,22456,22460,22464,22471,22475],{},[1855,22378,22379,22077],{},[1159,22380,22076],{},[1855,22382,22383,22083],{},[1159,22384,22082],{},[1855,22386,22387,8598,22389,22096],{},[1159,22388,22088],{},[2006,22390,22392],{"href":22091,"rel":22391},[2010],[1220,22393,22095],{},[1855,22395,22396,8598,22398,22105],{},[1159,22397,22101],{},[2006,22399,21972],{"href":21970,"rel":22400},[2010],[1855,22402,22403,8598,22405,22116],{},[1159,22404,22110],{},[2006,22406,22115],{"href":22113,"rel":22407},[2010],[1855,22409,22410,22122,22412,22096],{},[1159,22411,22121],{},[2006,22413,973],{"href":21975,"rel":22414},[2010],[1855,22416,22417,22131,22419],{},[1159,22418,22130],{},[2006,22420,22136],{"href":22134,"rel":22421},[2010],[1855,22423,22424,8598,22426,22145],{},[1159,22425,22141],{},[2006,22427,10247],{"href":12553,"rel":22428},[2010],[1855,22430,22431,22151,22433,2541],{},[1159,22432,22150],{},[2006,22434,11566],{"href":22154,"rel":22435},[2010],[1855,22437,22438,8598,22440,22167,22445,22170],{},[1159,22439,22160],{},[2006,22441,22443],{"href":22163,"rel":22442},[2010],[1220,22444,248],{},[1220,22446,22095],{},[1855,22448,22449,8598,22451,22096],{},[1159,22450,22175],{},[2006,22452,22454],{"href":22178,"rel":22453},[2010],[1220,22455,22182],{},[1855,22457,22458,22188],{},[1159,22459,22187],{},[1855,22461,22462,22194],{},[1159,22463,22193],{},[1855,22465,22466,22200,22468,22205],{},[1159,22467,22199],{},[2006,22469,22000],{"href":22203,"rel":22470},[2010],[1855,22472,22473,22211],{},[1159,22474,22210],{},[1855,22476,22477,22217,22479,4363,22484,22230],{},[1159,22478,22216],{},[2006,22480,22482],{"href":22220,"rel":22481},[2010],[1220,22483,536],{},[2006,22485,22487],{"href":22226,"rel":22486},[2010],[1220,22488,444],{},[1143,22490,22233,22491,22238,22494,22244,22497,2281],{},[2006,22492,22237],{"href":22039,"rel":22493},[2010],[2006,22495,22243],{"href":22241,"rel":22496},[2010],[2006,22498,22249],{"href":22247,"rel":22499},[2010],[1143,22501,22252],{},[1143,22503,22255,22504,22260],{},[2006,22505,22259],{"href":21959,"rel":22506},[2010],[1143,22508,22263,22509,22267],{},[2006,22510,10291],{"href":10289,"rel":22511},[2010],{"title":1218,"searchDepth":1233,"depth":1233,"links":22513},[22514,22515,22516],{"id":21963,"depth":1233,"text":21964},{"id":22012,"depth":1233,"text":22013},{"id":15270,"depth":1233,"text":15271},"2021-10-11","468 days after the first commit, the Nuxt 3 beta has finally arrived. Discover what's inside and what to expect from it. Yes, it includes Vue 3 and Vite ⚡️","/assets/blog/introducing-nuxt-3-beta.png",{},{"title":1084,"description":22518},"hglqVTwhdf",{"id":22524,"title":1100,"authors":22525,"body":22536,"category":2176,"date":23171,"description":23172,"draft":108,"extension":1954,"image":23173,"meta":23174,"navigation":1739,"path":1101,"seo":23175,"stem":1102,"tags":6,"__hash__":23176},"blog/blog/8.nuxt-static-improvements.md",[22526,22532,22534],{"name":22527,"avatar":22528,"to":22530,"twitter":22531},"Alexander Lichter",{"src":22529},"https://github.com/manniL.png","https://x.com/TheAlexLichter","TheAlexLichter",{"name":1130,"avatar":22533,"to":1133},{"src":7720},{"name":10194,"avatar":22535,"to":21771,"twitter":21772},{"src":21770},{"type":1140,"value":22537,"toc":23158},[22538,22540,22554,22613,22616,22632,22644,22647,22652,22666,22672,22681,22704,22707,22715,22743,22758,22794,22803,22808,22817,22828,22831,22834,22868,22879,22949,22956,22959,22973,23019,23022,23041,23050,23053,23063,23066,23081,23084,23102,23105,23126,23129,23155],[1147,22539,19],{"id":17910},[1143,22541,22542,22543,22546,22547,22550,22551],{},"With Nuxt version 2.13, the ",[2006,22544,22545],{"href":1089},"full-static mode"," has been introduced. In addition, a new command ",[1220,22548,22549],{},"nuxt export"," was added to pre-render your pages without triggering a webpack build with the goal to separate the rendering and build process. The only issue was that most Nuxt users weren't able to unleash the full potential of the separation... ",[1159,22552,22553],{},"until now.",[1852,22555,22556,22561,22567,22573,22593,22607],{},[1855,22557,22558],{},[2006,22559,19],{"href":22560},"#introduction",[1855,22562,22563],{},[2006,22564,22566],{"href":22565},"#faster-static-deployments","Faster Static Deployments",[1855,22568,22569],{},[2006,22570,22572],{"href":22571},"#generate-time-cache-vs-full-webpack-build","Generate time: cache vs full webpack build",[1855,22574,22575,22579],{},[2006,22576,22578],{"href":22577},"#using-in-your-projects","Using in your projects",[1852,22580,22581,22587],{},[1855,22582,22583],{},[2006,22584,22586],{"href":22585},"#excluding-files-from-cache","Excluding Files from Cache",[1855,22588,22589],{},[2006,22590,22592],{"href":22591},"#module-authors","Module Authors",[1855,22594,22595,22599],{},[2006,22596,22598],{"href":22597},"#how-it-works","How it works",[1852,22600,22601],{},[1855,22602,22603],{},[2006,22604,22606],{"href":22605},"#back-to-old-school-commands","Back to old school commands",[1855,22608,22609],{},[2006,22610,22612],{"href":22611},"#what-to-do-next","What to do next",[1147,22614,22566],{"id":22615},"faster-static-deployments",[1143,22617,22618,22619,22621,22622,22625,22626,22629,22630,2281],{},"With v2.14, ",[1220,22620,15824],{}," will ",[1159,22623,22624],{},"automagically skip webpack build step when no code has been changed"," and use the previous build using cache. This will help to drastically improve static deployments time by avoiding unnecessary builds which is usually the most time-consuming part of generation process. Cache support is ",[1159,22627,22628],{},"platform-agnostic"," and works on Netlify, Vercel, or any other CI/CD setup that is caching ",[1220,22631,203],{},[7119,22633,22635,22638,22641],{":autoplay":9655,":controls":9655,"autoPlay":1739,"controls":1739,"poster":22634},"https://res.cloudinary.com/nuxt/video/upload/v1595852304/nuxt-smart-generate_pjaat1.jpg",[15705,22636],{"src":22637,"type":15708},"https://res.cloudinary.com/nuxt/video/upload/v1595852304/nuxt-smart-generate_pjaat1.webm",[15705,22639],{"src":22640,"type":15712},"https://res.cloudinary.com/nuxt/video/upload/v1595852304/nuxt-smart-generate_pjaat1.mp4",[15705,22642],{"src":22643,"type":15716},"https://res.cloudinary.com/nuxt/video/upload/v1595852304/nuxt-smart-generate_pjaat1.ogg",[1147,22645,22572],{"id":22646},"generate-time-cache-vs-full-webpack-build",[1143,22648,22649,22650,1765],{},"See the comparison in seconds between two ",[1220,22651,15824],{},[1852,22653,22654,22660],{},[1855,22655,22656,22659],{},[1220,22657,22658],{},"Build"," is when a webpack build is required",[1855,22661,22662,22665],{},[1220,22663,22664],{},"Cache"," is only when the content has changed (webpack build skipped)",[1143,22667,22668],{},[2243,22669],{"alt":22670,"src":22671},"Comparison between build VS cache time","/assets/blog/bar-chart-cache-build.png",[7733,22673,22674],{},[1143,22675,22676,22677,22680],{},"The static site generation of our projects on content changes are now ",[1159,22678,22679],{},"~3.6x times"," faster 🚀",[1143,22682,22683,22684,5062,22689,5062,22694,4363,22699,2281],{},"Project links: ",[2006,22685,22688],{"href":22686,"rel":22687},"https://github.com/pi0/nuxt-static-demo",[2010],"Basic",[2006,22690,22693],{"href":22691,"rel":22692},"https://github.com/nuxt-community/strapi-module/tree/master/docs",[2010],"Strapi Module Docs",[2006,22695,22698],{"href":22696,"rel":22697},"https://github.com/nuxt/content/tree/master/docs",[2010],"Content Module Docs",[2006,22700,22703],{"href":22701,"rel":22702},"https://github.com/nuxt/website-v2",[2010],"Nuxt 2 Docs",[1147,22705,22578],{"id":22706},"using-in-your-projects",[2412,22708,22709],{},[1855,22710,22711,22712,22714],{},"Update ",[1220,22713,2367],{}," to the latest minor version, which is v2.14.",[22716,22717,22718,22730],"package-managers",{},[1213,22719,22721],{"className":2022,"code":22720,"filename":2090,"language":2024,"meta":1218,"style":1218},"npm update\n",[1220,22722,22723],{"__ignoreMap":1218},[1223,22724,22725,22727],{"class":1225,"line":1226},[1223,22726,2090],{"class":2036},[1223,22728,22729],{"class":1254}," update\n",[1213,22731,22733],{"className":2022,"code":22732,"filename":2076,"language":2024,"meta":1218,"style":1218},"yarn upgrade nuxt\n",[1220,22734,22735],{"__ignoreMap":1218},[1223,22736,22737,22739,22741],{"class":1225,"line":1226},[1223,22738,2076],{"class":2036},[1223,22740,3599],{"class":1254},[1223,22742,2239],{"class":1254},[2412,22744,22745],{"start":1233},[1855,22746,22747,22748,22751,22752,22755,22756],{},"Ensure ",[1220,22749,22750],{},"target"," is ",[1220,22753,22754],{},"static"," inside your ",[1220,22757,5357],{},[1213,22759,22762],{"className":9317,"code":22760,"filename":22761,"language":9319,"meta":1218,"style":1218},"export default {\n  target: 'static'\n  // ...\n}\n","nuxt.config.js",[1220,22763,22764,22772,22785,22790],{"__ignoreMap":1218},[1223,22765,22766,22768,22770],{"class":1225,"line":1226},[1223,22767,1745],{"class":1679},[1223,22769,1748],{"class":1679},[1223,22771,1891],{"class":1236},[1223,22773,22774,22777,22779,22781,22783],{"class":1225,"line":1233},[1223,22775,22776],{"class":1240},"  target",[1223,22778,1765],{"class":1236},[1223,22780,1695],{"class":1236},[1223,22782,22754],{"class":1254},[1223,22784,1701],{"class":1236},[1223,22786,22787],{"class":1225,"line":1263},[1223,22788,22789],{"class":1229},"  // ...\n",[1223,22791,22792],{"class":1225,"line":1296},[1223,22793,2407],{"class":1236},[1143,22795,22796,22798,22799,22802],{},[1220,22797,15824],{}," will behave as before to avoid breaking changes and provide legacy compatibility if you keep ",[1220,22800,22801],{},"target: ‘server’"," or don't specify target.",[2412,22804,22805],{"start":1263},[1855,22806,22807],{},"That’s it 🙌",[1143,22809,22810,22811,22813,22814,22816],{},"Now, the ",[1220,22812,15824],{}," command will build the project only if necessary, which is the case when files inside the project have been changed. It will always re-render your routes to static HTML files, like ",[1220,22815,22549],{}," is doing already.",[1143,22818,22819,22820,4880,22823,22825,22826,2281],{},"Now you only have to change your build command back from ",[1220,22821,22822],{},"nuxt build && nuxt export",[1220,22824,15824],{}," on the platform you are using. If you are using a CI, ensure that you are properly caching ",[1220,22827,203],{},[1155,22829,22586],{"id":22830},"excluding-files-from-cache",[1143,22832,22833],{},"By default, nuxt ignores these directories so if any change happens inside them, build will not be triggered:",[1852,22835,22836,22842,22848,22854,22858,22863],{},[1855,22837,22838,22839,2541],{},"Build directory (",[1220,22840,22841],{},".nuxt/",[1855,22843,22844,22845,2541],{},"Static directory (",[1220,22846,22847],{},"static/",[1855,22849,22850,22851,2541],{},"Generate dist (",[1220,22852,22853],{},"dist/",[1855,22855,22856],{},[1220,22857,203],{},[1855,22859,22860],{},[1220,22861,22862],{},"README.md",[1855,22864,22865,22866,2541],{},"Hidden dotfiles (like ",[1220,22867,2134],{},[1143,22869,22870,22871,22876,22877,1765],{},"You can add more patterns using ",[2006,22872,22875],{"href":22873,"rel":22874},"https://v2.nuxt.com/docs/configuration-glossary/configuration-generate/#cache",[2010],"generate.cache.ignore"," option in ",[1220,22878,5357],{},[1213,22880,22882],{"className":9317,"code":22881,"filename":22761,"language":9319,"meta":1218,"style":1218},"export default {\n  generate: {\n    cache: {\n      ignore: [\n        // When something changed in the docs folder, do not re-build via webpack\n        'docs'\n      ]\n    }\n  }\n}\n",[1220,22883,22884,22892,22901,22910,22919,22924,22932,22937,22941,22945],{"__ignoreMap":1218},[1223,22885,22886,22888,22890],{"class":1225,"line":1226},[1223,22887,1745],{"class":1679},[1223,22889,1748],{"class":1679},[1223,22891,1891],{"class":1236},[1223,22893,22894,22897,22899],{"class":1225,"line":1233},[1223,22895,22896],{"class":1240},"  generate",[1223,22898,1765],{"class":1236},[1223,22900,1891],{"class":1236},[1223,22902,22903,22906,22908],{"class":1225,"line":1263},[1223,22904,22905],{"class":1240},"    cache",[1223,22907,1765],{"class":1236},[1223,22909,1891],{"class":1236},[1223,22911,22912,22915,22917],{"class":1225,"line":1296},[1223,22913,22914],{"class":1240},"      ignore",[1223,22916,1765],{"class":1236},[1223,22918,1768],{"class":1285},[1223,22920,22921],{"class":1225,"line":1325},[1223,22922,22923],{"class":1229},"        // When something changed in the docs folder, do not re-build via webpack\n",[1223,22925,22926,22928,22930],{"class":1225,"line":1355},[1223,22927,9222],{"class":1236},[1223,22929,9],{"class":1254},[1223,22931,1701],{"class":1236},[1223,22933,22934],{"class":1225,"line":1771},[1223,22935,22936],{"class":1285},"      ]\n",[1223,22938,22939],{"class":1225,"line":1783},[1223,22940,1984],{"class":1236},[1223,22942,22943],{"class":1225,"line":1792},[1223,22944,1990],{"class":1236},[1223,22946,22947],{"class":1225,"line":1798},[1223,22948,2407],{"class":1236},[1143,22950,22951,22952,22955],{},"It is also possible to use a function for ",[1220,22953,22954],{},"ignore"," option to override default ignore entries.",[1155,22957,22592],{"id":22958},"module-authors",[1143,22960,22961,22962,22965,22966,22968,22969,22972],{},"What if you are developing a nuxt module that is working with files that should not trigger a rebuild? The best example is for ",[2006,22963,11715],{"href":16979,"rel":22964},[2010]," module that reads markdown files from the repository. In this case, these files are used within a runtime module, which is the case when using ",[1220,22967,11715],{},", the module itself can tell nuxt to ignore these files for you already so you don't have to do anything! Module authors can use the new ",[1220,22970,22971],{},"generate:cache:ignore"," hook to do so:",[1213,22974,22976],{"className":9317,"code":22975,"language":9319,"meta":1218,"style":1218},"nuxt.hook('generate:cache:ignore', ignore => ignore.push('content'))\n",[1220,22977,22978],{"__ignoreMap":1218},[1223,22979,22980,22982,22984,22987,22989,22991,22993,22995,22997,23000,23002,23004,23006,23009,23011,23013,23015,23017],{"class":1225,"line":1226},[1223,22981,2367],{"class":1285},[1223,22983,2281],{"class":1236},[1223,22985,22986],{"class":1751},"hook",[1223,22988,1754],{"class":1285},[1223,22990,1957],{"class":1236},[1223,22992,22971],{"class":1254},[1223,22994,1957],{"class":1236},[1223,22996,2333],{"class":1236},[1223,22998,22999],{"class":2329}," ignore",[1223,23001,3125],{"class":1244},[1223,23003,22999],{"class":1285},[1223,23005,2281],{"class":1236},[1223,23007,23008],{"class":1751},"push",[1223,23010,1754],{"class":1285},[1223,23012,1957],{"class":1236},[1223,23014,187],{"class":1254},[1223,23016,1957],{"class":1236},[1223,23018,12444],{"class":1285},[1147,23020,22598],{"id":23021},"how-it-works",[1143,23023,23024,23025,2553,23027,23029,23030,23033,23034,23037,23038,23040],{},"When using the new ",[1220,23026,15824],{},[1220,23028,22754],{}," target, a snapshot including checksum of non-ignored project files as well as nuxt version and some other configuration will be written ",[1220,23031,23032],{},".nuxt/build.json",". In addition, we also move the build directory to ",[1220,23035,23036],{},"node_modules/.cache/nuxt",". Because ",[1220,23039,203],{}," is cached by all major platforms (Netlify, Vercel, ...) and common CI/CD scripts, this solution works out of the box without additional configuration.",[1143,23042,23043,23044,23046,23047,2281],{},"When ",[1220,23045,15824],{}," is called subsequently, it will again create a checksum based on your project files and then compare it to the existing one inside ",[1220,23048,23049],{},"node_modules/.cache/nuxt/build.json",[1143,23051,23052],{},"If they match, it means that nothing is changed that needs rebuild so we can directly start rendering pages.",[1143,23054,23055,23056,23058,23059,2281],{},"If a mismatch is detected, it means that a full rebuild would be necessary. You can also see what file caused rebuild by checking console logs. After the build, nuxt generate will save the new checksum inside ",[1220,23057,23032],{},". You can check full implementation ",[2006,23060,2274],{"href":23061,"rel":23062},"https://github.com/nuxt/nuxt.js/pull/7712",[2010],[1155,23064,22606],{"id":23065},"back-to-old-school-commands",[1143,23067,23068,23069,4363,23071,23074,23075,4363,23077,23080],{},"With Nuxt v2.13, we introduced ",[1220,23070,22549],{},[1220,23072,23073],{},"nuxt serve"," specially designed for the static target. With Nuxt v2.14, they are deprecated as ",[1220,23076,15824],{},[1220,23078,23079],{},"nuxt start"," is smart to detect the target and build when necessary.",[1143,23082,23083],{},"Server target:",[1852,23085,23086,23092,23097],{},[1855,23087,23088,23091],{},[1220,23089,23090],{},"nuxt dev"," = development server",[1855,23093,23094,23096],{},[1220,23095,18007],{}," = build your application for production",[1855,23098,23099,23101],{},[1220,23100,23079],{}," = start the production server (use it for Node.js hosting like Heroku, DigitalOcean, etc)",[1143,23103,23104],{},"Static target:",[1852,23106,23107,23111,23118],{},[1855,23108,23109,23091],{},[1220,23110,23090],{},[1855,23112,23113,23115,23116],{},[1220,23114,15824],{}," = build if needed and statically export to ",[1220,23117,22853],{},[1855,23119,23120,23122,23123,23125],{},[1220,23121,23079],{}," = serve the ",[1220,23124,22853],{}," directory like your static hosting would do (Netlify, Vercel, Surge, etc), great for testing before deploying",[1147,23127,22612],{"id":23128},"what-to-do-next",[1852,23130,23131,23139,23146,23152],{},[1855,23132,23133,23134],{},"Upgrade your project to ",[2006,23135,23138],{"href":23136,"rel":23137},"https://github.com/nuxt/nuxt.js/releases/tag/v2.14.0",[2010],"nuxt@2.14.0",[1855,23140,23141,23142,2420,23144],{},"Use ",[1220,23143,15824],{},[1220,23145,22549],{},[1855,23147,23141,23148,2420,23150],{},[1220,23149,23079],{},[1220,23151,23073],{},[1855,23153,23154],{},"Enjoy fast deployments 🤙",[2160,23156,23157],{},"html pre.shiki code .sT2Ow, html code.shiki .sT2Ow{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}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 .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .svXlt, html code.shiki .svXlt{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .ssYd4, html code.shiki .ssYd4{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}",{"title":1218,"searchDepth":1233,"depth":1233,"links":23159},[23160,23161,23162,23163,23167,23170],{"id":17910,"depth":1233,"text":19},{"id":22615,"depth":1233,"text":22566},{"id":22646,"depth":1233,"text":22572},{"id":22706,"depth":1233,"text":22578,"children":23164},[23165,23166],{"id":22830,"depth":1263,"text":22586},{"id":22958,"depth":1263,"text":22592},{"id":23021,"depth":1233,"text":22598,"children":23168},[23169],{"id":23065,"depth":1263,"text":22606},{"id":23128,"depth":1233,"text":22612},"2020-07-27","With Nuxt version 2.13, the full-static mode has been introduced. In addition, a new command nuxt export was added to pre-render your pages without triggering a webpack build with the goal to separate the rendering and build process. The only issue was that most Nuxt users weren't able to unleash the full potential of the separation... until now.","/assets/blog/nuxt-static-improvements.png",{},{"title":1100,"description":23172},"2GlqFtQICH",{"id":23178,"title":1088,"authors":23179,"body":23183,"category":2176,"date":23883,"description":23884,"draft":108,"extension":1954,"image":23885,"meta":23886,"navigation":1739,"path":1089,"seo":23887,"stem":1090,"tags":6,"__hash__":23888},"blog/blog/5.going-full-static.md",[23180],{"name":23181,"avatar":23182,"to":1133,"twitter":7721},"Sebastien Chopin",{"src":7720},{"type":1140,"value":23184,"toc":23863},[23185,23189,23213,23221,23233,23241,23245,23329,23332,23344,23347,23361,23364,23419,23428,23433,23441,23535,23548,23554,23585,23592,23597,23607,23610,23636,23643,23646,23649,23663,23671,23674,23682,23687,23700,23703,23705,23708,23773,23783,23791,23793,23799,23848,23850,23860],[1147,23186,23188],{"id":23187},"too-long-to-read","Too long to read",[2412,23190,23191,23197,23205,23210],{},[1855,23192,23193,23194],{},"Upgrade nuxt to ",[1220,23195,23196],{},"2.14.0",[1855,23198,23199,23200,2131,23203],{},"Set ",[1220,23201,23202],{},"target: 'static'",[1220,23204,22761],{},[1855,23206,23207,23208],{},"Run ",[1220,23209,15824],{},[1855,23211,23212],{},"That's it ✨",[1143,23214,23215],{},[3746,23216,23217,23218,23220],{},"Bonus: you can run ",[1220,23219,23079],{}," to run a local server serving your generated static application.",[7119,23222,23224,23227,23230],{":autoplay":9655,":controls":9655,"autoPlay":1739,"controls":1739,"poster":23223},"https://res.cloudinary.com/nuxt/video/upload/v1588095794/nuxt-full-static_rnnbvm.jpg",[15705,23225],{"src":23226,"type":15708},"https://res.cloudinary.com/nuxt/video/upload/v1588095794/nuxt-full-static_rnnbvm.webm",[15705,23228],{"src":23229,"type":15712},"https://res.cloudinary.com/nuxt/video/upload/v1588095794/nuxt-full-static_rnnbvm.mp4",[15705,23231],{"src":23232,"type":15716},"https://res.cloudinary.com/nuxt/video/upload/v1588095794/nuxt-full-static_rnnbvm.ogg",[1143,23234,23235,23236,23238,23239,2281],{},"Note: in this video we are using ",[1220,23237,22549],{}," which has been deprecated in favor of ",[1220,23240,15824],{},[1147,23242,23244],{"id":23243},"table-of-contents","Table of Contents",[1852,23246,23247,23252,23257,23263,23269,23277,23305,23312,23318],{},[1855,23248,23249],{},[2006,23250,23188],{"href":23251},"#too-long-to-read",[1855,23253,23254],{},[2006,23255,23244],{"href":23256},"#table-of-contents",[1855,23258,23259],{},[2006,23260,23262],{"href":23261},"#history","History",[1855,23264,23265],{},[2006,23266,23268],{"href":23267},"#current-issues","Current issues",[1855,23270,23271],{},[2006,23272,23274,23275],{"href":23273},"#new-config-option-target","New config option: ",[1220,23276,22750],{},[1855,23278,23279,23285],{},[2006,23280,23282,23283],{"href":23281},"#smarter-nuxt-generate","Smarter ",[1220,23284,15824],{},[1852,23286,23287,23293,23299],{},[1855,23288,23289],{},[2006,23290,23292],{"href":23291},"#crazy-fast-static-applications","Crazy fast static applications",[1855,23294,23295],{},[2006,23296,23298],{"href":23297},"#crawler-integrated","Crawler integrated",[1855,23300,23301],{},[2006,23302,23304],{"href":23303},"#faster-re-deploy","Faster re-deploy",[1855,23306,23307],{},[2006,23308,23282,23310],{"href":23309},"#smarter-nuxt-start",[1220,23311,23079],{},[1855,23313,23314],{},[2006,23315,23317],{"href":23316},"#preview-mode","Preview mode",[1855,23319,23320,23323],{},[2006,23321,655],{"href":23322},"#commands",[1852,23324,23325],{},[1855,23326,23327],{},[2006,23328,22612],{"href":22611},[1147,23330,23262],{"id":23331},"history",[1143,23333,23334,23335,23337,23338,23343],{},"Nuxt had the static generation feature with ",[1220,23336,15824],{}," since ",[2006,23339,23342],{"href":23340,"rel":23341},"https://github.com/nuxt/nuxt.js/releases/tag/v0.3.2",[2010],"v0.3.2"," (November 2016), since then we have improved it in multiple ways but never achieved full static generation. Today I am excited to announce that full static export is now possible with Nuxt 2.13.",[1147,23345,23268],{"id":23346},"current-issues",[1143,23348,23349,23351,23352,4363,23354,23356,23357,23360],{},[1220,23350,15824],{}," is mostly pre-rendering, when you navigate client-side, ",[1220,23353,13261],{},[1220,23355,16689],{}," are called, ",[3746,23358,23359],{},"making a request to your API",". A lot of users asked to support a \"full static\" mode, meaning to not call these 2 hooks on navigation, since the next page has been already pre-rendered.",[1143,23362,23363],{},"Also, the developer experience is not optimal:",[1852,23365,23366,23378,23389,23402,23411],{},[1855,23367,23368,23369,6381,23372,23375,23376],{},"You have access to ",[1220,23370,23371],{},"req",[1220,23373,23374],{},"res"," on SSR but not when running ",[1220,23377,15824],{},[1855,23379,23380,22751,23383,23385,23386,23388],{},[1220,23381,23382],{},"process.static",[1220,23384,9655],{}," only when running ",[1220,23387,15824],{},", making it slow to develop Nuxt modules or plugins for static generation",[1855,23390,23391,23392,23397,23398,23401],{},"You have to specify all your ",[2006,23393,23396],{"href":23394,"rel":23395},"https://v2.nuxt.com/docs/features/file-system-routing#dynamic-routes",[2010],"dynamic routes"," in ",[1220,23399,23400],{},"generate.routes",", making it harder since you don't have access to nuxt modules there.",[1855,23403,23404,23405,23410],{},"You cannot test the ",[2006,23406,23409],{"href":23407,"rel":23408},"https://v2.nuxt.com/docs/concepts/static-site-generation#spa-fallback",[2010],"SPA fallback"," in development, the fallback is a client-only version of your Nuxt application that loads when hitting a 404 page",[1855,23412,23413,23415,23416,23418],{},[1220,23414,15824],{}," runs ",[1220,23417,18007],{}," by default, making it slower to generate your website if only your content changed",[1143,23420,23421,23422,23427],{},"Note that it was possible to have full static support with ",[2006,23423,23426],{"href":23424,"rel":23425},"https://github.com/DreaMinder/nuxt-payload-extractor",[2010],"nuxt-payload-extractor"," module but it was more verbose to use and had limitations.",[1147,23429,23274,23431],{"id":23430},"new-config-option-target",[1220,23432,22750],{},[1143,23434,23435,23436,23438,23439,1765],{},"To improve the user experience as well as telling Nuxt that you want to export your application to static hosting, we are introducing a ",[1220,23437,22750],{}," option in your ",[1220,23440,22761],{},[1213,23442,23444],{"className":2595,"code":23443,"language":2597,"meta":1218,"style":1218},"\u003Cscript setup>\n  import { ref, computed } from '#imports'\n\n  const count = ref(1)\n  const double = computed(() => count.value * 2)\n\u003C/script>\n",[1220,23445,23446,23456,23479,23483,23499,23527],{"__ignoreMap":1218},[1223,23447,23448,23450,23452,23454],{"class":1225,"line":1226},[1223,23449,1237],{"class":1236},[1223,23451,5899],{"class":1240},[1223,23453,5902],{"class":1244},[1223,23455,1260],{"class":1236},[1223,23457,23458,23461,23463,23465,23467,23469,23471,23473,23475,23477],{"class":1225,"line":1233},[1223,23459,23460],{"class":1679},"  import",[1223,23462,1683],{"class":1236},[1223,23464,6964],{"class":1285},[1223,23466,2333],{"class":1236},[1223,23468,12974],{"class":1285},[1223,23470,1689],{"class":1236},[1223,23472,1692],{"class":1679},[1223,23474,1695],{"class":1236},[1223,23476,18519],{"class":1254},[1223,23478,1701],{"class":1236},[1223,23480,23481],{"class":1225,"line":1263},[1223,23482,1740],{"emptyLinePlaceholder":1739},[1223,23484,23485,23487,23489,23491,23493,23495,23497],{"class":1225,"line":1296},[1223,23486,2349],{"class":1244},[1223,23488,12937],{"class":1285},[1223,23490,1248],{"class":1236},[1223,23492,6964],{"class":1751},[1223,23494,1754],{"class":1285},[1223,23496,21057],{"class":6166},[1223,23498,1804],{"class":1285},[1223,23500,23501,23503,23505,23507,23509,23511,23513,23515,23517,23519,23521,23523,23525],{"class":1225,"line":1325},[1223,23502,2349],{"class":1244},[1223,23504,12969],{"class":1285},[1223,23506,1248],{"class":1236},[1223,23508,12974],{"class":1751},[1223,23510,1754],{"class":1285},[1223,23512,1777],{"class":1236},[1223,23514,3125],{"class":1244},[1223,23516,12983],{"class":1285},[1223,23518,2281],{"class":1236},[1223,23520,12988],{"class":1285},[1223,23522,12991],{"class":1236},[1223,23524,8930],{"class":6166},[1223,23526,1804],{"class":1285},[1223,23528,23529,23531,23533],{"class":1225,"line":1355},[1223,23530,1289],{"class":1236},[1223,23532,5899],{"class":1240},[1223,23534,1260],{"class":1236},[13332,23536,23537],{},[1143,23538,23539,23540,23543,23544,23547],{},"Full static doesn't work with ",[1220,23541,23542],{},"ssr: 'false'"," (which is the same as the deprecated ",[1220,23545,23546],{},"mode: 'spa'",") as this is used for client-side rendering only (Single Page Applications).",[1143,23549,23550,23551,23553],{},"Running ",[1220,23552,23090],{}," with the static target will improve the developer experience:",[1852,23555,23556,23564,23570,23579],{},[1855,23557,23558,23559,17151,23561,23563],{},"Remove ",[1220,23560,23371],{},[1220,23562,23374],{}," from context",[1855,23565,23566,23567,2541],{},"Fallback to client-side rendering on 404, errors and redirects (see ",[2006,23568,23409],{"href":23407,"rel":23569},[2010],[1855,23571,23572,23575,23576,23578],{},[1220,23573,23574],{},"$route.query"," will always be equal to ",[1220,23577,13796],{}," on server-side rendering",[1855,23580,23581,22751,23583],{},[1220,23582,23382],{},[1220,23584,9655],{},[1143,23586,23587,23588,23591],{},"We are also exposing ",[1220,23589,23590],{},"process.target"," for modules author to add logic depending on the user target.",[1147,23593,23282,23595],{"id":23594},"smarter-nuxt-generate",[1220,23596,15824],{},[1143,23598,23599,23600,23603,23604,23606],{},"Now with ",[1220,23601,23602],{},"v2.14.0",", you can use ",[1220,23605,15824],{},", it will smartly know if it has to build or not.",[1155,23608,23292],{"id":23609},"crazy-fast-static-applications",[1143,23611,23612,2553,23614,23616,23617,4363,23619,23621,23622,8602,23624,23627,23628,23631,23632,23635],{},[1220,23613,15824],{},[1220,23615,23202],{}," will pre-render all your pages to HTML and save a payload file in order to mock ",[1220,23618,13261],{},[1220,23620,16689],{}," on client-side navigation, this means ",[1159,23623,6429],{},[1159,23625,23626],{},"more HTTP calls to your API on client-side navigation."," By extracting the page payload to a js file, ",[1159,23629,23630],{},"it also reduces the HTML size"," served as well as preloading it (from the ",[23633,23634],"link",{}," in the header) for optimal performance.",[1143,23637,23638,23639,23642],{},"We also improved the ",[2006,23640,23641],{"href":1093},"smart prefetching"," when doing full static, it will also fetch the payloads, making navigation instant 👀",[1155,23644,23298],{"id":23645},"crawler-integrated",[1143,23647,23648],{},"On top of that, it also has a crawler inside, detecting every relative link and generating it:",[1143,23650,23651,23652,23657,23658,23662],{},"If you want to exclude a bunch of routes, use the ",[2006,23653,23656],{"href":23654,"rel":23655},"https://v2.nuxt.com/docs/configuration-glossary/configuration-generate#exclude",[2010],"generate.exclude",". You can keep using ",[2006,23659,23400],{"href":23660,"rel":23661},"https://v2.nuxt.com/docs/configuration-glossary/configuration-generate#routes",[2010]," to add extra routes that the crawler could not detect.",[1143,23664,23665,23666,2131,23669],{},"To disable the crawler, set ",[1220,23667,23668],{},"generate.crawler: false",[1220,23670,22761],{},[1155,23672,23304],{"id":23673},"faster-re-deploy",[1143,23675,23676,23677,4363,23679,23681],{},"By separating ",[1220,23678,18007],{},[1220,23680,22549],{},", we are opening a new range of improvements: pre-render your pages only if you content has changed, this means: no webpack build → faster re-deployments.",[1147,23683,23282,23685],{"id":23684},"smarter-nuxt-start",[1220,23686,23079],{},[1143,23688,23689,23690,23692,23693,23695,23696,2281],{},"Once you statically generated your Nuxt app into ",[1220,23691,22853],{},", use ",[1220,23694,23079],{}," to start a production HTTP server and serve your static app, supporting ",[2006,23697,23699],{"href":23407,"rel":23698},[2010],"SPA Fallback",[1143,23701,23702],{},"This command is perfect to locally test your static application before pushing to your favorite static hosting provider.",[1147,23704,23317],{"id":10683},[1143,23706,23707],{},"We do support live preview out of the box to keep calling your API:",[1213,23709,23712],{"className":9317,"code":23710,"filename":23711,"language":9319,"meta":1218,"style":1218},"export default async function ({ query, enablePreview }) {\n  if (query.preview) {\n    enablePreview()\n  }\n}\n","plugins/preview.client.js",[1220,23713,23714,23740,23758,23765,23769],{"__ignoreMap":1218},[1223,23715,23716,23718,23720,23723,23725,23728,23731,23733,23736,23738],{"class":1225,"line":1226},[1223,23717,1745],{"class":1679},[1223,23719,1748],{"class":1679},[1223,23721,23722],{"class":1244}," async",[1223,23724,2321],{"class":1244},[1223,23726,23727],{"class":1236}," ({",[1223,23729,23730],{"class":2329}," query",[1223,23732,2333],{"class":1236},[1223,23734,23735],{"class":2329}," enablePreview",[1223,23737,6622],{"class":1236},[1223,23739,1891],{"class":1236},[1223,23741,23742,23744,23746,23749,23751,23754,23756],{"class":1225,"line":1233},[1223,23743,11033],{"class":1679},[1223,23745,3114],{"class":1240},[1223,23747,23748],{"class":1285},"query",[1223,23750,2281],{"class":1236},[1223,23752,23753],{"class":1285},"preview",[1223,23755,11048],{"class":1240},[1223,23757,1757],{"class":1236},[1223,23759,23760,23763],{"class":1225,"line":1263},[1223,23761,23762],{"class":1751},"    enablePreview",[1223,23764,1789],{"class":1240},[1223,23766,23767],{"class":1225,"line":1296},[1223,23768,1990],{"class":1236},[1223,23770,23771],{"class":1225,"line":1325},[1223,23772,2407],{"class":1236},[1143,23774,23775,23776,5062,23779,4363,23781,3681],{},"It will automatically refresh the page data (calling ",[1220,23777,23778],{},"nuxtServerInit",[1220,23780,13261],{},[1220,23782,16689],{},[1143,23784,23785,23786,4363,23788,23790],{},"When the preview mode is activated, ",[1220,23787,13261],{},[1220,23789,16689],{}," original methods will be called.",[1147,23792,655],{"id":17056},[1143,23794,23795,23796,23798],{},"Depending of the ",[1220,23797,22750],{},", you can run these commands.",[1852,23800,23801,23822],{},[1855,23802,23803,23805],{},[1220,23804,219],{},[1852,23806,23807,23812,23817],{},[1855,23808,23809,23811],{},[1220,23810,23090],{},": Start the development server",[1855,23813,23814,23816],{},[1220,23815,18007],{},": Bundle your Nuxt application for production",[1855,23818,23819,23821],{},[1220,23820,23079],{},": Start the production server",[1855,23823,23824,23826],{},[1220,23825,22754],{},[1852,23827,23828,23833,23841],{},[1855,23829,23830,23832],{},[1220,23831,23090],{},": Start the development server (static aware)",[1855,23834,23835,23837,23838,23840],{},[1220,23836,15824],{},": Bundle your Nuxt application for production if needed (static aware) and export your application to static HTML in ",[1220,23839,22853],{}," directory",[1855,23842,23843,23845,23846],{},[1220,23844,23079],{},": Serve your production application from ",[1220,23847,22853],{},[1155,23849,22612],{"id":23128},[3611,23851,23853],{"target":3615,"to":23852},"https://v2.nuxt.com/tutorials/moving-from-nuxtjs-dotenv-to-runtime-config",[1143,23854,23855,23856,23859],{},"Learn more about how to move from ",[1220,23857,23858],{},"@nuxtjs/dotenv"," to runtime config.",[2160,23861,23862],{},"html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .sV9sa, html code.shiki .sV9sa{--shiki-light:#F76D47;--shiki-default:#F76D47;--shiki-dark:#F78C6C}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 .ssYd4, html code.shiki .ssYd4{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":1218,"searchDepth":1233,"depth":1233,"links":23864},[23865,23866,23867,23868,23869,23871,23877,23879,23880],{"id":23187,"depth":1233,"text":23188},{"id":23243,"depth":1233,"text":23244},{"id":23331,"depth":1233,"text":23262},{"id":23346,"depth":1233,"text":23268},{"id":23430,"depth":1233,"text":23870},"New config option: target",{"id":23594,"depth":1233,"text":23872,"children":23873},"Smarter nuxt generate",[23874,23875,23876],{"id":23609,"depth":1263,"text":23292},{"id":23645,"depth":1263,"text":23298},{"id":23673,"depth":1263,"text":23304},{"id":23684,"depth":1233,"text":23878},"Smarter nuxt start",{"id":10683,"depth":1233,"text":23317},{"id":17056,"depth":1233,"text":655,"children":23881},[23882],{"id":23128,"depth":1263,"text":22612},"2020-06-18","Long awaited features for JAMstack fans has been shipped in v2.13: full static export, improved smart prefetching, integrated crawler, faster re-deploy, built-in web server and new target option for config ⚡️","/assets/blog/going-full-static.png",{},{"title":1088,"description":23884},"HbkpRUjk6b",{"id":23890,"title":1096,"authors":23891,"body":23898,"category":2176,"date":25512,"description":25513,"draft":108,"extension":1954,"image":25514,"meta":25515,"navigation":1739,"path":1097,"seo":25516,"stem":1098,"tags":6,"__hash__":25517},"blog/blog/7.understanding-how-fetch-works-in-nuxt-2-12.md",[23892],{"name":23893,"avatar":23894,"to":23896,"twitter":23897},"Krutie Patel",{"src":23895},"https://github.com/Krutie.png","https://x.com/KrutiePatel","KrutiePatel",{"type":1140,"value":23899,"toc":25481},[23900,23906,23909,23913,23930,23936,23944,23988,23991,23995,24001,24008,24012,24035,24038,24042,24048,24053,24067,24071,24076,24079,24085,24089,24092,24095,24099,24102,24128,24142,24144,24150,24157,24163,24171,24174,24197,24200,24318,24333,24566,24572,24576,24579,24617,24673,24677,24688,24699,24712,24760,24768,24773,24800,24810,24819,24903,24907,24917,24928,24931,24950,25058,25062,25081,25199,25203,25209,25217,25225,25238,25245,25256,25264,25273,25284,25322,25330,25372,25378,25383,25388,25394,25401,25409,25418,25422,25431,25441,25444,25451,25464,25466,25469,25472,25478],[1143,23901,23902,23903,23905],{},"Nuxt introduces a new ",[1220,23904,16689],{}," with the latest release of version 2.12. Fetch provides a brand new way to bring data into Nuxt applications.",[1143,23907,23908],{},"In this post, we will explore different features of the fetch hook and try to understand how it works.",[1147,23910,23912],{"id":23911},"fetch-hook-and-nuxt-lifecycle","Fetch Hook and Nuxt Lifecycle",[1143,23914,23915,23916,23918,23919,23922,23923,23926,23927,23929],{},"In terms of Nuxt lifecycle hooks, ",[1220,23917,16689],{}," sits within Vue lifecycle after ",[1220,23920,23921],{},"created"," hook. As we already know that, all Vue lifecycle hooks are called with their ",[1220,23924,23925],{},"this"," context. The same applies to ",[1220,23928,16689],{}," hook as well.",[1143,23931,23932],{},[2243,23933],{"alt":23934,"src":23935},"New fetch in Nuxt lifecycle","/assets/blog/new-fetch-lifecycle-hooks.png",[1143,23937,23938,23939,23941,23942,2281],{},"Fetch hook is called after the component instance is created on the server-side. That makes ",[1220,23940,23925],{}," context available inside the ",[1220,23943,16689],{},[1213,23945,23947],{"className":9317,"code":23946,"language":9319,"meta":1218,"style":1218},"export default {\n  fetch() {\n    console.log(this)\n  }\n}\n",[1220,23948,23949,23957,23966,23980,23984],{"__ignoreMap":1218},[1223,23950,23951,23953,23955],{"class":1225,"line":1226},[1223,23952,1745],{"class":1679},[1223,23954,1748],{"class":1679},[1223,23956,1891],{"class":1236},[1223,23958,23959,23962,23964],{"class":1225,"line":1233},[1223,23960,23961],{"class":1240},"  fetch",[1223,23963,1777],{"class":1236},[1223,23965,1891],{"class":1236},[1223,23967,23968,23970,23972,23974,23976,23978],{"class":1225,"line":1263},[1223,23969,6759],{"class":1285},[1223,23971,2281],{"class":1236},[1223,23973,6764],{"class":1751},[1223,23975,1754],{"class":1240},[1223,23977,23925],{"class":1236},[1223,23979,1804],{"class":1240},[1223,23981,23982],{"class":1225,"line":1296},[1223,23983,1990],{"class":1236},[1223,23985,23986],{"class":1225,"line":1325},[1223,23987,2407],{"class":1236},[1143,23989,23990],{},"Let’s see what this could mean for page components.",[1155,23992,23994],{"id":23993},"page-components","Page Components",[1143,23996,23997,23998,24000],{},"With the help of ",[1220,23999,23925],{}," context, fetch is able to mutate component’s data directly. It means we can set the component’s local data without having to dispatch Vuex store action or committing mutation from the page component.",[1143,24002,24003,24004,24007],{},"As a result, Vuex becomes optional, but not impossible. We can still use ",[1220,24005,24006],{},"this.$store"," as usual to access Vuex store if required.",[1147,24009,24011],{"id":24010},"availability-of-fetch-hook","Availability of fetch hook",[1143,24013,13273,24014,24016,24017,24020,24021,24024,24025,24027,24028,4363,24031,24034],{},[1220,24015,16689],{},", we can prefetch the data asynchronously ",[1159,24018,24019],{},"in any Vue components",". It means, other than page components found in ",[1220,24022,24023],{},"/pages"," directory, every other ",[1220,24026,9302],{}," components found in ",[1220,24029,24030],{},"/layouts",[1220,24032,24033],{},"/components"," directories can also benefit from the fetch hook.",[1143,24036,24037],{},"Let's see what this could mean for layout and building-block components.",[1155,24039,24041],{"id":24040},"layout-components","Layout Components",[1143,24043,24044,24045,24047],{},"Using new ",[1220,24046,16689],{},", now we can make API calls directly from the layout components. This was impossible prior to the release of v2.12.",[1143,24049,24050],{},[1159,24051,24052],{},"Possible use cases",[1852,24054,24055,24058,24061],{},[1855,24056,24057],{},"Fetch config data from the back-end in Nuxt layouts to generate footer and navbar dynamically",[1855,24059,24060],{},"Fetch user related data (i.e. user profile, shopping-cart item count) in the navbar",[1855,24062,24063,24064],{},"Fetch site relevant data on ",[1220,24065,24066],{},"layouts/error.vue",[1155,24068,24070],{"id":24069},"building-block-childnested-components","Building-block (Child/Nested) Components",[1143,24072,13273,24073,24075],{},[1220,24074,16689],{}," hook available in child components as well, we can off-load some of the data-fetching tasks from page-level components, and delegate them over to nested components. This was also impossible prior to the release of v2.12.",[1143,24077,24078],{},"This reduces the responsibility of route-level components to a great extent.",[1143,24080,24081,24084],{},[1159,24082,24083],{},"Possible use case -"," We can still pass props to child components, but if the child components need to have their own data-fetching logic, now they can!",[1147,24086,24088],{"id":24087},"call-order-of-multiple-fetch-hooks","Call order of multiple fetch hooks",[1143,24090,24091],{},"Since each component can have its own data-fetching logic, you may ask what would be the order in which each of them are called?",[1143,24093,24094],{},"Fetch hook is called on server-side once (on the first request to the Nuxt app) and then on client-side when navigating to further routes. But since we can define one fetch hook for each component, fetch hooks are called in sequence of their hierarchy.",[1155,24096,24098],{"id":24097},"disabling-fetch-on-server-side","Disabling fetch on server-side",[1143,24100,24101],{},"In addition, we can even disable fetch on the server-side if required.",[1213,24103,24105],{"className":9317,"code":24104,"language":9319,"meta":1218,"style":1218},"export default {\n  fetchOnServer: false\n}\n",[1220,24106,24107,24115,24124],{"__ignoreMap":1218},[1223,24108,24109,24111,24113],{"class":1225,"line":1226},[1223,24110,1745],{"class":1679},[1223,24112,1748],{"class":1679},[1223,24114,1891],{"class":1236},[1223,24116,24117,24120,24122],{"class":1225,"line":1233},[1223,24118,24119],{"class":1240},"  fetchOnServer",[1223,24121,1765],{"class":1236},[1223,24123,10665],{"class":2928},[1223,24125,24126],{"class":1225,"line":1263},[1223,24127,2407],{"class":1236},[1143,24129,24130,24131,24134,24135,24138,24139,24141],{},"And this way, the fetch hook will only be called on client-side. When ",[1220,24132,24133],{},"fetchOnServer"," is set to false, ",[1220,24136,24137],{},"$fetchState.pending"," becomes ",[1220,24140,9655],{}," when the component is rendered on server-side.",[1147,24143,74],{"id":21146},[1143,24145,24146,24147,24149],{},"New ",[1220,24148,16689],{}," handles error at component level. Let’s see how.",[1143,24151,24152,24153,24156],{},"Because we’re fetching data asynchronously, the new fetch() provides a ",[1220,24154,24155],{},"$fetchState"," object to check whether the request has finished and progressed successfully.",[1143,24158,24159,24160,24162],{},"Below is what the ",[1220,24161,24155],{}," object looks like.",[1213,24164,24169],{"className":24165,"code":24167,"language":24168},[24166],"language-text","$fetchState = {\n  pending: true | false,\n  error: null | {},\n  timestamp: Integer\n};\n","text",[1220,24170,24167],{"__ignoreMap":1218},[1143,24172,24173],{},"We have three keys,",[2412,24175,24176,24182,24188],{},[1855,24177,24178,24181],{},[1159,24179,24180],{},"Pending -"," lets you display a placeholder when fetch is being called on client-side",[1855,24183,24184,24187],{},[1159,24185,24186],{},"Error -"," lets you show an error message",[1855,24189,24190,24193,24194],{},[1159,24191,24192],{},"Timestamp -"," shows timestamp of the last fetch which is useful for caching with ",[1220,24195,24196],{},"keep-alive",[1143,24198,24199],{},"These keys are then used directly in the template area of the component to show relevant placeholders during the process of fetching data from the API.",[1213,24201,24203],{"className":1215,"code":24202,"language":1217,"meta":1218,"style":1218},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cp v-if=\"$fetchState.pending\">Fetching posts...\u003C/p>\n    \u003Cp v-else-if=\"$fetchState.error\">Error while fetching posts\u003C/p>\n    \u003Cul v-else>\n      …\n    \u003C/ul>\n  \u003C/div>\n\u003C/template>\n",[1220,24204,24205,24213,24221,24249,24278,24289,24294,24302,24310],{"__ignoreMap":1218},[1223,24206,24207,24209,24211],{"class":1225,"line":1226},[1223,24208,1237],{"class":1236},[1223,24210,2606],{"class":1240},[1223,24212,1260],{"class":1236},[1223,24214,24215,24217,24219],{"class":1225,"line":1233},[1223,24216,1266],{"class":1236},[1223,24218,1241],{"class":1240},[1223,24220,1260],{"class":1236},[1223,24222,24223,24225,24227,24230,24232,24234,24236,24238,24240,24243,24245,24247],{"class":1225,"line":1263},[1223,24224,5138],{"class":1236},[1223,24226,1143],{"class":1240},[1223,24228,24229],{"class":1244}," v-if",[1223,24231,1248],{"class":1236},[1223,24233,1251],{"class":1236},[1223,24235,24137],{"class":1254},[1223,24237,1251],{"class":1236},[1223,24239,1282],{"class":1236},[1223,24241,24242],{"class":1285},"Fetching posts...",[1223,24244,1289],{"class":1236},[1223,24246,1143],{"class":1240},[1223,24248,1260],{"class":1236},[1223,24250,24251,24253,24255,24258,24260,24262,24265,24267,24269,24272,24274,24276],{"class":1225,"line":1296},[1223,24252,5138],{"class":1236},[1223,24254,1143],{"class":1240},[1223,24256,24257],{"class":1244}," v-else-if",[1223,24259,1248],{"class":1236},[1223,24261,1251],{"class":1236},[1223,24263,24264],{"class":1254},"$fetchState.error",[1223,24266,1251],{"class":1236},[1223,24268,1282],{"class":1236},[1223,24270,24271],{"class":1285},"Error while fetching posts",[1223,24273,1289],{"class":1236},[1223,24275,1143],{"class":1240},[1223,24277,1260],{"class":1236},[1223,24279,24280,24282,24284,24287],{"class":1225,"line":1325},[1223,24281,5138],{"class":1236},[1223,24283,1852],{"class":1240},[1223,24285,24286],{"class":1244}," v-else",[1223,24288,1260],{"class":1236},[1223,24290,24291],{"class":1225,"line":1355},[1223,24292,24293],{"class":1285},"      …\n",[1223,24295,24296,24298,24300],{"class":1225,"line":1771},[1223,24297,5164],{"class":1236},[1223,24299,1852],{"class":1240},[1223,24301,1260],{"class":1236},[1223,24303,24304,24306,24308],{"class":1225,"line":1783},[1223,24305,5211],{"class":1236},[1223,24307,1241],{"class":1240},[1223,24309,1260],{"class":1236},[1223,24311,24312,24314,24316],{"class":1225,"line":1792},[1223,24313,1289],{"class":1236},[1223,24315,2606],{"class":1240},[1223,24317,1260],{"class":1236},[1143,24319,24320,24321,24324,24325,24328,24329,24332],{},"When error occurs at ",[1159,24322,24323],{},"component-level",", we can set HTTP status code on server-side by checking ",[1220,24326,24327],{},"process.server"," in fetch hook and follow it up with ",[1220,24330,24331],{},"throw new Error()"," statement.",[1213,24334,24336],{"className":9317,"code":24335,"language":9319,"meta":1218,"style":1218},"async fetch() {\n  const post = await fetch(`https://jsonplaceholder.typicode.com/posts/${this.$route.params.id}`)\n                     .then((res) => res.json())\n\n  if (post.id === this.$route.params.id) {\n      this.post = post\n    } else {\n      // set status code on server and\n      if (process.server) {\n        this.$nuxt.context.res.statusCode = 404\n      }\n      // use throw new Error()\n      throw new Error('Post not found')\n    }\n}\n",[1220,24337,24338,24349,24393,24420,24424,24456,24468,24478,24483,24501,24528,24532,24537,24558,24562],{"__ignoreMap":1218},[1223,24339,24340,24343,24345,24347],{"class":1225,"line":1226},[1223,24341,24342],{"class":1285},"async ",[1223,24344,16689],{"class":1751},[1223,24346,6659],{"class":1285},[1223,24348,1757],{"class":1236},[1223,24350,24351,24353,24356,24358,24360,24363,24365,24368,24371,24374,24377,24380,24382,24384,24386,24388,24391],{"class":1225,"line":1233},[1223,24352,2349],{"class":1244},[1223,24354,24355],{"class":1285}," post",[1223,24357,2339],{"class":1236},[1223,24359,10512],{"class":1679},[1223,24361,24362],{"class":1751}," fetch",[1223,24364,1754],{"class":1240},[1223,24366,24367],{"class":1236},"`",[1223,24369,24370],{"class":1254},"https://jsonplaceholder.typicode.com/posts/",[1223,24372,24373],{"class":1236},"${",[1223,24375,24376],{"class":1236},"this.",[1223,24378,24379],{"class":1285},"$route",[1223,24381,2281],{"class":1236},[1223,24383,3897],{"class":1285},[1223,24385,2281],{"class":1236},[1223,24387,3902],{"class":1285},[1223,24389,24390],{"class":1236},"}`",[1223,24392,1804],{"class":1240},[1223,24394,24395,24398,24400,24402,24404,24406,24408,24410,24413,24415,24417],{"class":1225,"line":1263},[1223,24396,24397],{"class":1236},"                     .",[1223,24399,12479],{"class":1751},[1223,24401,1754],{"class":1240},[1223,24403,1754],{"class":1236},[1223,24405,23374],{"class":2329},[1223,24407,2541],{"class":1236},[1223,24409,3125],{"class":1244},[1223,24411,24412],{"class":1285}," res",[1223,24414,2281],{"class":1236},[1223,24416,14315],{"class":1751},[1223,24418,24419],{"class":1240},"())\n",[1223,24421,24422],{"class":1225,"line":1296},[1223,24423,1740],{"emptyLinePlaceholder":1739},[1223,24425,24426,24428,24430,24433,24435,24437,24439,24442,24444,24446,24448,24450,24452,24454],{"class":1225,"line":1325},[1223,24427,11033],{"class":1679},[1223,24429,3114],{"class":1240},[1223,24431,24432],{"class":1285},"post",[1223,24434,2281],{"class":1236},[1223,24436,3902],{"class":1285},[1223,24438,7076],{"class":1236},[1223,24440,24441],{"class":1236}," this.",[1223,24443,24379],{"class":1285},[1223,24445,2281],{"class":1236},[1223,24447,3897],{"class":1285},[1223,24449,2281],{"class":1236},[1223,24451,3902],{"class":1285},[1223,24453,11048],{"class":1240},[1223,24455,1757],{"class":1236},[1223,24457,24458,24461,24463,24465],{"class":1225,"line":1355},[1223,24459,24460],{"class":1236},"      this.",[1223,24462,24432],{"class":1285},[1223,24464,2339],{"class":1236},[1223,24466,24467],{"class":1285}," post\n",[1223,24469,24470,24473,24476],{"class":1225,"line":1771},[1223,24471,24472],{"class":1236},"    }",[1223,24474,24475],{"class":1679}," else",[1223,24477,1891],{"class":1236},[1223,24479,24480],{"class":1225,"line":1783},[1223,24481,24482],{"class":1229},"      // set status code on server and\n",[1223,24484,24485,24488,24490,24493,24495,24497,24499],{"class":1225,"line":1792},[1223,24486,24487],{"class":1679},"      if",[1223,24489,3114],{"class":1240},[1223,24491,24492],{"class":1285},"process",[1223,24494,2281],{"class":1236},[1223,24496,219],{"class":1285},[1223,24498,11048],{"class":1240},[1223,24500,1757],{"class":1236},[1223,24502,24503,24506,24509,24511,24514,24516,24518,24520,24523,24525],{"class":1225,"line":1798},[1223,24504,24505],{"class":1236},"        this.",[1223,24507,24508],{"class":1285},"$nuxt",[1223,24510,2281],{"class":1236},[1223,24512,24513],{"class":1285},"context",[1223,24515,2281],{"class":1236},[1223,24517,23374],{"class":1285},[1223,24519,2281],{"class":1236},[1223,24521,24522],{"class":1285},"statusCode",[1223,24524,2339],{"class":1236},[1223,24526,24527],{"class":6166}," 404\n",[1223,24529,24530],{"class":1225,"line":1975},[1223,24531,1978],{"class":1236},[1223,24533,24534],{"class":1225,"line":1981},[1223,24535,24536],{"class":1229},"      // use throw new Error()\n",[1223,24538,24539,24542,24544,24547,24549,24551,24554,24556],{"class":1225,"line":1987},[1223,24540,24541],{"class":1679},"      throw",[1223,24543,3222],{"class":1236},[1223,24545,24546],{"class":1751}," Error",[1223,24548,1754],{"class":1240},[1223,24550,1957],{"class":1236},[1223,24552,24553],{"class":1254},"Post not found",[1223,24555,1957],{"class":1236},[1223,24557,1804],{"class":1240},[1223,24559,24560],{"class":1225,"line":1993},[1223,24561,1984],{"class":1236},[1223,24563,24564],{"class":1225,"line":2720},[1223,24565,2407],{"class":1236},[1143,24567,24568,24569,2281],{},"Setting the HTTP status code this way ",[1159,24570,24571],{},"is useful for correct SEO",[1147,24573,24575],{"id":24574},"fetch-as-a-method","Fetch as a method",[1143,24577,24578],{},"New fetch hook also acts as a method that can be invoked upon user interaction or invoked programmatically from the component methods.",[1213,24580,24582],{"className":1215,"code":24581,"language":1217,"meta":1218,"style":1218},"\u003C!-- from template in template  -->\n\u003Cbutton @click=\"$fetch\">Refresh Data\u003C/button>\n",[1220,24583,24584,24589],{"__ignoreMap":1218},[1223,24585,24586],{"class":1225,"line":1226},[1223,24587,24588],{"class":1229},"\u003C!-- from template in template  -->\n",[1223,24590,24591,24593,24595,24598,24600,24602,24604,24606,24608,24611,24613,24615],{"class":1225,"line":1233},[1223,24592,1237],{"class":1236},[1223,24594,1330],{"class":1240},[1223,24596,24597],{"class":1244}," @click",[1223,24599,1248],{"class":1236},[1223,24601,1251],{"class":1236},[1223,24603,547],{"class":1254},[1223,24605,1251],{"class":1236},[1223,24607,1282],{"class":1236},[1223,24609,24610],{"class":1285},"Refresh Data",[1223,24612,1289],{"class":1236},[1223,24614,1330],{"class":1240},[1223,24616,1260],{"class":1236},[1213,24618,24620],{"className":9317,"code":24619,"language":9319,"meta":1218,"style":1218},"// from component methods in script section\nexport default {\n  methods: {\n    refresh() {\n      this.$fetch()\n    }\n  }\n}\n",[1220,24621,24622,24627,24635,24644,24653,24661,24665,24669],{"__ignoreMap":1218},[1223,24623,24624],{"class":1225,"line":1226},[1223,24625,24626],{"class":1229},"// from component methods in script section\n",[1223,24628,24629,24631,24633],{"class":1225,"line":1233},[1223,24630,1745],{"class":1679},[1223,24632,1748],{"class":1679},[1223,24634,1891],{"class":1236},[1223,24636,24637,24640,24642],{"class":1225,"line":1263},[1223,24638,24639],{"class":1240},"  methods",[1223,24641,1765],{"class":1236},[1223,24643,1891],{"class":1236},[1223,24645,24646,24649,24651],{"class":1225,"line":1296},[1223,24647,24648],{"class":1240},"    refresh",[1223,24650,1777],{"class":1236},[1223,24652,1891],{"class":1236},[1223,24654,24655,24657,24659],{"class":1225,"line":1325},[1223,24656,24460],{"class":1236},[1223,24658,547],{"class":1751},[1223,24660,1789],{"class":1240},[1223,24662,24663],{"class":1225,"line":1355},[1223,24664,1984],{"class":1236},[1223,24666,24667],{"class":1225,"line":1771},[1223,24668,1990],{"class":1236},[1223,24670,24671],{"class":1225,"line":1783},[1223,24672,2407],{"class":1236},[1147,24674,24676],{"id":24675},"making-nuxt-pages-more-performant","Making Nuxt pages more performant",[1143,24678,24679,24680,24683,24684,24687],{},"We can use ",[1220,24681,24682],{},":keep-alive-props"," prop and ",[1220,24685,24686],{},"activated"," hook to make Nuxt page components more performant using a new fetch hook.",[1143,24689,24690,24691,24694,24695,24698],{},"Nuxt allows ",[1159,24692,24693],{},"caching a certain number of pages"," in the memory along with their fetched data. And also allows ",[1159,24696,24697],{},"adding a number of seconds"," before we can re-fetch the data.",[1143,24700,24701,24702,24704,24705,4363,24708,24711],{},"For any of the above methods to work, we have to use the ",[1220,24703,24196],{}," prop in generic ",[1220,24706,24707],{},"\u003Cnuxt />",[1220,24709,24710],{},"\u003Cnuxt-child","> components.",[1213,24713,24715],{"className":1215,"code":24714,"filename":9310,"language":1217,"meta":1218,"style":1218},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cnuxt keep-alive />\n  \u003C/div>\n\u003C/template>\n",[1220,24716,24717,24725,24733,24744,24752],{"__ignoreMap":1218},[1223,24718,24719,24721,24723],{"class":1225,"line":1226},[1223,24720,1237],{"class":1236},[1223,24722,2606],{"class":1240},[1223,24724,1260],{"class":1236},[1223,24726,24727,24729,24731],{"class":1225,"line":1233},[1223,24728,1266],{"class":1236},[1223,24730,1241],{"class":1240},[1223,24732,1260],{"class":1236},[1223,24734,24735,24737,24739,24742],{"class":1225,"line":1263},[1223,24736,5138],{"class":1236},[1223,24738,2367],{"class":1240},[1223,24740,24741],{"class":1244}," keep-alive",[1223,24743,2626],{"class":1236},[1223,24745,24746,24748,24750],{"class":1225,"line":1296},[1223,24747,5211],{"class":1236},[1223,24749,1241],{"class":1240},[1223,24751,1260],{"class":1236},[1223,24753,24754,24756,24758],{"class":1225,"line":1325},[1223,24755,1289],{"class":1236},[1223,24757,2606],{"class":1240},[1223,24759,1260],{"class":1236},[1143,24761,24762,24763,4880,24765,24767],{},"In addition, we can pass ",[1220,24764,24682],{},[1220,24766,24707],{}," component to cache a number of pages along with their fetched data.",[1143,24769,24770,24772],{},[1220,24771,24682],{}," prop allow us to indicate the maximum number of pages that should be kept in the memory while we navigate elsewhere within the site.",[1213,24774,24776],{"className":1215,"code":24775,"filename":9310,"language":1217,"meta":1218,"style":1218},"\u003Cnuxt keep-alive :keep-alive-props=\"{ max: 10 }\" />\n",[1220,24777,24778],{"__ignoreMap":1218},[1223,24779,24780,24782,24784,24786,24789,24791,24793,24796,24798],{"class":1225,"line":1226},[1223,24781,1237],{"class":1236},[1223,24783,2367],{"class":1240},[1223,24785,24741],{"class":1244},[1223,24787,24788],{"class":1244}," :keep-alive-props",[1223,24790,1248],{"class":1236},[1223,24792,1251],{"class":1236},[1223,24794,24795],{"class":1254},"{ max: 10 }",[1223,24797,1251],{"class":1236},[1223,24799,2626],{"class":1236},[1143,24801,24802,24803,24806,24807,24809],{},"Above is one way to boost page performance which is more high-level and generic, while the next one drills down to optimize the fetch request calls by using the ",[1220,24804,24805],{},"timestamp"," property of ",[1220,24808,24155],{}," and comparing it against the number of seconds delay before it re-fetches the data.",[1143,24811,24812,24813,24815,24816,24818],{},"Vue’s ",[1220,24814,24686],{}," hook is used here with Nuxt's ",[1220,24817,24196],{}," prop to re-fetch the data.",[1213,24820,24822],{"className":9317,"code":24821,"language":9319,"meta":1218,"style":1218},"export default {\n  activated() {\n    // Call fetch again if last fetch more than a minute ago\n    if (this.$fetchState.timestamp \u003C= Date.now() - 60000) {\n      this.$fetch()\n    }\n  }\n}\n",[1220,24823,24824,24832,24841,24846,24883,24891,24895,24899],{"__ignoreMap":1218},[1223,24825,24826,24828,24830],{"class":1225,"line":1226},[1223,24827,1745],{"class":1679},[1223,24829,1748],{"class":1679},[1223,24831,1891],{"class":1236},[1223,24833,24834,24837,24839],{"class":1225,"line":1233},[1223,24835,24836],{"class":1240},"  activated",[1223,24838,1777],{"class":1236},[1223,24840,1891],{"class":1236},[1223,24842,24843],{"class":1225,"line":1263},[1223,24844,24845],{"class":1229},"    // Call fetch again if last fetch more than a minute ago\n",[1223,24847,24848,24851,24853,24855,24857,24859,24861,24864,24867,24869,24872,24874,24876,24879,24881],{"class":1225,"line":1296},[1223,24849,24850],{"class":1679},"    if",[1223,24852,3114],{"class":1240},[1223,24854,24376],{"class":1236},[1223,24856,24155],{"class":1285},[1223,24858,2281],{"class":1236},[1223,24860,24805],{"class":1285},[1223,24862,24863],{"class":1236}," \u003C=",[1223,24865,24866],{"class":1285}," Date",[1223,24868,2281],{"class":1236},[1223,24870,24871],{"class":1751},"now",[1223,24873,6659],{"class":1240},[1223,24875,5004],{"class":1236},[1223,24877,24878],{"class":6166}," 60000",[1223,24880,11048],{"class":1240},[1223,24882,1757],{"class":1236},[1223,24884,24885,24887,24889],{"class":1225,"line":1325},[1223,24886,24460],{"class":1236},[1223,24888,547],{"class":1751},[1223,24890,1789],{"class":1240},[1223,24892,24893],{"class":1225,"line":1355},[1223,24894,1984],{"class":1236},[1223,24896,24897],{"class":1225,"line":1771},[1223,24898,1990],{"class":1236},[1223,24900,24901],{"class":1225,"line":1783},[1223,24902,2407],{"class":1236},[1147,24904,24906],{"id":24905},"asyncdata-vs-fetch","asyncData vs Fetch",[1143,24908,24909,24910,24912,24913,24916],{},"As far as page components are concerned, new ",[1220,24911,16689],{}," seems way too similar to ",[1220,24914,24915],{},"asyncData()"," because they both deal with the local data. But there are some key differences worth taking note of as below.",[1143,24918,24919,24920,24922,24923,24925,24926,2281],{},"As of Nuxt 2.12, ",[1220,24921,13261],{}," method is still an active feature. Let’s examine some of the key differences between ",[1220,24924,13261],{}," and new ",[1220,24927,16689],{},[1155,24929,13261],{"id":24930},"asyncdata",[2412,24932,24933,24938,24943],{},[1855,24934,24935,24937],{},[1220,24936,13261],{}," is limited to only page-level components",[1855,24939,24940,24942],{},[1220,24941,23925],{}," context is unavailable",[1855,24944,24945,24946,24949],{},"Adds payload by ",[1159,24947,24948],{},"returning"," the data",[1213,24951,24953],{"className":9317,"code":24952,"language":9319,"meta":1218,"style":1218},"export default {\n  async asyncData(context) {\n    const data = await context.$axios.$get(\n      `https://jsonplaceholder.typicode.com/todos`\n    )\n    // `todos` does not have to be declared in data()\n    return { todos: data.Item }\n    // `todos` is merged with local data\n  }\n}\n",[1220,24954,24955,24963,24978,25004,25015,25020,25025,25045,25050,25054],{"__ignoreMap":1218},[1223,24956,24957,24959,24961],{"class":1225,"line":1226},[1223,24958,1745],{"class":1679},[1223,24960,1748],{"class":1679},[1223,24962,1891],{"class":1236},[1223,24964,24965,24967,24970,24972,24974,24976],{"class":1225,"line":1233},[1223,24966,19816],{"class":1244},[1223,24968,24969],{"class":1240}," asyncData",[1223,24971,1754],{"class":1236},[1223,24973,24513],{"class":2329},[1223,24975,2541],{"class":1236},[1223,24977,1891],{"class":1236},[1223,24979,24980,24983,24985,24987,24989,24992,24994,24997,24999,25002],{"class":1225,"line":1263},[1223,24981,24982],{"class":1244},"    const",[1223,24984,10957],{"class":1285},[1223,24986,2339],{"class":1236},[1223,24988,10512],{"class":1679},[1223,24990,24991],{"class":1285}," context",[1223,24993,2281],{"class":1236},[1223,24995,24996],{"class":1285},"$axios",[1223,24998,2281],{"class":1236},[1223,25000,25001],{"class":1751},"$get",[1223,25003,9141],{"class":1240},[1223,25005,25006,25009,25012],{"class":1225,"line":1296},[1223,25007,25008],{"class":1236},"      `",[1223,25010,25011],{"class":1254},"https://jsonplaceholder.typicode.com/todos",[1223,25013,25014],{"class":1236},"`\n",[1223,25016,25017],{"class":1225,"line":1325},[1223,25018,25019],{"class":1240},"    )\n",[1223,25021,25022],{"class":1225,"line":1355},[1223,25023,25024],{"class":1229},"    // `todos` does not have to be declared in data()\n",[1223,25026,25027,25029,25031,25034,25036,25038,25040,25043],{"class":1225,"line":1771},[1223,25028,3190],{"class":1679},[1223,25030,1683],{"class":1236},[1223,25032,25033],{"class":1240}," todos",[1223,25035,1765],{"class":1236},[1223,25037,10957],{"class":1285},[1223,25039,2281],{"class":1236},[1223,25041,25042],{"class":1285},"Item",[1223,25044,5311],{"class":1236},[1223,25046,25047],{"class":1225,"line":1783},[1223,25048,25049],{"class":1229},"    // `todos` is merged with local data\n",[1223,25051,25052],{"class":1225,"line":1792},[1223,25053,1990],{"class":1236},[1223,25055,25056],{"class":1225,"line":1798},[1223,25057,2407],{"class":1236},[1155,25059,25061],{"id":25060},"new-fetch","New Fetch",[2412,25063,25064,25069,25074],{},[1855,25065,25066,25068],{},[1220,25067,16689],{}," is available in all Vue components",[1855,25070,25071,25073],{},[1220,25072,23925],{}," context is available",[1855,25075,25076,25077,25080],{},"Simply ",[1159,25078,25079],{},"mutates"," the local data",[1213,25082,25084],{"className":9317,"code":25083,"language":9319,"meta":1218,"style":1218},"export default {\n  data() {\n    return {\n      todos: []\n    }\n  },\n  async fetch() {\n    const { data } = await axios.get(\n      `https://jsonplaceholder.typicode.com/todos`\n    )\n    // `todos` has to be declared in data()\n    this.todos = data\n  }\n}\n",[1220,25085,25086,25094,25103,25109,25119,25123,25127,25137,25161,25169,25173,25178,25191,25195],{"__ignoreMap":1218},[1223,25087,25088,25090,25092],{"class":1225,"line":1226},[1223,25089,1745],{"class":1679},[1223,25091,1748],{"class":1679},[1223,25093,1891],{"class":1236},[1223,25095,25096,25099,25101],{"class":1225,"line":1233},[1223,25097,25098],{"class":1240},"  data",[1223,25100,1777],{"class":1236},[1223,25102,1891],{"class":1236},[1223,25104,25105,25107],{"class":1225,"line":1263},[1223,25106,3190],{"class":1679},[1223,25108,1891],{"class":1236},[1223,25110,25111,25114,25116],{"class":1225,"line":1296},[1223,25112,25113],{"class":1240},"      todos",[1223,25115,1765],{"class":1236},[1223,25117,25118],{"class":1240}," []\n",[1223,25120,25121],{"class":1225,"line":1325},[1223,25122,1984],{"class":1236},[1223,25124,25125],{"class":1225,"line":1355},[1223,25126,3312],{"class":1236},[1223,25128,25129,25131,25133,25135],{"class":1225,"line":1771},[1223,25130,19816],{"class":1244},[1223,25132,24362],{"class":1240},[1223,25134,1777],{"class":1236},[1223,25136,1891],{"class":1236},[1223,25138,25139,25141,25143,25145,25147,25149,25151,25154,25156,25159],{"class":1225,"line":1783},[1223,25140,24982],{"class":1244},[1223,25142,1683],{"class":1236},[1223,25144,10957],{"class":1285},[1223,25146,1689],{"class":1236},[1223,25148,2339],{"class":1236},[1223,25150,10512],{"class":1679},[1223,25152,25153],{"class":1285}," axios",[1223,25155,2281],{"class":1236},[1223,25157,25158],{"class":1751},"get",[1223,25160,9141],{"class":1240},[1223,25162,25163,25165,25167],{"class":1225,"line":1792},[1223,25164,25008],{"class":1236},[1223,25166,25011],{"class":1254},[1223,25168,25014],{"class":1236},[1223,25170,25171],{"class":1225,"line":1798},[1223,25172,25019],{"class":1240},[1223,25174,25175],{"class":1225,"line":1975},[1223,25176,25177],{"class":1229},"    // `todos` has to be declared in data()\n",[1223,25179,25180,25183,25186,25188],{"class":1225,"line":1981},[1223,25181,25182],{"class":1236},"    this.",[1223,25184,25185],{"class":1285},"todos",[1223,25187,2339],{"class":1236},[1223,25189,25190],{"class":1285}," data\n",[1223,25192,25193],{"class":1225,"line":1987},[1223,25194,1990],{"class":1236},[1223,25196,25197],{"class":1225,"line":1993},[1223,25198,2407],{"class":1236},[1147,25200,25202],{"id":25201},"fetch-before-nuxt-212","Fetch before Nuxt 2.12",[1143,25204,25205,25206,25208],{},"If you have been working with Nuxt for a while, then you’ll know that the previous version of ",[1220,25207,16689],{}," was significantly different.",[25210,25211,25212],"blockquote",{},[1143,25213,25214],{},[1159,25215,25216],{},"Is this a breaking change?",[25210,25218,25219],{},[1143,25220,25221,25222,25224],{},"No, it isn't. Actually, the old fetch can still be used by passing the ",[1220,25223,24513],{}," as the first argument to avoid any breaking changes in your existing Nuxt applications.",[1143,25226,25227,25228,25230,25231,4363,25234,25237],{},"Here’s the list of notable changes in ",[1220,25229,16689],{}," hook compared with ",[1159,25232,25233],{},"before",[1159,25235,25236],{},"after"," v2.12.",[1155,25239,25241,25242,25244],{"id":25240},"_1-call-order-of-fetch-hook","1. Call order of ",[1220,25243,16689],{}," hook",[1143,25246,25247,8602,25250,25252,25253,25255],{},[1159,25248,25249],{},"Before -",[1220,25251,16689],{}," hook was called before initiating the component, hence ",[1220,25254,23925],{}," wasn’t available inside the fetch hook.",[1143,25257,25258,8602,25261,25263],{},[1159,25259,25260],{},"After -",[1220,25262,16689],{}," is called after the component instance is created on the server-side when the route is accessed.",[1155,25265,25267,25268,25270,25271],{"id":25266},"_2-this-vs-context","2. ",[1220,25269,23925],{}," vs ",[1220,25272,24513],{},[1143,25274,25275,25277,25278,25280,25281,25283],{},[1159,25276,25249],{}," We had access to the Nuxt ",[1220,25279,24513],{}," on page-level components, given that the ",[1220,25282,24513],{}," is passed as a first parameter.",[1213,25285,25287],{"className":9317,"code":25286,"language":9319,"meta":1218,"style":1218},"export default {\n  fetch(context) {\n    // …\n  }\n}\n",[1220,25288,25289,25297,25309,25314,25318],{"__ignoreMap":1218},[1223,25290,25291,25293,25295],{"class":1225,"line":1226},[1223,25292,1745],{"class":1679},[1223,25294,1748],{"class":1679},[1223,25296,1891],{"class":1236},[1223,25298,25299,25301,25303,25305,25307],{"class":1225,"line":1233},[1223,25300,23961],{"class":1240},[1223,25302,1754],{"class":1236},[1223,25304,24513],{"class":2329},[1223,25306,2541],{"class":1236},[1223,25308,1891],{"class":1236},[1223,25310,25311],{"class":1225,"line":1263},[1223,25312,25313],{"class":1229},"    // …\n",[1223,25315,25316],{"class":1225,"line":1296},[1223,25317,1990],{"class":1236},[1223,25319,25320],{"class":1225,"line":1325},[1223,25321,2407],{"class":1236},[1143,25323,25324,25326,25327,25329],{},[1159,25325,25260],{}," We can access ",[1220,25328,23925],{}," context just like Vue client-side hooks without passing any parameters.",[1213,25331,25332],{"className":9317,"code":23946,"language":9319,"meta":1218,"style":1218},[1220,25333,25334,25342,25350,25364,25368],{"__ignoreMap":1218},[1223,25335,25336,25338,25340],{"class":1225,"line":1226},[1223,25337,1745],{"class":1679},[1223,25339,1748],{"class":1679},[1223,25341,1891],{"class":1236},[1223,25343,25344,25346,25348],{"class":1225,"line":1233},[1223,25345,23961],{"class":1240},[1223,25347,1777],{"class":1236},[1223,25349,1891],{"class":1236},[1223,25351,25352,25354,25356,25358,25360,25362],{"class":1225,"line":1263},[1223,25353,6759],{"class":1285},[1223,25355,2281],{"class":1236},[1223,25357,6764],{"class":1751},[1223,25359,1754],{"class":1240},[1223,25361,23925],{"class":1236},[1223,25363,1804],{"class":1240},[1223,25365,25366],{"class":1225,"line":1296},[1223,25367,1990],{"class":1236},[1223,25369,25370],{"class":1225,"line":1325},[1223,25371,2407],{"class":1236},[1155,25373,25375,25376,25244],{"id":25374},"_3-availability-of-fetch-hook","3. Availability of ",[1220,25377,16689],{},[1143,25379,25380,25382],{},[1159,25381,25249],{}," Only page (route-level) components were allowed to fetch data on the server-side.",[1143,25384,25385,25387],{},[1159,25386,25260],{}," Now, we can prefetch the data asynchronously in any Vue components.",[1155,25389,25391,25392,25244],{"id":25390},"_4-call-order-of-fetch-hook","4. Call order of ",[1220,25393,16689],{},[1143,25395,25396,8602,25398,25400],{},[1159,25397,25249],{},[1220,25399,16689],{}," could be called server-side once (on the first request to the Nuxt app) and client-side when navigating to further routes.",[1143,25402,25403,25405,25406,25408],{},[1159,25404,25260],{}," New ",[1220,25407,16689],{}," is the same as an old fetch, but…",[1143,25410,25411,25412,25414,25415,25417],{},"…since we can have one ",[1220,25413,16689],{}," for each component, ",[1220,25416,16689],{}," hooks are called in sequence of their hierarchy.",[1155,25419,25421],{"id":25420},"_5-error-handling","5. Error Handling",[1143,25423,25424,25426,25427,25430],{},[1159,25425,25249],{}," We used the ",[1220,25428,25429],{},"context.error"," function that showed a custom error page when an error occurred during API calls.",[1143,25432,25433,25405,25435,25437,25438,25440],{},[1159,25434,25260],{},[1220,25436,16689],{}," uses the ",[1220,25439,24155],{}," object to handle errors in the template area during API calls.",[1143,25442,25443],{},"Error handling is performed at component level.",[25210,25445,25446],{},[1143,25447,25448],{},[1159,25449,25450],{},"Does this mean we cannot show users a custom error page like we did prior to Nuxt 2.12?",[1143,25452,25453,25454,25456,25457,25459,25460,25463],{},"Yes we can, but only with ",[1220,25455,24915],{}," when it's about page-level component data. When using ",[1220,25458,16689],{},", we can utilize ",[1220,25461,25462],{},"this.$nuxt.error({ statusCode: 404, message: 'Data not found' })"," to show a custom error page.",[1147,25465,15562],{"id":15561},[1143,25467,25468],{},"New fetch hook brings a lot of improvements and provides more flexibility in fetching data and organizing route-level & building-block components in a whole new way!",[1143,25470,25471],{},"It will certainly make you think a little differently when you plan and design your new Nuxt project that requires multiple API calls within the same route.",[1143,25473,25474,25475,25477],{},"I hope this article has helped you get acquainted with the new ",[1220,25476,16689],{}," feature. I'd love to see what you build with it.",[2160,25479,25480],{},"html pre.shiki code .sFVN2, html code.shiki .sFVN2{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sYp4K, html code.shiki .sYp4K{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .sQ5dg, html code.shiki .sQ5dg{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .spdxX, html code.shiki .spdxX{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .szd4z, html code.shiki .szd4z{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}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 .sagxc, html code.shiki .sagxc{--shiki-light:#FF5370;--shiki-default:#FF5370;--shiki-dark:#FF9CAC}html pre.shiki code .sRBFq, html code.shiki .sRBFq{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .s5UST, html code.shiki .s5UST{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}html pre.shiki code .ssYd4, html code.shiki .ssYd4{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .svXlt, html code.shiki .svXlt{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sV9sa, html code.shiki .sV9sa{--shiki-light:#F76D47;--shiki-default:#F76D47;--shiki-dark:#F78C6C}",{"title":1218,"searchDepth":1233,"depth":1233,"links":25482},[25483,25486,25490,25493,25494,25495,25496,25500,25511],{"id":23911,"depth":1233,"text":23912,"children":25484},[25485],{"id":23993,"depth":1263,"text":23994},{"id":24010,"depth":1233,"text":24011,"children":25487},[25488,25489],{"id":24040,"depth":1263,"text":24041},{"id":24069,"depth":1263,"text":24070},{"id":24087,"depth":1233,"text":24088,"children":25491},[25492],{"id":24097,"depth":1263,"text":24098},{"id":21146,"depth":1233,"text":74},{"id":24574,"depth":1233,"text":24575},{"id":24675,"depth":1233,"text":24676},{"id":24905,"depth":1233,"text":24906,"children":25497},[25498,25499],{"id":24930,"depth":1263,"text":13261},{"id":25060,"depth":1263,"text":25061},{"id":25201,"depth":1233,"text":25202,"children":25501},[25502,25504,25506,25508,25510],{"id":25240,"depth":1263,"text":25503},"1. Call order of fetch hook",{"id":25266,"depth":1263,"text":25505},"2. this vs context",{"id":25374,"depth":1263,"text":25507},"3. Availability of fetch hook",{"id":25390,"depth":1263,"text":25509},"4. Call order of fetch hook",{"id":25420,"depth":1263,"text":25421},{"id":15561,"depth":1233,"text":15562},"2020-04-06","Explore different features of the fetch hook and learn a brand new way to bring data into Nuxt applications.","/assets/blog/understanding-how-fetch-works-in-nuxt-2.12.png",{},{"title":1096,"description":25513},"VPd2sK2rQZ",{"id":25519,"title":1104,"authors":25520,"body":25523,"category":2176,"date":25655,"description":25656,"draft":108,"extension":1954,"image":25657,"meta":25658,"navigation":1739,"path":1105,"seo":25659,"stem":1106,"tags":6,"__hash__":25660},"blog/blog/9.nuxtjs-from-terminal-to-browser.md",[25521],{"name":1130,"avatar":25522,"to":1133,"twitter":7721},{"src":1132},{"type":1140,"value":25524,"toc":25650},[25525,25534,25544,25551,25561,25568,25573,25579,25584,25590,25595,25601,25608,25611,25614,25619,25622],[25210,25526,25527],{},[1143,25528,25529,25530,25533],{},"Nuxt is a Vue.js framework to create different kind of web applications with the ",[1159,25531,25532],{},"same directory structure & conventions",": Universal, Single Page, PWA or Static Generated.",[1143,25535,25536],{},[3746,25537,25538,25539,2281],{},"ℹ️ These features are all available with ",[2006,25540,25543],{"href":25541,"rel":25542},"https://github.com/nuxt/nuxt.js/releases/tag/v2.8.0",[2010],"v2.8.0 release",[1147,25545,25547,25550],{"id":25546},"problems",[2006,25548],{"href":25549},"#problems","Problems",[2412,25552,25553,25556],{},[1855,25554,25555],{},"Developing JavaScript applications with Webpack or any bundler requires to switch between your browser and terminal for debugging purpose.",[1855,25557,2483,25558,25560],{},[1220,25559,10439],{}," to debug when the app is server rendered requires to remember that logs will be displayed on the terminal when refreshing the page.",[1147,25562,25564,25567],{"id":25563},"solutions",[2006,25565],{"href":25566},"#solutions","Solutions",[2412,25569,25570],{},[1855,25571,25572],{},"Forwarding Webpack build state right in the browser and display them in a fancy manner.",[1143,25574,25575],{},[2243,25576],{"alt":25577,"src":25578},"foward-webpack-build-state","https://res.cloudinary.com/practicaldev/image/fetch/s--1u6wSHPt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/904724/58880743-ec7a3280-86d8-11e9-8856-8d9d22b89b70.gif",[2412,25580,25581],{"start":1233},[1855,25582,25583],{},"Same for Hot Module Replacement (really useful when the project gets bigger and takes more time to re-build).",[1143,25585,25586],{},[2243,25587],{"alt":25588,"src":25589},"nuxt-build-indicator-hmr","https://res.cloudinary.com/practicaldev/image/fetch/s--faVtF222--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/904724/58547105-129a6100-8207-11e9-9c61-a93956a17727.gif",[2412,25591,25592],{"start":1263},[1855,25593,25594],{},"Forwarding SSR logs to the browser in development mode",[1143,25596,25597],{},[2243,25598],{"alt":25599,"src":25600},"nuxt-ssr-logs-forwarding","https://res.cloudinary.com/practicaldev/image/fetch/s--bwQ8iEq2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/904724/58566291-a3396700-8230-11e9-9dd6-09c3ff8578d2.gif",[1147,25602,25604,25607],{"id":25603},"nuxt-vision",[2006,25605],{"href":25606},"#nuxtjs-vision","Nuxt Vision",[1143,25609,25610],{},"The purpose to these changes is to use the terminal for commands only.",[1143,25612,25613],{},"Now you can focus right on your code and its visual result 🙂",[25210,25615,25616],{},[1143,25617,25618],{},"Be lazy, be smart, be Nuxt.",[1143,25620,25621],{},"Links:",[1852,25623,25624,25630,25637,25644],{},[1855,25625,25626,25627],{},"Nuxt 2 docs: ",[2006,25628,21611],{"href":21611,"rel":25629},[2010],[1855,25631,25632,25633],{},"GitHub: ",[2006,25634,25635],{"href":25635,"rel":25636},"https://github.com/nuxt/nuxt.js",[2010],[1855,25638,25639,25640],{},"Loading Screen source code: ",[2006,25641,25642],{"href":25642,"rel":25643},"https://github.com/nuxt/loading-screen",[2010],[1855,25645,25646,25647],{},"Twitter: ",[2006,25648,10289],{"href":10289,"rel":25649},[2010],{"title":1218,"searchDepth":1233,"depth":1233,"links":25651},[25652,25653,25654],{"id":25546,"depth":1233,"text":25550},{"id":25563,"depth":1233,"text":25567},{"id":25603,"depth":1233,"text":25607},"2019-06-03","How we changed the developer experience to stop switching between the terminal and browser.","/assets/blog/nuxt-from-terminal-to-browser.png",{},{"title":1104,"description":25656},"FoIypGB1cD",{"id":25662,"title":1092,"authors":25663,"body":25666,"category":2176,"date":25732,"description":25733,"draft":108,"extension":1954,"image":25734,"meta":25735,"navigation":1739,"path":1093,"seo":25736,"stem":1094,"tags":6,"__hash__":25737},"blog/blog/6.introducing-smart-prefetching.md",[25664],{"name":1130,"avatar":25665,"to":1133,"twitter":7721},{"src":7720},{"type":1140,"value":25667,"toc":25729},[25668,25672,25694,25700,25703,25719],[1147,25669,25671],{"id":25670},"introducing-smart-prefetching-️","Introducing Smart prefetching ⚡️",[1143,25673,25674,25675,25680,25681,25684,25685,25688,25689,2281],{},"Starting from ",[2006,25676,25679],{"href":25677,"rel":25678},"https://github.com/nuxt/nuxt.js/releases/tag/v2.4.0",[2010],"Nuxt v2.4.0",", Nuxt will automagically prefetch the code-splitted pages linked with ",[1220,25682,25683],{},"\u003Cnuxt-link>"," when visible in the viewport ",[1159,25686,25687],{},"by default",". This hugely improves the end user performances, inspired by ",[2006,25690,25693],{"href":25691,"rel":25692},"https://github.com/GoogleChromeLabs/quicklink",[2010],"quicklink",[1143,25695,25696],{},[2243,25697],{"alt":25698,"src":25699},"nuxt-prefetch-comparison","https://user-images.githubusercontent.com/904724/51692960-4158be80-1ffe-11e9-9299-61881d06412e.gif",[1143,25701,25702],{},"Demos are online and we recommend you to try it out to feel the difference:",[1852,25704,25705,25712],{},[1855,25706,25707,25708],{},"No prefetching (v2.3): ",[2006,25709,25710],{"href":25710,"rel":25711},"https://nuxt-no-prefetch.surge.sh",[2010],[1855,25713,25714,25715],{},"With prefetching (v2.4): ",[2006,25716,25717],{"href":25717,"rel":25718},"https://nuxt-prefetch.surge.sh",[2010],[1143,25720,25721,25722,25728],{},"You can learn more about this feature in the ",[2006,25723,25726],{"href":25724,"rel":25725},"https://v2.nuxt.com/docs/features/nuxt-components#the-nuxtlink-component",[2010],[1220,25727,25683],{}," section of the documentation.",{"title":1218,"searchDepth":1233,"depth":1233,"links":25730},[25731],{"id":25670,"depth":1233,"text":25671},"2019-01-28","Starting from Nuxt v2.4.0, Nuxt will automagically prefetch the code-splitted pages linked with a nuxt-link when visible in the viewport by default.","/assets/blog/introducing-smart-prefetching.png",{},{"title":1092,"description":25733},"Y1x1PfQmXc",1742651336887]