Bắt đầu với Next.js 15: Hướng dẫn Toàn diện
Bắt đầu với Next.js 15: Hướng dẫn Toàn diện
Next.js đã trở thành framework React hàng đầu cho việc xây dựng ứng dụng web hiện đại, và phiên bản 15 mang đến những cải tiến đáng kể về hiệu suất và trải nghiệm phát triển. Trong bài viết này, chúng ta sẽ khám phá những tính năng nổi bật của Next.js 15 và cách bắt đầu xây dựng ứng dụng của bạn.
Giới thiệu
Next.js là gì?
Next.js là một framework React mã nguồn mở được phát triển bởi Vercel, cung cấp các tính năng như server-side rendering (SSR), static site generation (SSG), và routing tích hợp sẵn. Framework này giúp developers xây dựng ứng dụng web có hiệu suất cao với trải nghiệm phát triển tuyệt vời.
Tại sao chọn Next.js 15?
Next.js 15 không chỉ là một bản cập nhật thông thường - đây là một bước tiến lớn với nhiều cải tiến quan trọng:
- Performance tốt hơn: Thời gian build nhanh hơn đáng kể với Turbopack
- Developer Experience cải thiện: Công cụ và error messages tốt hơn
- React 19 Support: Hỗ trợ đầy đủ các tính năng mới nhất của React
- Stability: Production-ready với nhiều bug fixes và optimizations
Ai nên đọc bài này?
Bài viết này phù hợp với:
- Developers đã có kiến thức cơ bản về React
- Những người muốn học về Next.js từ đầu
- Developers muốn nâng cấp từ phiên bản Next.js cũ lên v15
Tính năng nổi bật của Next.js 15
1. App Router - Cách tiếp cận mới cho Routing
App Router là một kiến trúc routing hoàn toàn mới được giới thiệu từ Next.js 13 và được hoàn thiện trong v15. Khác với Pages Router cũ, App Router sử dụng cấu trúc thư mục để định nghĩa routes và hỗ trợ React Server Components mặc định.
Ưu điểm của App Router:
- Folder-based Routing: Mỗi thư mục trong
app
directory đại diện cho một route segment - Layouts: Chia sẻ UI giữa nhiều pages mà không cần re-render
- Loading States: Built-in support cho loading và error states
- Nested Routing: Dễ dàng tạo nested routes với layouts lồng nhau
// app/layout.tsx - Root Layout
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="vi">
<body>
<header>
<nav>Navigation Bar</nav>
</header>
<main>{children}</main>
<footer>Footer Content</footer>
</body>
</html>
);
}
2. React Server Components - Tối ưu Performance
React Server Components (RSC) là một tính năng mạnh mẽ cho phép render components trên server, giúp giảm JavaScript bundle size gửi đến client và cải thiện hiệu suất tải trang.
Lợi ích của Server Components:
- Reduced Bundle Size: Code của server components không được gửi đến client
- Direct Data Access: Truy cập database và API trực tiếp mà không cần API routes
- Better Performance: Faster initial page load và improved SEO
- Security: Giữ sensitive code (API keys, database queries) trên server
// app/blog/page.tsx - Server Component
async function BlogPage() {
// Fetch data trực tiếp trong component
const posts = await db.query('SELECT * FROM posts ORDER BY date DESC');
return (
<div>
<h1>Blog Posts</h1>
<div className="grid gap-6">
{posts.map((post) => (
<BlogCard key={post.id} post={post} />
))}
</div>
</div>
);
}
export default BlogPage;
3. Server Actions - Xử lý Form đơn giản
Server Actions là một tính năng mới cho phép bạn gọi các hàm server trực tiếp từ client mà không cần tạo API endpoints riêng biệt. Điều này làm đơn giản hóa đáng kể việc xử lý forms và mutations.
// app/actions.ts
'use server';
export async function createPost(formData: FormData) {
const title = formData.get('title') as string;
const content = formData.get('content') as string;
// Validate data
if (!title || !content) {
return { error: 'Title and content are required' };
}
// Save to database
await db.posts.create({
data: { title, content, createdAt: new Date() }
});
return { success: true };
}
// app/new-post/page.tsx
import { createPost } from '../actions';
export default function NewPostPage() {
return (
<form action={createPost}>
<input type="text" name="title" placeholder="Post Title" required />
<textarea name="content" placeholder="Post Content" required />
<button type="submit">Create Post</button>
</form>
);
}
4. Turbopack - Build nhanh hơn
Turbopack là bundler mới được viết bằng Rust, thay thế Webpack trong Next.js 15. Nó mang lại tốc độ build nhanh hơn đáng kể, đặc biệt với các dự án lớn.
Cải tiến về tốc độ:
- Fast Refresh nhanh hơn 700x so với Webpack
- Cold starts nhanh hơn 10x
- Incremental builds được tối ưu hóa
Hướng dẫn Thực hành
Cài đặt Next.js 15
Để bắt đầu với Next.js 15, bạn chỉ cần một dòng lệnh:
npx create-next-app@latest my-next-app
Trong quá trình cài đặt, bạn sẽ được hỏi một số câu hỏi:
✔ Would you like to use TypeScript? Yes
✔ Would you like to use ESLint? Yes
✔ Would you like to use Tailwind CSS? Yes
✔ Would you like to use `src/` directory? No
✔ Would you like to use App Router? Yes
✔ Would you like to customize the default import alias? No
Khuyến nghị: Chọn TypeScript và App Router để tận dụng tối đa các tính năng mới.
Tạo trang đầu tiên
Sau khi cài đặt xong, cấu trúc project sẽ như sau:
my-next-app/
├── app/
│ ├── layout.tsx # Root layout
│ ├── page.tsx # Home page
│ └── globals.css # Global styles
├── public/ # Static assets
├── package.json
└── next.config.ts
Hãy tạo một trang "About" đơn giản:
// app/about/page.tsx
export default function AboutPage() {
return (
<div className="container mx-auto px-4 py-8">
<h1 className="text-4xl font-bold mb-4">About Us</h1>
<p className="text-lg text-gray-700">
Welcome to our Next.js 15 application!
</p>
</div>
);
}
Để truy cập trang này, chỉ cần mở http://localhost:3000/about
- Next.js tự động tạo route dựa trên cấu trúc thư mục.
Fetch Data với Server Component
Một trong những điểm mạnh của Server Components là khả năng fetch data trực tiếp:
// app/users/page.tsx
interface User {
id: number;
name: string;
email: string;
}
async function getUsers(): Promise<User[]> {
const res = await fetch('https://jsonplaceholder.typicode.com/users', {
// Cache data trong 1 giờ
next: { revalidate: 3600 }
});
if (!res.ok) {
throw new Error('Failed to fetch users');
}
return res.json();
}
export default async function UsersPage() {
const users = await getUsers();
return (
<div className="container mx-auto px-4 py-8">
<h1 className="text-3xl font-bold mb-6">Users</h1>
<div className="grid gap-4">
{users.map((user) => (
<div key={user.id} className="p-4 border rounded-lg">
<h2 className="text-xl font-semibold">{user.name}</h2>
<p className="text-gray-600">{user.email}</p>
</div>
))}
</div>
</div>
);
}
Tạo Form với Server Action
Xây dựng một contact form hoàn chỉnh:
// app/contact/actions.ts
'use server';
export async function submitContactForm(formData: FormData) {
const name = formData.get('name') as string;
const email = formData.get('email') as string;
const message = formData.get('message') as string;
// Validation
if (!name || !email || !message) {
return {
success: false,
error: 'All fields are required'
};
}
// Email validation
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
return {
success: false,
error: 'Invalid email address'
};
}
try {
// Send email hoặc save to database
console.log('Contact form submitted:', { name, email, message });
return {
success: true,
message: 'Thank you for contacting us!'
};
} catch (error) {
return {
success: false,
error: 'Failed to submit form. Please try again.'
};
}
}
// app/contact/page.tsx
import { submitContactForm } from './actions';
export default function ContactPage() {
return (
<div className="container mx-auto px-4 py-8 max-w-2xl">
<h1 className="text-3xl font-bold mb-6">Contact Us</h1>
<form action={submitContactForm} className="space-y-4">
<div>
<label htmlFor="name" className="block mb-2 font-medium">
Name
</label>
<input
type="text"
id="name"
name="name"
required
className="w-full px-4 py-2 border rounded-lg"
/>
</div>
<div>
<label htmlFor="email" className="block mb-2 font-medium">
Email
</label>
<input
type="email"
id="email"
name="email"
required
className="w-full px-4 py-2 border rounded-lg"
/>
</div>
<div>
<label htmlFor="message" className="block mb-2 font-medium">
Message
</label>
<textarea
id="message"
name="message"
rows={5}
required
className="w-full px-4 py-2 border rounded-lg"
/>
</div>
<button
type="submit"
className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
>
Send Message
</button>
</form>
</div>
);
}
Best Practices
1. Khi nào dùng Server Components
Server Components là default và nên được sử dụng khi:
- Data Fetching: Fetch data từ database hoặc API
- Backend Logic: Xử lý business logic phức tạp
- Security: Code chứa sensitive information
- Large Dependencies: Sử dụng libraries lớn (chỉ chạy trên server)
// Sử dụng Server Component (default)
async function ProductList() {
const products = await fetchProducts(); // Fetch trực tiếp
return <div>{/* Render products */}</div>;
}
2. Khi nào dùng Client Components
Client Components cần thiết khi:
- Interactivity: Sử dụng event listeners (onClick, onChange, etc.)
- Browser APIs: Cần truy cập window, localStorage, etc.
- React Hooks: useState, useEffect, useContext
- Real-time Updates: WebSocket connections
'use client'; // Khai báo Client Component
import { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
3. Error Handling
Next.js 15 cung cấp error boundaries tích hợp:
// app/error.tsx
'use client';
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<div className="flex flex-col items-center justify-center min-h-screen">
<h2 className="text-2xl font-bold mb-4">Something went wrong!</h2>
<p className="text-gray-600 mb-4">{error.message}</p>
<button
onClick={reset}
className="px-4 py-2 bg-blue-600 text-white rounded"
>
Try again
</button>
</div>
);
}
4. TypeScript Setup
Tận dụng TypeScript để có type safety tốt hơn:
// types/index.ts
export interface Post {
id: string;
title: string;
content: string;
author: {
name: string;
email: string;
};
createdAt: Date;
tags: string[];
}
// app/blog/[id]/page.tsx
import type { Post } from '@/types';
async function getPost(id: string): Promise<Post> {
// Fetch post với type safety
const res = await fetch(`/api/posts/${id}`);
return res.json();
}
Kết luận
Next.js 15 đại diện cho một bước tiến lớn trong việc xây dựng web applications hiện đại. Với App Router, React Server Components, Server Actions, và Turbopack, framework này cung cấp một bộ công cụ mạnh mẽ để xây dựng ứng dụng có hiệu suất cao và trải nghiệm phát triển tuyệt vời.
Những điểm chính cần nhớ:
- App Router: Kiến trúc routing mới với folder-based organization
- Server Components: Giảm bundle size và cải thiện performance
- Server Actions: Đơn giản hóa việc xử lý forms và mutations
- Turbopack: Build và hot reload nhanh hơn đáng kể
Bước tiếp theo
Để tiếp tục hành trình học Next.js 15:
- Thực hành: Tạo một dự án nhỏ để làm quen với các concepts
- Đọc Documentation: Next.js Official Docs
- Khám phá Advanced Features: Middleware, Internationalization, Analytics
- Join Community: Next.js Discord
Resources bổ sung
- Next.js 15 Release Notes
- React Server Components RFC
- Vercel Deployment Guide
- Next.js GitHub Repository
Có câu hỏi? Hãy để lại comment bên dưới hoặc liên hệ qua email. Chúc bạn thành công với Next.js 15!

Cong Dinh
Technology Consultant | Trainer | Solution Architect
Với hơn 10 năm kinh nghiệm trong phát triển web và cloud architecture, tôi giúp doanh nghiệp xây dựng giải pháp công nghệ hiện đại và bền vững. Chuyên môn: Next.js, TypeScript, AWS, và Solution Architecture.
Bài viết liên quan
TypeScript Best Practices 2025: Viết Code Sạch và An toàn
Khám phá các pattern TypeScript hiện đại, utility types, và best practices để viết code type-safe và maintainable, giúp team phát triển hiệu quả hơn.

TypeScript Best Practices cho React Developers
Hướng dẫn chi tiết về các best practices khi sử dụng TypeScript trong React projects, bao gồm typing patterns, generic types và advanced techniques
Tối ưu Performance Next.js: Hướng dẫn Toàn diện 2025
Học cách tối ưu ứng dụng Next.js để đạt Lighthouse score >95 với image optimization, code splitting, font optimization và Core Web Vitals monitoring.