Suggest an editImprove this articleRefine the answer for “How do auto-imports work in Nuxt?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Auto-imports in Nuxt** scan directories like `~/composables` and `~/components` at build time, then inject their exports into every `.vue` file via a virtual `#imports` module. ```ts const { data } = await useFetch('/api/users') // no import needed const route = useRoute() // also auto-imported ``` **Key point:** scanning happens once at build; runtime is plain JS modules with no extra overhead.Shown above the full answer for quick recall.Answer (EN)Image**Auto-imports in Nuxt** - a build-time feature that makes composables, components, and utilities available in every file of your app without writing a single `import` statement. ## Theory ### TL;DR - Nuxt scans `~/composables`, `~/components`, `~/utils` at build time and injects their exports into every `.vue` file - Think hotel kitchen: tools sit in shared drawers, chefs grab what they need without asking - No `import` boilerplate; the Vite plugin handles injection via a virtual `#imports` module - To opt out: set `autoImports: false` in `nuxt.config.ts` ### Quick example ```vue <!-- pages/users.vue - zero import lines needed --> <script setup> // useFetch and useRoute come from the auto-generated #imports module const { data: users } = await useFetch('/api/users') const route = useRoute() </script> <template> <!-- ~/components/UserList.vue is picked up automatically --> <UserList v-for="user in users" :key="user.id" :user="user" /> </template> ``` `useFetch`, `useRoute`, and `UserList` are all injected without a single import line. Nuxt resolves them at build time, not at runtime. ### How it works internally Nuxt's Vite plugin scans your directories at build time and generates a virtual `#imports` module. That module exports everything it found: composables, utility functions, components. Every `.vue` file in the project gets this module injected into its scope automatically. At runtime, this is just standard JS modules. No overhead, no magic. The scanning and injection happen once during the build, and the result is identical to writing the imports yourself. Default scan targets: `~/composables`, `~/components`, `~/utils`, `~/plugins`, and `~/server/composables` (added in Nuxt 3.8+). You can extend the list via `imports.dirs` in `nuxt.config.ts`. ### Client vs server auto-imports Client composables go in `~/composables/`. Server composables go in `~/server/composables/`. The `.client.ts` and `.server.ts` file suffixes tell Nuxt which build to include a file in. Put a client composable inside a server API route and Nuxt throws "not defined". The server build never scanned `~/composables/`. This is the most common source of auto-import bugs I've seen in Nuxt projects. Moving the file to `~/server/composables/` fixes it. ### When to use - Adding a new page or composable: create the file, it works everywhere immediately - Shared logic across components: drop it in `~/composables/`, done - Large monorepo or strict bundle control: disable with `autoImports: false`, add manual imports ### Common mistakes **Client composable in a server route:** ```ts // server/api/orders.get.ts - WRONG // ~/composables/ is not scanned during the server build const data = useMyClientUtil() // throws: not defined // CORRECT - move to ~/server/composables/useMyServerUtil.ts ``` **Naming your composable the same as a Nuxt built-in:** ```ts // ~/composables/useRoute.ts // This shadows Nuxt's useRoute and breaks routing app-wide // Rename to useAppRoute or usePageRoute ``` **Using auto-imports inside `defineNuxtPlugin`:** ```ts // Plugins run before auto-import scan completes export default defineNuxtPlugin(() => { const util = useMyUtil() // undefined - scan has not happened yet // Fix: inject via provide instead return { provide: { myUtil: () => 'works' } } }) ``` ### Real-world usage - Nuxt Content: `queryContent('/')` auto-imported for MDX blog pages (nuxt/content v2.6+) - Nuxt UI: `<UButton />` from `~/components/Ui` available everywhere (nuxt/ui v2.8) - Supabase Nuxt: `useSupabaseClient()` and `useSupabaseUser()` for auth flows - Vitest + Nuxt: test setup auto-mocks the `#imports` module ### Follow-up questions **Q:** What directories does Nuxt scan by default? **A:** `~/composables`, `~/components`, `~/utils`, `~/plugins`, and `~/server/composables`. Add custom paths via `imports.dirs` in `nuxt.config.ts`. **Q:** How do you add a custom directory to auto-imports? **A:** Set `imports: { dirs: ['~/logic'] }` in `nuxt.config.ts`. Every exported function from that folder becomes auto-imported across the app. **Q:** How do client and server auto-imports differ? **A:** Client composables live in `~/composables/`, server ones in `~/server/composables/`. The `.client.ts` or `.server.ts` suffix restricts a file to one build target only. **Q:** Does disabling auto-imports improve bundle size? **A:** Auto-imported code is already tree-shaken, so unused composables do not end up in the bundle. You would disable auto-imports for explicit dependency graphs in a large monorepo, not for bundle size. **Q:** How does this differ from Vue's `globalProperties`? **A:** Auto-imports are module exports - tree-shakable and TypeScript-inferred. `globalProperties` are runtime objects attached to the app instance with no tree-shaking and much weaker type support. ## Examples ### Basic: composable and component on a page ```vue <!-- pages/dashboard.vue --> <script setup> const route = useRoute() // auto-imported const { data: orders } = await useFetch('/api/orders', { params: { userId: route.params.id } }) </script> <template> <!-- ~/components/OrderTable.vue - auto-imported --> <OrderTable :orders="orders" /> </template> ``` `useFetch`, `useRoute`, and `OrderTable` are all resolved by Nuxt at build time. Rename the component file and the tag name in templates updates automatically. ### Intermediate: server composable vs client composable ```ts // ~/server/composables/useDb.ts - available in server/api/ routes only export const useDb = () => { return { query: (sql: string) => db.execute(sql) } } // server/api/users.get.ts export default defineEventHandler(async () => { const { query } = useDb() // auto-imported from ~/server/composables/ return query('SELECT * FROM users') }) // ~/composables/useUsers.ts - available in pages/ and components/ only export const useUsers = () => { const users = ref([]) const load = async () => { users.value = await $fetch('/api/users') } return { users, load } } ``` The server and client builds each have their own auto-import scope. Mixing them is where "X is not defined" errors come from.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.