Next.js Docsnextjs

Sitemap cho Next.js App Router: làm đúng ngay từ đầu

Chỉ cần một file app/sitemap.ts, URL tuyệt đối và ngày sửa thật. Đây là cách sitemap vận hành trong App Router và những lỗi khiến Google bỏ qua nó.

Nội dung được tóm lược tự động bằng AI từ Next.js Docs

Muốn có sitemap trong Next.js App Router, bạn tạo file sitemap.ts (hoặc sitemap.js) trong thư mục app và export mặc định một hàm trả về mảng các URL. Next.js tự dựng thành sitemap.xml hợp lệ ở gốc website, không cần cài thêm thư viện next-sitemap hay viết script chạy sau build như nhiều hướng dẫn cũ.

Nếu site chỉ có vài trang tĩnh, ví dụ trang giới thiệu của một studio nhỏ, bạn thậm chí có thể đặt thẳng file sitemap.xml viết tay vào thư mục app và Next.js sẽ phục vụ nguyên trạng. Phiên bản sinh bằng code chỉ thật sự có ích khi nội dung nằm trong database hoặc CMS, như blog, trang tin hay cửa hàng. Mỗi phần tử có kiểu MetadataRoute.Sitemap, nhận url, lastModified, changeFrequency, priority, cùng các trường tuỳ chọn alternates cho bản đa ngôn ngữ, images và videos.

Lỗi hay gặp nhất là dùng đường dẫn tương đối. Tài liệu của Google yêu cầu URL đầy đủ, tuyệt đối và nói rõ Googlebot sẽ thử crawl đúng chuỗi được liệt kê. Vì vậy hãy khai báo một hằng BASE_URL đọc từ biến môi trường rồi ghép với slug của từng bài. Cách này còn tránh được chuyện bản preview trên Vercel lọt tên miền tạm vào sitemap production, lỗi mà nhiều team phát hiện ra khi thấy Search Console báo hàng loạt URL lạ.

Đừng mất thời gian tinh chỉnh priority và changeFrequency: Google công bố là bỏ qua cả hai. Trường đáng quan tâm là lastModified, vì Google có dùng nó, nhưng chỉ khi giá trị chính xác một cách nhất quán, tức phản ánh lần sửa đáng kể gần nhất ở nội dung chính, dữ liệu có cấu trúc hoặc liên kết. Nhiều ví dụ trên mạng gán new Date() cho mọi URL, tương đương tuyên bố mọi trang vừa đổi hôm nay. Lặp lại vài lần là tín hiệu này mất giá trị. Hãy lấy cột updatedAt thật trong database.

Chuyện cache cũng cần nắm rõ. Theo tài liệu Next.js, sitemap.js là một Route Handler đặc biệt, được cache mặc định trừ khi dùng Request-time API hoặc tuỳ chọn cấu hình dynamic. Nghĩa là sitemap đọc từ database có thể bị đóng băng ở thời điểm build, bài đăng sau khi deploy sẽ chưa xuất hiện cho tới lần build kế tiếp. Với trang tin cập nhật nhiều lần mỗi ngày, đây là khoảng trống đáng kể, nên hãy chủ động bật revalidate theo nhịp phù hợp.

Site lớn sẽ chạm trần: mỗi file sitemap tối đa 50.000 URL và 50MB khi chưa nén. Next.js cho hai cách chia nhỏ. Cách thứ nhất là đặt sitemap riêng trong từng route segment, chẳng hạn app/sitemap.xml và app/products/sitemap.xml. Cách thứ hai là hàm generateSitemaps trả về mảng các id, mỗi id sinh một file ở đường dẫn dạng /product/sitemap/1.xml. Từ Next.js 16, id được truyền vào hàm sitemap dưới dạng promise trả về chuỗi, nên code viết cho bản 15 cần thêm await và ép sang số trước khi tính khoảng bản ghi.

Site song ngữ Việt - Anh nên dùng trường alternates. Truyền bảng languages cho từng URL, Next.js sẽ sinh thẻ xhtml:link kèm hreflang ngay trong sitemap, một trong những cách khai báo phiên bản ngôn ngữ mà Google chấp nhận. Gom quan hệ ngôn ngữ về một chỗ dễ kiểm tra hơn nhiều so với rải thẻ link khắp các template.

Cuối cùng, hãy chỉ đường cho công cụ tìm kiếm. Google coi sitemap là gợi ý chứ không phải mệnh lệnh, nhưng bạn có thể thêm dòng Sitemap: vào robots.txt, file này cũng sinh được bằng app/robots.ts, rồi gửi URL sitemap trong báo cáo Sitemaps của Search Console để xem lần Googlebot tải gần nhất và các lỗi xử lý. Sau mỗi lần deploy lớn, mở /sitemap.xml trên trình duyệt kiểm tra: truy vấn hỏng trả về mảng rỗng vẫn cho ra một sitemap hợp lệ nhưng vô dụng, và sẽ không có cảnh báo nào cả.

Tóm lại: một file sitemap.ts trong app, URL tuyệt đối từ một hằng duy nhất, lastModified lấy từ ngày sửa thật, bỏ qua priority, chọn cách cache có chủ đích, chia file trước mốc 50.000 URL, dùng alternates cho bài song ngữ và khai báo trong robots.txt. Làm đủ những bước này, sitemap sẽ lặng lẽ giúp Google tìm thấy trang mới nhanh hơn.

nextjs · Next.js Docs · Đăng lúc 00:03 · 23/09/2026

Đọc bản gốc ↗