Едынаклі источнік правды для маршрутаў у прыемплявах Next.js
Дазвольце дазнаць, як модуль центральных маршрутаў, створаны за дапамой типавання, заменяе розрозненыя шляхі у вигляде стрынгаў у Next.js, за дапамогою функцый-падказчыкаў для дынамічных сегментаў і групавання экспорта маршрутаў.
Большасць проектаў на Next.js пачынаюцца з прымусовага вводу шляхоў безпасцередна ў компоненты Link і вызывы router.push. Гэта шырока для першых калькі сторанак, але калі прыложэнне растае, тыя ж самыя строкі павтараюцца ў навігацыяных панелях, футерах, перенаправленнях і электронных пісьмох, і кожная замена назвы стае задачай пошуку та замены. Проблема паглыбляецца, калі асистэнты для напісання коду на AI генеруюць частку коду, адтолькі як яны рэдка калі дотрымваюцца адной і той жа конвэнціі настойчыва. Перанесенне всіх шляхоў у адны модуль з вводам рашае гэту проблему.
Што паследзіць з інлайн-шляхамі
Ёсць тыповы компонент навігацыі, дзе кожна пунктазначэння ўособлівае ся як строка:
// ❌ Problematic approach
import Link from 'next/link'
import { useRouter } from 'next/router'
export default function Navbar() {
const router = useRouter()
const handleNavigation = () => {
router.push('/dashboard/user/profile')
}
return (
<nav>
<Link href="/about">About</Link>
<Link href="/contact">Contact</Link>
<Link href="/blog">Blog</Link>
<Link href="/dashboard/analytics">Analytics</Link>
<button onClick={handleNavigation}>Profile</button>
</nav>
)
}
Сёньдзе тут нічога не зламана, але чатыры проблемы выявляюцца ў меру росту базы коду та каманды.
Замены назв стаюць складным задачам
Змена /blog на /articles абярае пошук усіх прыкладоў ў компанентах, коде сервера, тэстах і настройках. Якшто ўпусціць адны, застаецца недзейная лінк.
Памылкі напісу застаюцца
Такі шлях як /dashbord — гэта проста строка, таму ні кампайляр, ні інструменты для перагледу коду яе не спраўляюць. Памылка зазвычай выявляецца як код 404, інодзе толькі ў режыме продакшна.
Рэдагар не можа дапамогчы
Пакалі маршруты — гэта неструктураваныя строкі, то немае автодаполнення, немае возможнасці «перайсці да вызначэння», і немае паведамлення, калі маршрут больш не існуе.
Члэны команды раз'яўляюцца
Разныя людзі і разныя запросы для ШІ ў канцэ нарабляюць той самы пункт назначэння адносна разнымі спосабамі: з канцоўкай слэша або без яе, з ручна створаным шаблонам запита і так далей.
Цэнтрызаванне маршрутаў у адным модуле
Рашэнь — это адзін файл настройкаў, які імпортуецца кожным часткам прыёмніка.
Дзе знаходзіцца файл
Папка constants або config, якая знаходзіцца празаўсёды ля app і components, дапамагае лёгка ўсё знайсці:
/src
/app
/components
/constants
└── routes.ts
/lib
Адзначэнне об’екта маршрутаў
Модуль нижэй групавае маршруты па зонам. Статычныя сторанкі — это простыя строкі. Дынамічныя сторанкі — это маленькія функцыі, якія прымоўнаюць зменную сегмент і вяртаюць полны шлях, таму вызываючыя апранткі ніколі не складаюць URL-адрэсы вручную. Канцэнтры API знаходзяцца пад вкладанай ключоўкой API для выкарыстоўвання ў вызовах fetch. Адзначэнне as const дапамагае TypeScript адгадваць точныя літэральныя значэнні і пазначае об’ект як толькі для чытання, што дазволяе точнае автодаполненне і запобегае випадковай перэзначэнню.
// constants/routes.ts
export const ROUTES = {
// Public routes
HOME: '/',
ABOUT: '/about',
CONTACT: '/contact',
PRICING: '/pricing',
// Auth routes
LOGIN: '/auth/login',
REGISTER: '/auth/register',
FORGOT_PASSWORD: '/auth/forgot-password',
// Blog routes
BLOG: '/blog',
BLOG_DETAIL: (slug: string) => `/blog/${slug}`,
BLOG_CATEGORY: (category: string) => `/blog/category/${category}`,
// Dashboard routes
DASHBOARD: '/dashboard',
DASHBOARD_ANALYTICS: '/dashboard/analytics',
DASHBOARD_SETTINGS: '/dashboard/settings',
DASHBOARD_PROFILE: '/dashboard/profile',
// Dynamic user routes
USER_PROFILE: (userId: string) => `/user/${userId}`,
USER_POSTS: (userId: string) => `/user/${userId}/posts`,
// API routes (useful for fetch calls)
API: {
USERS: '/api/users',
POSTS: '/api/posts',
AUTH: '/api/auth',
},
} as const
// Export route groups for better organization
export const AUTH_ROUTES = {
LOGIN: ROUTES.LOGIN,
REGISTER: ROUTES.REGISTER,
FORGOT_PASSWORD: ROUTES.FORGOT_PASSWORD,
} as const
export const DASHBOARD_ROUTES = {
HOME: ROUTES.DASHBOARD,
ANALYTICS: ROUTES.DASHBOARD_ANALYTICS,
SETTINGS: ROUTES.DASHBOARD_SETTINGS,
PROFILE: ROUTES.DASHBOARD_PROFILE,
} as const
Два дадзеных экспорта, AUTH_ROUTES і DASHBOARD_ROUTES, являюцься відбірамі з галоўнага об’екта для коду, якій не патрэбны іншыя роздзелы, напрыклад, для мідлвэра, який захоўвае панель керування. Паколькі ў яных выкарыстоўваецца ROUTES, а не павтарэння страк, за кожным шляхам застаецца толькі адна вялічына.
Аднай з удосконаленняў, якія варта рассмотрзець, ёсць наступная: якщо ідэнтыфікатор або ID можа мець прасловы чы спецыяльныя знакі, яго трэба загорнуць у encodeURIComponent у рамках дапаможнага функцыі, каб кожны корыстувач апошнюючы трымаў безпечны URL.
Іспытанне шляхоў у компонентах
Тепер navbar імпортуе імены заместо страк. Як Link, так і імператыўная навігацыя чытаюць данні з таго ж модуля, таму яны ніколі не можаць суперсечыцца:
// components/Navbar.tsx
import Link from 'next/link'
import { useRouter } from 'next/router'
import { ROUTES, DASHBOARD_ROUTES } from '@/constants/routes'
export default function Navbar() {
const router = useRouter()
const handleProfileNavigation = () => {
router.push(DASHBOARD_ROUTES.PROFILE)
}
return (
<nav className="flex space-x-4">
<Link href={ROUTES.ABOUT} className="hover:text-blue-500">
About
</Link>
<Link href={ROUTES.CONTACT} className="hover:text-blue-500">
Contact
</Link>
<Link href={ROUTES.BLOG} className="hover:text-blue-500">
Blog
</Link>
<Link href={DASHBOARD_ROUTES.ANALYTICS} className="hover:text-blue-500">
Analytics
</Link>
<button
onClick={handleProfileNavigation}
className="rounded bg-blue-500 px-4 py-2 text-white"
>
Profile
</button>
</nav>
)
}
Заўважкі: у гэтым прыкладзе імпортуецца useRouter з next/router, які належыць да Pages Router. У проектах App Router яго трэба імпортуваць з next/navigation унутры кліентскага компонента; модуль routes працюе аднойчы так сама незалежна ад таго, куды ён імпортуецца.
Стварэнне дынамічных лінкаў
Дынамічныя сегменты — гэта там, дзе такі падход даўа максымальны эфект. У прыведзенай нижэй справаке є паўязкі на кожную пастацю і яе катэгорыю за дапамогою функцый-памочнікаў, якія прымаюць даны з пастаці:
// components/BlogList.tsx
import Link from 'next/link'
import { ROUTES } from '@/constants/routes'
interface Post {
slug: string
title: string
category: string
}
interface BlogListProps {
posts: Post[]
}
export default function BlogList({ posts }: BlogListProps) {
return (
<div className="space-y-4">
{posts.map((post) => (
<article key={post.slug} className="rounded border p-4">
<h2 className="text-xl font-bold">
<Link href={ROUTES.BLOG_DETAIL(post.slug)} className="hover:text-blue-500">
{post.title}
</Link>
</h2>
<Link
href={ROUTES.BLOG_CATEGORY(post.category)}
className="text-sm text-gray-500 hover:text-blue-500"
>
Category: {post.category}
</Link>
</article>
))}
</div>
)
}
Якщо структура URL для пастацяў калі-небудзь зменіцца, напрыклад, праз дадаўшы сегмент з годам, достатнья будзе адначасова апдэйтаваць BLOG_DETAIL, і ўсі вызывальнікі будуць яго следаваць. TypeScript таксама пакажа павестку пра будзь-які вызыв, у яком будзе некалькі аргументаў.
Што вы отрымваеце
- Кожны шлях задаецца аднойчы і викорыстоўваецца ў всіх месцах.
Ліміты і альтэрнатывы
Файл з константамі не пераканальвае, чы рэальна сторонка, якая падходзіць, існуе ў каталогу app або pages. Якщо папка перайменовуецца без адкорэгавання модуля, галоўнікі застаюцца несправнымі. Next.js таксама прымае опцыю typed routes, якая генеруе типы з файловай системы; пераканальваецеся ў актуальной даследчыцкай документацыі ўсюго пра ее статус і чы яна падходзіць вашай наладзе. Багато командаў сумяшваюць абодве: генераваныя типы для правільнасці і модуль з константамі для чытабельных назваў і дапаможнікаў.
Калі AI-асистэнты дапамагаюць у стварэнні коду, паведаміце ім у інструкцыях да вашага проекту, каб яны імпортавалі з модуля routes.
Заключанне
Спрыяйце URL-адрэсам даўаць ся як частка API вашага прыемлівальніка, а не як розрозненыя строкі. Типаваны, цэнтрызаваны модуль routes ператварае перайменоўванні на адзіныя змены, выяўляе памылкі ў рэдагувальніку і дае як людям, так і інструментам адзіны зрозумелы месца для пошуку.