Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке plugins в Nuxt?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Nuxt plugins** (плагіни Nuxt) - це файли в директорії `plugins/`, які виконуються один раз при старті застосунку, реєструючи Vue-плагіни або ін'єктуючи глобальні хелпери. `vueApp.use()` для Vue-інтеграцій, `return { provide: { ... } }` для доступу через `useNuxtApp()`. Суфікс `.client.ts` або `.server.ts` визначає середовище виконання. ```javascript export default defineNuxtPlugin((nuxtApp) => { nuxtApp.vueApp.use(SomePlugin) return { provide: { helper: myHelper } } }) ``` **Головне:** плагіни виконуються один раз при старті, composables - на кожен компонент.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Nuxt plugins** (плагіни Nuxt) - це файли в директорії `plugins/`, які виконуються один раз під час ініціалізації застосунку, реєструючи Vue-плагіни, утиліти або глобальні хелпери до того, як монтується будь-який компонент. ## Теорія ### TL;DR - Уяви плагіни як наземну команду аеропорту: вони готують сервіси (auth, повідомлення, API-клієнти) до старту застосунку, щоб кожна сторінка мала до них доступ - Плагіни виконуються один раз при старті; composables - на кожен компонент; middleware - на кожен роут - Потрібна Vue-інтеграція (`vueApp.use()`) або глобальний inject (`provide`) - потрібен плагін - Суфікс `.client.ts` для браузерного коду, `.server.ts` для SSR - Nuxt сортує плагіни за алфавітом; числові префікси (`01.auth.ts`) контролюють порядок ### Швидкий приклад ```javascript // plugins/toast.client.ts - виконується лише в браузері import Toast from 'vue-toastification' export default defineNuxtPlugin((nuxtApp) => { nuxtApp.vueApp.use(Toast, { timeout: 3000 }) // Toast зареєстровано глобально у Vue-застосунку }) // У будь-якому компоненті чи сторінці: const { $toast } = useNuxtApp() $toast.success('Збережено!') ``` Один раз зареєстрував - доступно всюди. Жодних окремих імпортів у компонентах. ### Головна відмінність Плагіни виконуються під час фази старту Nuxt, до гідратації. Vue-застосунок отримує плагін ще до побудови дерева компонентів. Composables, навпаки, запускаються за потребою всередині `setup` компонентів. Покладеш логіку компонента в плагін і отримаєш зайве навантаження при кожному завантаженні сторінки. ### Коли використовувати - Інтеграція Vue-плагіна (`vue-toastification`, `pinia`, `i18n`) -> плагін з `vueApp.use()` - Глобальний API-клієнт доступний скрізь -> плагін з `provide: { api }` - Перевикористовувана логіка без Vue-інтеграції -> composable - Логіка, специфічна для роуту -> middleware - Браузерний код (аналітика, localStorage) -> `plugin.client.ts` - Серверний код (підключення до БД) -> `plugin.server.ts` ### Як Nuxt завантажує плагіни Nuxt сканує директорію `plugins/` під час збірки й автоматично реєструє кожен файл. При старті плагіни виконуються послідовно в алфавітному порядку. Клієнтські плагіни запускаються після гідратації, серверні виконуються на кожен запит у движку Nitro. Об'єкт `provide` з кожного плагіна автоматично об'єднується в контекст `useNuxtApp()` через `app.provide()`. Саме тому `$toast` або `$api` з'являється в `useNuxtApp()` без жодного явного імпорту в компоненті. Nuxt 3.10+ також підтримує `parallel: true` всередині `defineNuxtPlugin` для плагінів без взаємних залежностей. Це помітно скорочує час старту у великих застосунках. ### Типові помилки **1. Немає суфікса `.client.ts` для браузерного коду** ```javascript // Неправильно: plugins/analytics.ts // Виконується і на SSR, і на клієнті = подвійне відстеження, помилки з window // Правильно: plugins/analytics.client.ts export default defineNuxtPlugin(() => { window.analytics.init() // window тут безпечний }) ``` **2. Неправильний порядок плагінів при залежностях** ```javascript // Неправильно: plugins/api.ts завантажується до plugins/auth.ts // api.ts намагається прочитати auth-токен, якого ще немає // Правильно: перейменуй на 01.auth.ts та 02.api.ts // Nuxt сортує за алфавітом, числа мають пріоритет ``` Це найпоширеніша прихована помилка, яку я бачу в Nuxt-репозиторіях: auth та API завантажуються не в тому порядку, бо ніхто не додав числові префікси, поки щось не зламалось у продакшені. **3. Забутий `return { provide }`** ```javascript // Неправильно: export default defineNuxtPlugin(() => { const api = { getUser: (id) => $fetch(`/api/users/${id}`) } // api визначено, але нікуди не передається }) // Правильно: export default defineNuxtPlugin(() => { const api = { getUser: (id) => $fetch(`/api/users/${id}`) } return { provide: { api } } }) // Тепер: const { $api } = useNuxtApp() працює в будь-якому компоненті ``` **4. Отримання даних безпосередньо в ініціалізації плагіна** Уникай fetch-запитів у коді налаштування плагіна. Вони виконуються поза lifecycle компонентів, тому `useAsyncData` та `useFetch` там недоступні. Перенеси отримання даних у composables, де є доступ до правильного контексту запиту. ### Де зустрічається - `vue-toastification` -> глобальні повідомлення в e-commerce застосунках - `Pinia` -> налаштування сховищ у SaaS-дашбордах (типово в nuxtjs/starter) - `Supabase` -> auth-клієнт доступний скрізь у CMS і контент-сайтах - `Day.js` -> глобальне форматування дат у блог-платформах - `Sentry` -> відстеження помилок, ініціалізоване один раз для всього застосунку ### Питання на співбесіді **Q:** Як Nuxt визначає порядок виконання плагінів? **A:** За алфавітом, за назвою файлу. Числові префікси контролюють порядок: `01.auth.ts` виконається до `02.api.ts`. **Q:** У чому різниця між `provide` і `vueApp.use()`? **A:** `vueApp.use()` реєструє Vue-плагін (директиви, компоненти, глобальна логіка install). `provide` ін'єктує значення в контекст Nuxt, доступне через `useNuxtApp()`. В одному плагіні часто використовують обидва. **Q:** Чи може плагін бути асинхронним? **A:** Так. Передай `async (nuxtApp) => { ... }` у `defineNuxtPlugin`. Nuxt чекає на асинхронні плагіни перед рендерингом, тому тримай їх швидкими, інакше кожен запит буде чекати. **Q:** Як плагіни впливають на гідратацію SSR? **A:** Використовуй `.client.ts` для плагінів, які звертаються до браузерних API. Для спільного стану між сервером і клієнтом використовуй `useState()` всередині плагіна, а не звичайну змінну. **Q:** Що таке `parallel: true` і коли це використовувати? **A:** Додано в Nuxt 3.10. Дозволяє плагіну запускатися паралельно з іншими, без очікування. Використовуй для плагінів без залежностей між ними. Помітно скорочує час старту у великих застосунках. ## Приклади ### Реєстрація Vue-плагіна ```javascript // plugins/toast.client.ts import Toast from 'vue-toastification' export default defineNuxtPlugin((nuxtApp) => { nuxtApp.vueApp.use(Toast, { timeout: 3000 }) }) // pages/index.vue const { $toast } = useNuxtApp() async function saveUser(data) { await $fetch('/api/user', { method: 'POST', body: data }) $toast.success('Збережено!') } ``` Один імпорт, одна реєстрація, доступно на кожній сторінці та в кожному компоненті. Покриває більшість сценаріїв використання плагінів. ### Глобальний API-клієнт через provide ```javascript // plugins/supabase.ts import { createClient } from '@supabase/supabase-js' export default defineNuxtPlugin(() => { const config = useRuntimeConfig() const client = createClient( config.public.supabaseUrl, config.public.supabaseKey ) return { provide: { supabase: client } } }) // components/Login.vue const { $supabase } = useNuxtApp() async function login(email, password) { const { data, error } = await $supabase.auth.signInWithPassword({ email, password }) if (error) console.error(error.message) } ``` Supabase-клієнт ініціалізується один раз, повторно використовує пул з'єднань і доступний скрізь без повторного імпорту. Типовий підхід у CMS-стартерах на базі Nuxt.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.