shared

Директория shared/ предназначена для общего кода между Vue-приложением и сервером Nitro.

Директория shared/ позволяет использовать один и тот же код и во Vue-приложении, и на сервере Nitro.

Директория shared/ доступна в Nuxt v3.14+.
Код в shared/ не может импортировать код Vue или Nitro.

Почему нельзя смешивать код Vue и Nitro

Nuxt собирает два отдельных бандла: Vue-приложение (клиент и SSR) и Nitro-сервер (API routes, server middleware, server plugins). Они бандлятся независимо и работают в разных контекстах. Код в shared/ используется в обоих бандлах, поэтому не может импортировать ни из одного из них.

Код Vue-приложения в Nitro

Компонентам и composables нужен runtime Vue-приложения и часто контекст Nuxt (например useNuxtApp() или useRoute()), ни того, ни другого в Nitro нет. Импорт в server code может вызвать ошибки сборки или рантайма и подтянуть зависимости Vue-приложения в server bundle.

Код Nitro во Vue-приложении

Server-only код (Node API, утилиты Nitro, server route handlers) не должен выполняться в браузере. Импорт в app может сломать клиентскую сборку, вызвать ошибки в браузере или утянуть server logic в client bundle.

Type-only импорты

import type стирается при компиляции и не подтягивает runtime в другой бандл, поэтому импорт только типов через границу может казаться рабочим. Тем не менее общие типы (например типы ответов API) лучше держать в shared/types/, где они автоимпортируются в обоих контекстах. Это сохраняет границу, не даёт случайно превратить type import в value import и соответствует отдельным type contexts Nuxt для app, server и shared.

Использование

Способ 1: именованный экспорт

shared/utils/capitalize.ts
export const capitalize = (input: string) => {
  return input[0] ? input[0].toUpperCase() + input.slice(1) : ''
}

Способ 2: экспорт по умолчанию

shared/utils/capitalize.ts
export default function (input: string) {
  return input[0] ? input[0].toUpperCase() + input.slice(1) : ''
}

Утилиты из shared/ автоимпортируются в приложении Nuxt и в директории server/.

app/app.vue
<script setup lang="ts">
const hello = capitalize('hello')
</script>

<template>
  <div>
    {{ hello }}
  </div>
</template>
server/api/hello.get.ts
export default defineEventHandler((event) => {
  return {
    hello: capitalize('hello'),
  }
})

Как сканируются файлы

Автоимпортируются только файлы из shared/utils/ и shared/types/. Файлы во вложенных поддиректориях не автоимпортируются, если не добавить эти директории в imports.dirs и nitro.imports.dirs.

Принцип автоимпорта и сканирования для shared/utils и shared/types такой же, как для app/composables/ и app/utils/.
Узнать больше Docs > 4 X > Directory Structure > App > Composables#how Files Are Scanned.
Directory Structure
-| shared/
---| capitalize.ts        # Не автоимпортируется
---| formatters
-----| lower.ts           # Не автоимпортируется
---| utils/
-----| lower.ts           # Автоимпортируется
-----| formatters
-------| upper.ts         # Не автоимпортируется
---| types/
-----| bar.ts             # Автоимпортируется

Остальные файлы в shared/ нужно импортировать вручную через алиас #shared (настраивается Nuxt):

// Файлы прямо в shared
import capitalize from '#shared/capitalize'

// Файлы во вложенных директориях
import lower from '#shared/formatters/lower'

// Файлы в папке внутри utils
import upper from '#shared/utils/formatters/upper'

Так импорты остаются единообразными в любом месте приложения.

Узнать больше Docs > 4 X > Guide > Concepts > Auto Imports.