Skip to content

Nuxt Components — Auto-Importing and Reusable Vue Components

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about Nuxt Components. We cover key concepts, practical examples, and best practices to help you master this topic.

Learn Nuxt 3 component system: auto-imports, component naming conventions, and building reusable UI components without manual registration.

In this lesson, you'll understand how Nuxt 3 auto-imports components, naming conventions, and component organization.

What You'll Learn

How Nuxt auto-imports components, naming conventions for multi-word components, component directories, and Lazy Loading.

Why It Matters

Auto-imports eliminate repetitive import statements. Components are available everywhere without manual registration, speeding up development.

flowchart LR
    A[components/] --> B[Auto-imported]
    A --> C[Available Globally]
    B --> D[NuxtAppHeader]
    B --> E[BlogPostCard]
    B --> F[BaseButton]
    C --> G[Any Page or Component]
    style A fill:#00dc82,color:#fff

Basic Component

Create components/AppHeader.vue:

<template>
  <header>
    <NuxtLink to="/">Home</NuxtLink>
    <slot />
  </header>
</template>

Use it anywhere without import:

<!-- pages/index.vue -->
<template>
  <div>
    <AppHeader />
    <h1>Home Page</h1>
  </div>
</template>

Output: The component renders automatically. No import statement needed.

Nested Components

Organize components in subdirectories:

components/
├── base/
│   ├── BaseButton.vue
│   ├── BaseInput.vue
│   └── BaseCard.vue
├── blog/
│   ├── BlogPostCard.vue
│   └── BlogSidebar.vue
└── AppHeader.vue

Usage with directory prefix:

<template>
  <div>
    <BaseButton variant="primary">Click</BaseButton>
    <BlogPostCard :post="post" />
  </div>
</template>

Output: Nuxt prefixes component names with directory names. components/base/BaseButton.vue becomes <BaseButton>.

Lazy Loading

Lazy-load non-critical components:

<template>
  <div>
    <h1>Dashboard</h1>
    
    <!-- This component loads only when visible -->
    <LazyDashboardChart />
    
    <!-- Conditional lazy loading -->
    <LazyAdminPanel v-if="user.isAdmin" />
  </div>
</template>

Output: Components prefixed with Lazy are loaded asynchronously, reducing initial bundle size.

Dynamic Components

Render components dynamically:

<script setup>
const { data: sections } = await useFetch('/api/sections');
</script>

<template>
  <div>
    <component 
      v-for="section in sections"
      :is="section.component" 
      :key="section.id"
      v-bind="section.props" 
    />
  </div>
</template>

Component Props and Emits

<!-- components/UserCard.vue -->
<script setup>
const props = defineProps({
  user: { type: Object, required: true },
  variant: { type: String, default: 'default' }
});

const emit = defineEmits(['select', 'delete']);

const handleSelect = () => emit('select', props.user.id);
</script>

<template>
  <div class="card" :class="variant" @click="handleSelect">
    <img :src="user.avatar" :alt="user.name" />
    <h3>{{ user.name }}</h3>
    <p>{{ user.email }}</p>
    <button @click="$emit('delete', user.id)">Delete</button>
  </div>
</template>

Common Mistakes

  1. Using single-word component names: Components like Button.vue might conflict with HTML elements. Use multi-word names: BaseButton.vue.
  2. Not using directory prefixes correctly: components/ui/Button.vue becomes <UiButton>, not <Button>.
  3. Forgetting Lazy prefix for Code Splitting: Without Lazy, components are eagerly loaded in the main bundle.
  4. Over-nesting directories: Deep directory trees create long component names. Limit to 2-3 levels.
  5. Not using <script setup>: Nuxt 3 and Vue 3 favor <script setup> for Composition API. Options API works but is less idiomatic.

Practice Questions

  1. How are components in Nuxt 3 auto-imported? Answer: Any .vue file in components/ is automatically available globally. No manual import or registration needed.

  2. How do you lazy-load a component? Answer: Prefix the component name with Lazy: <LazyComponentName />. It loads asynchronously when needed.

  3. How are components in subdirectories referenced? Answer: Using directory names as prefix: components/blog/PostCard.vue becomes <BlogPostCard>.

  4. What is the purpose of <script setup>? Answer: It's a compile-time syntax that reduces boilerplate for Composition API. Props, emits, and reactive data are declared concisely.

Challenge

Create a component library with: BaseButton, BaseInput, BaseCard, BaseModal, and BaseBadge. Use subdirectories for organization. Lazy-load the modal component.

Mini Project

Build a reusable UI kit with 10+ components organized in subdirectories (base, layout, form, data-display). Use auto-imports, lazy loading for heavy components, and demonstrate dynamic component rendering.

FAQ

Can I disable auto-imports for specific components?

: Yes. Configure components: { dirs: [{ path: '~/components/form', prefix: 'Form' }] } in nuxt.config.ts.

Do auto-imported components affect performance?

: No. Nuxt tree-shakes unused components. Only components actually used in templates are included in the bundle.

Can I use components from `node_modules`?

: Yes. Register them in nuxt.config.ts under the components option with the library's path.

How do I override a component from a module?

: Create a component with the same name in your components/ directory. Your local version takes precedence.

What's Next

Learn about Nuxt Composables to understand auto-imported composables and state management in Nuxt 3.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro