Auto-Imports Explained
Why ref, useFetch, and your own components and composables all work in Nuxt with no import statement.
2 phút đọc
If you've followed along so far, you've already noticed something odd: none of the examples import ref, useFetch, or NuxtLink from anywhere. In a plain Vue file, ref comes from import { ref } from "vue". In Nuxt, it's just there. This isn't magic — it's a build-time step that Nuxt performs on every file in your project.
What Nuxt scans, and what it generates
At build time (and continuously while nuxt dev runs), Nuxt scans a fixed set of directories and auto-generates the imports for anything it finds:
- Vue's own APIs (
ref,computed,watch,onMounted, …) - Nuxt's own composables (
useFetch,useRoute,useState,navigateTo, …) - Every component in
components/ - Every composable in
composables/ - Every utility function in
utils/
<script setup>
// no imports — all three of these are auto-imported
const count = ref(0);
const doubled = computed(() => count.value * 2);
const route = useRoute();
</script>
<template>
<BaseButton @click="count++">Count: {{ count }} (doubled: {{ doubled }})</BaseButton>
</template>BaseButton here resolves to components/BaseButton.vue purely by filename — nothing registers it, nothing imports it.
Naming from nested folders
A component in a subfolder gets its folder name prefixed, so the file path stays predictable even though there's no explicit import to look at:
components/
└─ base/
└─ Button.vue → <BaseButton />
└─ forms/
└─ Input.vue → <FormsInput />
The same applies to composables — composables/useCart.ts exporting useCart is available as useCart() anywhere, no import line required.
Why this is a deliberate trade-off, not just convenience
The obvious cost is that a file no longer tells you where a function came from just by reading its top few lines — you have to know the convention to know that useFetch is Nuxt's, not a local file. Editor tooling (the official Nuxt VS Code extension, or any editor with the Vue language server) covers this in practice: "go to definition" on an auto-imported symbol still jumps to the real source. In exchange, Nuxt avoids a common source of import churn — renaming or moving a component would otherwise mean updating every file that imports it.
Opting out when you need to
Auto-imports aren't mandatory — an explicit import always works and simply shadows the auto-import:
<script setup>
import { ref as vueRef } from "vue";
</script>This is rarely necessary, but knowing it's just a normal ES import under the hood — not a special Nuxt-only construct — makes auto-imports far less mysterious once you've seen it once.