--- navigation.icon: IconDirectory title: "components" description: "The components/ directory is where you put all your Vue components." head.title: "components/" --- # Components Directory The [`components/` directory](/docs/guide/directory-structure/components) is where you put all your Vue components which can then be imported inside your pages or other components ([learn more](https://vuejs.org/guide/essentials/component-basics.html#components-basics)). Nuxt automatically imports any components in your [`components/` directory](/docs/guide/directory-structure/components) (along with components that are registered by any modules you may be using). ```bash | components/ --| TheHeader.vue --| TheFooter.vue ``` ```html [layouts/default.vue] ``` ## Custom directories By default, only the `~/components` directory is scanned. If you want to add other directories, or change how the components are scanned within a subfolder of this directory, you can add additional directories to the configuration: ```ts [nuxt.config.ts] export default defineNuxtConfig({ components: [ // ~/calendar-module/components/event/Update.vue => { path: '~/calendar-module/components' }, // ~/user-module/components/account/UserDeleteDialog.vue => { path: '~/user-module/components', pathPrefix: false }, // ~/components/special-components/Btn.vue => { path: '~/components/special-components', prefix: 'Special' }, // It's important that this comes last if you have overrides you wish to apply // to sub-directories of `~/components`. // // ~/components/Btn.vue => // ~/components/base/Btn.vue => '~/components' ] }) ``` ::alert Any nested directories need to be added first as they are scanned in order. :: ## Component extensions By default, any file with an extension specified in the [extensions key of `nuxt.config.ts`](/docs/api/configuration/nuxt-config#extensions) is treated as a component. If you need to restrict the file extensions that should be registered as components, you can use the extended form of the components directory declaration and its `extensions` key: ```diff export default defineNuxtConfig({ components: [ { path: '~/components', + extensions: ['.vue'], } ] }) ``` ## Component Names If you have a component in nested directories such as: ```bash | components/ --| base/ ----| foo/ ------| Button.vue ``` ... then the component's name will be based on its own path directory and filename, with duplicate segments being removed. Therefore, the component's name will be: ```html ``` ::alert For clarity, we recommend that the component's filename matches its name. (So, in the example above, you could rename `Button.vue` to be `BaseFooButton.vue`.) :: If you want to auto-import components based only on its name, not path, then you need to set `pathPrefix` option to `false` using extended form of the configuration object: ```diff export default defineNuxtConfig({ components: [ { path: '~/components', + pathPrefix: false, }, ], }); ``` This registers the components using the same strategy as used in Nuxt 2. For example, `~/components/Some/MyComponent.vue` will be usable as `` and not ``. ## Dynamic Components If you want to use the Vue `` syntax, you need to use the `resolveComponent` helper provided by Vue or import the component directly from `#components` and pass it into `is` prop. For example: ```vue ``` ::alert{type=warning} If you are using `resolveComponent` to handle dynamic components, make sure not to insert anything but the name of the component, which must be a string and not a variable. :: Alternatively, though not recommended, you can register all your components globally, which will create async chunks for all your components and make them available throughout your application. ```diff export default defineNuxtConfig({ components: { + global: true, + dirs: ['~/components'] }, }) ``` You can also selectively register some components globally by placing them in a `~/components/global` directory. ::alert{type=info} The `global` option can also be set per component directory. :: ## Dynamic Imports To dynamically import a component (also known as lazy-loading a component) all you need to do is add the `Lazy` prefix to the component's name. ```html [layouts/default.vue] ``` This is particularly useful if the component is not always needed. By using the `Lazy` prefix you can delay loading the component code until the right moment, which can be helpful for optimizing your JavaScript bundle size. ```html [pages/index.vue] ``` ## Direct Imports You can also explicitly import components from `#components` if you want or need to bypass Nuxt's auto-importing functionality. ```html [pages/index.vue] ``` ## `` Component Nuxt provides the `` component for purposely rendering a component only on client side. To import a component only on the client, register the component in a client-side only plugin. ```html [pages/example.vue] ``` Use a slot as fallback until `` is mounted on client side. ```html [pages/example.vue] ``` ## .client Components If a component is meant to be rendered only client-side, you can add the `.client` suffix to your component. ```bash | components/ --| Comments.client.vue ``` ```html [pages/example.vue] ``` ::alert{type=warning} This feature only works with Nuxt auto-imports and `#components` imports. Explicitly importing these components from their real paths does not convert them into client-only components. :: ::alert{type=warning} `.client` components are rendered only after being mounted. To access the rendered template using `onMounted()`, add `await nextTick()` in the callback of the `onMounted()` hook. :: ## .server Components `.server` components can either be used on their own or paired with a `.client` component. ### Standalone server components Standalone server components will always be rendered on the server. When their props update, this will result in a network request that will update the rendered HTML in-place. :video-player{src="https://www.youtube.com/watch?v=u1yyXe86xJM"} > A video made by [LearnVue](https://go.learnvue.co) for the Nuxt documentation. Server components are currently experimental and in order to use them, you need to enable the 'component islands' feature in your nuxt.config: ```ts [nuxt.config.ts] export default defineNuxtConfig({ experimental: { componentIslands: true } }) ``` Now you can register server-only components with the `.server` suffix and use them anywhere in your application automatically. ```bash | components/ --| HighlightedMarkdown.server.vue ``` ```html [pages/example.vue] ``` Server-only components use `` under the hood, meaning that `lazy` prop and `#fallback` slot are both passed down to ``. #### server components and context When rendering a server-only or island component, `` makes a HTTP request to GET a `NuxtIslandResponse`. This means: - You can't access to the island context from your SSR app and you can't access to your SSR app context from the island component. Both are different context. - A new Vue app will be created server-side to create the `NuxtIslandResponse`. - Plugins will be ran for the island Vue app except those marked with `env.island: false` on an object plugin. You can access to an island context during the island component rendering through `nuxtApp.ssrContext.islandContext`. ::alert{type=info} Slots can be interactive and are wrapped within a `
` with `display: contents;` :: ### Paired with a `.client` component In this case, the `.server` + `.client` components are two 'halves' of a component and can be used in advanced use cases for separate implementations of a component on server and client side. ```bash | components/ --| Comments.client.vue --| Comments.server.vue ``` ```html [pages/example.vue] ``` ::alert{type=warning} It is essential that the client half of the component can 'hydrate' the server-rendered HTML. That is, it should render the same HTML on initial load, or you will experience a hydration mismatch. :: ## `` Component Nuxt provides the `` component to render a component only during development. The content will not be included in production builds and tree-shaken. ```html [pages/example.vue] ``` ## `` Component Nuxt provides the `` component to render its content on the client if any of its children trigger an error in SSR. You can specify a `fallbackTag` to make it render a specific tag if it fails to render on the server. ```html [pages/example.vue] ``` ## Library Authors Making Vue component libraries with automatic tree-shaking and component registration is super easy ✨ You can use the `components:dirs` hook to extend the directory list without requiring user configuration in your Nuxt module. Imagine a directory structure like this: ```bash | node_modules/ ---| awesome-ui/ ------| components/ ---------| Alert.vue ---------| Button.vue ------| nuxt.js | pages/ ---| index.vue | nuxt.config.js ``` Then in `awesome-ui/nuxt.js` you can use the `components:dirs` hook: ```ts import { defineNuxtModule, createResolver } from '@nuxt/kit' export default defineNuxtModule({ hooks: { 'components:dirs': (dirs) => { const { resolve } = createResolver(import.meta.url) // Add ./components dir to the list dirs.push({ path: fileURLToPath(resolve('./components')), prefix: 'awesome' }) } } }) ``` That's it! Now in your project, you can import your UI library as a Nuxt module in your `nuxt.config` file: ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['awesome-ui/nuxt'] }) ``` ... and directly use the module components (prefixed with `awesome-`) in our `pages/index.vue`: ```vue ``` It will automatically import the components only if used and also support HMR when updating your components in `node_modules/awesome-ui/components/`. :LinkExample{link="/docs/examples/features/auto-imports"}