IHOR.DEVБАЗА_ЗНАНЬ
МЕНЮ

~/blog / Вебстек / a-maintainable-next-js-app-router-project-structure.md

// основний посібник · 3 хв читання

Зручна для підтримки структура проєкту Next.js App Router

Організуйте маршрути App Router, модулі функцій, серверні дані й спільний UI так, щоб розробник міг простежити запит без лабіринту папок.

Коротка відповідь

Залиште app композицію URL і правила фреймворку, локальний UI — біля маршруту, повторну бізнес-поведінку — в модулях функцій. Явно відокремте серверні дані від браузера. Зручна структура дає простежити URL, дозволені дані й результат, а не лише розкласти все в components, hooks, services і utils.

Практичні кроки реалізації

1. Пояснюйте маршрут файлами фреймворку

page.tsx є точкою сторінки, layout.tsx — спільним UI, loading.tsx — fallback сегмента, error.tsx — межею помилки. Звичайні файли не створюють маршрут без page чи route. Папки з підкресленням виключаються з маршрутизації, групи в дужках не додають назву до URL.

2. Виносьте стабільну доменну відповідальність

Для умовного бронювання відокремте публічне читання доступності, дозволений запис і компоненти відображення. Називайте exports за операціями, а не загальним service-об’єктом. Виносьте з маршруту за реальної повторної потреби. Загальний helpers приховує власність; модуль має зрозумілу причину зміни й виклик.

3. Зробіть середовище явним

Назва .server.ts показує намір; import server-only зупиняє клієнтський імпорт під час збірки. Усередині залишаються ключі й клієнт бази. Client Components отримують невеликі публічні поля. Спільні типи виносьте за потреби. Не змішуйте серверні адаптери й браузерні компоненти в одному barrel.

4. Не перевантажуйте layout

Кореневий layout задає документ і спільну оболонку. Providers функції розміщуйте біля потрібних маршрутів. Перевірка в layout не замінює авторизацію читання чи прямого серверного виклику. Фіксуйте залежності між функціями, щоб перенесення не створило циклу.

Приклад реалізації

Невеликий серверний модуль використовує умовний локальний контент. У застосунку публічні поля формують після дозволеного чи явно публічного читання. Модуль доступний сторінці, але не графу імпортів Client Component. Next.js обробляє server-only і перевіряє межу при збірці.

// src/features/articles/read-public-article.server.ts
import "server-only";

type PublicArticle = { slug: string; title: string };
const published: PublicArticle[] = [
  { slug: "structure", title: "Project structure" },
];

export async function readPublicArticle(slug: string) {
  const article = published.find((entry) => entry.slug === slug);
  return article ? { slug: article.slug, title: article.title } : null;
}

Портфоліо вже розділяє src/app, src/lib для контенту й перекладів, src/components і src/content/blog. Це спостережувані обов’язки, не універсальні назви. Нова функція має спочатку вписатися в межі, а не запускати перебудову всього репозиторію.

Компроміси та альтернативи

Colocation спрощує навігацію, модулі функцій узгоджують спільні правила. Невеликий сайт може бути пласким, великий продукт — доменним. Окремі пакети потребують незалежних користувачів чи перевірок. Спочатку забезпечте напрям імпортів, потім додавайте папки.

Поширені помилки

Поширені збої: кореневий use client, utils із секретами й форматуванням, авторизація лише в page. Групи маршрутів змінюють організацію, не політику доступу. Перенесення файлів без оновлення імпортів, метаданих і динамічних маршрутів має runtime-наслідки.

Перевірка перед випуском

  • URL простежується до даних і результату.
  • Серверні адаптери мають server-only і публічні поля.
  • Клієнтські імпорти не містять привілейованих залежностей.
  • Providers і межі помилок розташовані біля маршрутів.
  • Групи не створюють однакових URL.
  • Напрям імпортів визначено.

Поширені запитання

Чи треба виносити всі файли з app?

Ні. Next.js підтримує colocation. Переносьте заради власності чи повторного використання, не через хибне припущення, що звичайні файли app стають маршрутами.

Чи папка server захищає функцію?

Ні. Маркери середовища контролюють імпорти, авторизація — доступ. Потрібні обидва; папки й типи не перевіряють викликачів.

Наступний крок

Простежте маршрут і позначте URL, бізнес-правила, зовнішні дані й браузер. Перенесіть лише неоднозначні обов’язки. Структура має спростити наступну зміну без нової системи папок для кожної функції.

Первинні джерела

Пов’язані матеріали та приклади

Ігор Харчишин

Незалежний full-stack інженер продуктів, який пише посібники з реалізації розширень браузера та сучасних вебпродуктів на основі першоджерел.

Потрібно реалізувати це у вашому продукті?

Перегляньте відповідні приклади продуктів або поділіться контекстом розробки вебзастосунку, розширення Chrome, API чи SaaS.