Next.js's routing system is based on the file system, providing a simple yet powerful routing management approach. Here are the core concepts of Next.js's routing system:
1. Basic Routing
In the pages directory, each file automatically becomes a route.
shellpages/ index.js → / (Home) about.js → /about blog/ index.js → /blog post.js → /blog/post
2. Dynamic Routes
Use square brackets [] to create dynamic route segments that can match any value.
shellpages/ blog/ [slug].js → /blog/hello-world, /blog/nextjs-tutorial users/ [id]/ profile.js → /users/123/profile
Getting dynamic route parameters:
javascriptexport default function BlogPost({ params }) { // Next.js 13+ App Router return <div>Post: {params.slug}</div>; } // Or use getStaticPaths and getStaticProps (Pages Router) export async function getStaticPaths() { const posts = await getAllPosts(); return { paths: posts.map(post => ({ params: { slug: post.slug } })), fallback: false }; } export async function getStaticProps({ params }) { const post = await getPostBySlug(params.slug); return { props: { post } }; }
3. Catch-all Routes
Use the [...param] syntax to capture multiple levels of paths.
shellpages/ docs/ [...path].js → /docs/a, /docs/a/b, /docs/a/b/c
javascriptexport default function DocsPage({ params }) { // params.path is an array, like ['a', 'b', 'c'] return <div>Path: {params.path.join('/')}</div>; }
4. Optional Catch-all Routes
Use the [[...param]] syntax to create optional catch-all routes that can match even without parameters.
shellpages/ shop/ [[...category]].js → /shop, /shop/clothes, /shop/clothes/men
5. Nested Routes
Next.js supports nested routes, which can be implemented through layout components.
javascript// pages/blog/index.js export default function Blog() { return ( <div> <h1>Blog</h1> <PostList /> </div> ); } // pages/blog/[slug].js export default function BlogPost() { return ( <div> <h1>Blog Post</h1> <PostContent /> </div> ); }
6. Route Navigation
Next.js provides multiple ways to navigate routes:
Using Link Component (Recommended)
javascriptimport Link from 'next/link'; export default function Navigation() { return ( <nav> <Link href="/">Home</Link> <Link href="/about">About</Link> <Link href="/blog/nextjs">Blog Post</Link> </nav> ); }
Using useRouter Hook
javascriptimport { useRouter } from 'next/router'; export default function Button() { const router = useRouter(); const handleClick = () => { router.push('/about'); // Or router.replace('/about') to replace current history }; return <button onClick={handleClick}>Go to About</button>; }
7. Route Middleware
Next.js 12+ supports route middleware, allowing logic to be executed before the request reaches the page.
javascript// middleware.js export function middleware(request) { const url = request.nextUrl; if (url.pathname.startsWith('/admin') && !request.cookies.get('token')) { return NextResponse.redirect(new URL('/login', request.url)); } return NextResponse.next(); }
8. Route Groups (App Router)
Next.js 13+ App Router introduces route groups concept, using parentheses () to create route groups that don't affect URLs.
shellapp/ (marketing)/ about/ page.js → /about contact/ page.js → /contact (dashboard)/ layout.js → Shared layout settings/ page.js → /settings
9. Parallel Routes and Intercepting Routes (App Router)
App Router also supports advanced routing patterns:
- Parallel Routes: Render multiple pages simultaneously
- Intercepting Routes: Display other content without changing the URL
Best Practices
- Keep routes simple: Use meaningful URL structures
- Use dynamic routes: Use dynamic routes for pages with similar content
- Use catch-all routes wisely: Only use when necessary
- Leverage Link component: Provides better user experience and performance
- Use route middleware: Handle authentication, redirects, and other logic
Next.js's routing system is designed to be simple yet powerful, automatically managing routes through the file system, greatly simplifying routing configuration work while providing enough flexibility to handle complex routing requirements.