Hướng dẫn SEO trên Gatsby
Cách tối ưu website Gatsby cho tìm kiếm qua các chế độ kết xuất, Metadata API, canonical, sitemap, robots.txt, dữ liệu có cấu trúc và kiểm tra HTML đã triển khai.
Ngôn ngữ
1 tín hiệu bằng chứng trên trang này
- Công cụ trực tuyến liên quanCanonicalization Checker
Gatsby có bốn phương thức kết xuất: SSG (mặc định — trang được kết xuất trước thành HTML tĩnh khi chạy gatsby build), DSG (tạo tĩnh trì hoãn đến yêu cầu đầu tiên), SSR (kết xuất phía máy chủ theo từng yêu cầu qua Gatsby Functions) và tuyến chỉ chạy phía máy khách (kết xuất hoàn toàn trong trình duyệt). Phần lớn trang Gatsby dùng SSG, nên trình thu thập dữ liệu nhận HTML hoàn chỉnh ngay lần tải đầu mà không phải chờ hàng đợi kết xuất — nền tảng SEO tốt hơn nhiều so với ứng dụng React thuần phía máy khách. Tuy nhiên, lợi thế đó không áp dụng cho mọi chế độ: trang DSG và SSR tạo HTML ngoài bước dựng và cần phép kiểm tra production riêng; tuyến chỉ chạy phía máy khách không nên được mặc định là cung cấp nội dung riêng theo tuyến trong HTML ban đầu. Dù dùng phương thức nào, Gatsby vẫn gửi toàn bộ môi trường chạy React (~200KB+) và hydrate phía máy khách — đây là chi phí Core Web Vitals, không phải vấn đề khả năng thu thập dữ liệu. Cách quản lý metadata hiện hành là Gatsby Head API tích hợp sẵn (v4.19+), hoạt động trên cả bốn phương thức và thay thế gatsby-plugin-react-helmet. Các lỗi thường gặp gồm canonical kép, trang nháp hoặc mồ côi lọt vào sitemap, thiếu văn bản thay thế, sitemap chỉ được tạo trên production, chưa quyết định rõ sitemap và phép kiểm tra production cho tuyến DSG/SSR/chỉ chạy phía máy khách, cùng rủi ro bảo trì chậm lại kể từ khi Netlify mua Gatsby năm 2023.
Tóm tắt — Theo mặc định, Gatsby tạo các trang thành HTML hoàn chỉnh trước khi có người truy cập; chế độ này gọi là SSG. Khi Google đến, nội dung đã nằm trong trang và không phải chờ JavaScript, nhờ đó Gatsby có lợi thế SEO ban đầu. Gatsby còn hỗ trợ các chế độ kết xuất khác cho trang cần tạo muộn hơn hoặc dùng dữ liệu theo từng yêu cầu. Tuy nhiên, framework vẫn gửi một gói React lớn đến trình duyệt, có thể làm trang chậm, và bạn vẫn phải tự thiết lập thẻ meta, sitemap, canonical và alt text cho hình ảnh.
Gatsby là gì?
Gatsby là framework xây dựng website dựa trên React. Phần lớn ứng dụng React tạo
trang trong trình duyệt sau khi JavaScript tải xong; điều này bất lợi cho SEO vì công
cụ tìm kiếm ban đầu có thể chỉ thấy một khung gần như trống. Gatsby mặc định đảo ngược
quy trình đó. Khi chạy gatsby build, framework tạo trước hầu hết trang thành tệp HTML
hoàn chỉnh. Vì vậy, khi Google, Bing hoặc người đọc yêu cầu trang, nội dung đã có sẵn
trong HTML. Evidence for this claim Gatsby creates static HTML files during its production build. Scope: Gatsby static generation; client-side behavior can still be added. Confidence: high · Verified: Gatsby: Builds and deploys
Chế độ mặc định khiến Gatsby trở thành trình tạo website tĩnh (SSG), nhờ đó khả năng SEO sẵn có thường tốt hơn nhiều so với ứng dụng React thuần. Từng trang cũng có thể chọn ba chế độ kết xuất khác: tạo ở yêu cầu đầu tiên, tạo trên máy chủ cho mỗi yêu cầu hoặc kết xuất hoàn toàn trong trình duyệt. Tab Nâng cao giải thích các chế độ này vì mỗi chế độ thay đổi nội dung mà trình thu thập thực sự nhìn thấy.
Vì sao mọi người lo về Gatsby và SEO — và vì sao phần lớn không cần lo
Quan niệm sai phổ biến nhất là “Gatsby is bad for SEO because it uses React.” (bản dịch) «Gatsby không tốt cho SEO vì dùng React.» Thực tế, phần React chạy sau khi trang đã được tạo và phân phối, chủ yếu để bổ sung tính tương tác. Văn bản, liên kết và tiêu đề mà công cụ tìm kiếm quan tâm đã có trong HTML ngay từ đầu.
Vì vậy, Gatsby tự động vượt qua trở ngại lớn nhất. Nhưng nó không làm toàn bộ SEO thay bạn.
Những phần bạn vẫn phải thiết lập
Website Gatsby không tự động được tối ưu hoàn toàn. Bạn vẫn cần:
- Thêm thẻ title và meta description cho từng trang bằng Gatsby Head API tích hợp sẵn. Evidence for this claim Gatsby's Head API lets pages export document-head metadata. Scope: Gatsby Head API. Confidence: high · Verified: Gatsby: Head API
- Tạo sitemap bằng plugin
gatsby-plugin-sitemap. - Đặt URL canonical để các phiên bản trùng lặp không cạnh tranh.
- Viết alt text cho hình ảnh. Công cụ hình ảnh của Gatsby tự đổi kích thước và tối ưu, nhưng không tự viết alt text.
Điều thường khiến mọi người bất ngờ
Gatsby vẫn gửi toàn bộ React runtime (~200KB+) đến trình duyệt trên mỗi trang. Điều này không cản trở lập chỉ mục vì HTML đã hoàn chỉnh, nhưng có thể làm trang chậm và ảnh hưởng Core Web Vitals, các chỉ số tốc độ trải nghiệm trang của Google. So với Gatsby, framework nhẹ như Astro gần như không gửi JavaScript.
Một điểm khác cần biết khi chọn Gatsby hiện nay: Netlify mua lại Gatsby năm 2023 và hoạt động phát triển tích cực đã chậm đi đáng kể. Điều này không thành vấn đề với website Gatsby hiện có, nhưng đáng cân nhắc cho dự án hoàn toàn mới.
Bạn muốn phiên bản kỹ thuật về Head API so với plugin react-helmet cũ, các bẫy sitemap và canonical, đánh đổi Core Web Vitals của gói React và đánh giá thẳng thắn về tương lai Gatsby? Hãy chuyển sang tab Nâng cao.
Tóm tắt — Gatsby có bốn tùy chọn kết xuất: SSG mặc định, DSG, SSR và route chỉ phía máy khách; chúng không đưa nội dung vào HTML thô theo cùng một cách. SSG tạo sẵn HTML tĩnh lúc build (
gatsby build), trước yêu cầu đầu tiên của trình thu thập. DSG trì hoãn tạo trang đến yêu cầu đầu tiên; SSR tạo trang trên máy chủ cho từng yêu cầu; route chỉ phía máy khách không kết xuất nội dung riêng cho route trước khi trình duyệt chạy JavaScript. Mọi đường dẫn đều hydrate gói React đầy đủ (~200KB+), gây chi phí Core Web Vitals chứ không phải khả năng thu thập. Cách quản lý metadata hiện tại là Gatsby Head API tích hợp (v4.19+), hoạt động với cả bốn đường dẫn và thay thếgatsby-plugin-react-helmet. Các lỗi thường gặp gồm canonical kép, trang nháp/mồ côi lọt vào sitemap, sitemap chỉ có ở production, thiếu alt text trênGatsbyImage, dấu gạch chéo cuối không nhất quán và route DSG/SSR/chỉ phía máy khách chưa được kiểm tra production. Sau thương vụ Netlify mua Gatsby năm 2023, tốc độ bảo trì cũng giảm mạnh.
Bốn tùy chọn kết xuất của Gatsby và ý nghĩa đối với SEO
Google xử lý trang JavaScript qua ba giai đoạn: thu thập, kết xuất rồi lập chỉ mục. Kết xuất diễn ra trong một lượt riêng từ hàng đợi dùng Chromium không giao diện. Hướng dẫn của Google nói rõ vì sao không nên phụ thuộc vào bước này: “Server-side or pre-rendering is still a great idea because it makes your website faster for users and crawlers, and not all bots can run JavaScript.” (bản dịch) «Kết xuất phía máy chủ hoặc kết xuất trước vẫn là lựa chọn tốt vì giúp website nhanh hơn cho người dùng và trình thu thập, đồng thời không phải bot nào cũng chạy được JavaScript.»
Website Gatsby không phải lúc nào cũng là HTML tĩnh tạo lúc build. Gatsby hỗ trợ bốn đường dẫn kết xuất riêng, chọn theo trang hoặc template Evidence for this claim gatsby build writes production output, including generated HTML, to the public directory. Scope: Gatsby production builds. Confidence: high · Verified: Gatsby CLI: build :
- SSG (Static Site Generation) — mặc định.
gatsby buildxuất HTML tĩnh đã kết xuất đầy đủ vào/public. Lần tải HTML thô đầu tiên của Googlebot đã có văn bản, liên kết và metadata. Đây là đường dẫn an toàn, rủi ro thấp mà phần lớn trang Gatsby dùng. - DSG (Deferred Static Generation). Việc tạo trang được trì hoãn đến yêu cầu đầu tiên, hữu ích cho website có rất nhiều trang ít lưu lượng khiến một lần build đầy đủ quá chậm. HTML chưa tồn tại trước yêu cầu đầu tiên, nên phải kiểm tra riêng hành vi yêu cầu đầu và cache.
- SSR (Server-Side Rendering). Trang được kết xuất cho từng yêu cầu bằng dữ liệu tại thời điểm yêu cầu qua Gatsby Functions. Cần kiểm tra production về mã trạng thái, header cache, timeout và nội dung trình thu thập thấy khi phản hồi rỗng hoặc lỗi.
- Route chỉ phía máy khách. Nội dung riêng cho route không có trong HTML ban đầu mà chỉ xuất hiện sau khi JavaScript chạy. Đây là thiết kế phụ thuộc JS, phù hợp với nội dung bị chặn/xác thực nhưng không phù hợp với nội dung cần được lập chỉ mục.
React hydration (ReactDOMClient.hydrateRoot()) chạy phía máy khách trên HTML do bất kỳ
đường dẫn nào tạo ra, chỉ để thêm tính tương tác. Quá trình này giống nhau với mọi đường
dẫn kết xuất và là mối quan tâm riêng với cách trang được tạo.
Ngược lại, ứng dụng React thuần phía máy khách phục vụ <div id="root"> trống và phụ
thuộc vào trình duyệt hoặc bộ kết xuất để tạo trang. Phần lớn trang Gatsby mặc định gửi
HTML có ý nghĩa; đó là lợi thế lập chỉ mục thực sự, nhưng thuộc về từng trang chứ không
phải bảo đảm của framework. Tùy chọn kết xuất và công cụ hình ảnh không tự bảo đảm Core
Web Vitals, lập chỉ mục hay thứ hạng; hãy xác minh đầu ra production của từng route.
Điểm đánh đổi chung của SSG, DSG và SSR nằm ở hiệu suất, chứ không phải khả năng thu thập dữ liệu: Gatsby gửi toàn bộ môi trường chạy React đến mỗi trang rồi hydrate lại trang đó. Phần dưới sẽ phân tích kỹ hơn vấn đề này và so sánh Gatsby với Astro.
Gatsby Head API so với gatsby-plugin-react-helmet
Đây là câu hỏi quan trọng nhất để xác định một dự án Gatsby SEO có đang triển khai theo cách hiện đại hay không: “are you doing it the modern way?” (bản dịch) «Bạn có đang làm theo cách hiện đại không?»
Cách cũ — gatsby-plugin-react-helmet. Trong nhiều năm, cách tiêu chuẩn để đặt
<title>, mô tả meta và các thẻ head khác là dùng thư viện react-helmet cùng plugin
này. Vai trò của plugin là cung cấp hỗ trợ SSR cho react-helmet — nếu không có nó,
tiêu đề và thẻ meta chỉ xuất hiện sau khi JavaScript chạy, thay vì có sẵn trong HTML
thô, khiến giải pháp mất đi mục đích SEO. Cách này vẫn hoạt động, nhưng có những vấn đề
đã biết với React Hooks và cơ chế kết xuất đồng thời, cùng lỗi tiêu đề ở thẻ trình duyệt
chạy nền mà bạn phải khắc phục bằng defer={false}.
Cách hiện đại — Gatsby Head API (v4.19+). Gatsby hiện có sẵn một cơ chế để thêm
các phần tử head: xuất một hàm có tên Head từ bất kỳ tệp trang hoặc mẫu nào. Evidence for this claim Gatsby pages and templates can export a named Head function to add head elements. Scope: Gatsby Head API. Confidence: high · Verified: Gatsby: Head API
export const Head = () => (
<>
<title>Page Title</title>
<meta name="description" content="..." />
</>
)API này nhận các prop hữu ích — location.pathname, params, data (từ truy vấn
GraphQL của trang) và pageContext — đồng thời loại bỏ các thẻ trùng nhau nếu chúng
có cùng prop id (thẻ sau cùng được giữ lại). Tuy vậy, việc chạy đồng thời hai cơ chế
quản lý thẻ head khác nhau (Head API cùng một lệnh gọi react-helmet còn sót lại) vẫn
có thể gây xung đột dù đã có tính năng loại bỏ trùng lặp. Head API chỉ hoạt động
trong tệp trang và mẫu, không hoạt động trong các component tùy ý. So với
react-helmet, nó không cần gói bên thứ ba hay lớp bọc Provider, đồng thời giữ thứ tự
thẻ ổn định khi React 18 kết xuất luồng. Hãy dùng Head API cho mọi dự án mới và
lập kế hoạch chuyển đổi các dự án hiện có.
Head API hoạt động theo cùng một cách trên cả bốn phương thức kết xuất — SSG, DSG, SSR
và tuyến chỉ chạy phía máy khách đều hỗ trợ xuất một hàm Head. Điểm khác biệt là
thời điểm kết quả của hàm này xuất hiện trong phần HTML mà trình thu thập dữ liệu có
thể tải: với SSG, nó được đưa vào ngay khi dựng trang; với DSG và SSR, nó được tạo ở
lần yêu cầu đầu tiên hoặc ở từng yêu cầu; còn với tuyến chỉ chạy phía máy khách, nó
hoàn toàn không có trong HTML ban đầu. Đừng cho rằng “I added a Head export”
(bản dịch) «Tôi đã thêm một hàm xuất Head» đồng nghĩa với “this is in the raw HTML for every route”
(bản dịch) «Nội dung này có trong HTML thô của mọi tuyến». Hãy kiểm tra đầu ra thực tế
trên môi trường sản xuất (view-source: hoặc curl) cho từng phương thức mà mỗi tuyến
sử dụng, thay vì chỉ kiểm tra một trang đại diện.
Lỗi “meta tags in DevTools but not in source” (bản dịch) «Thẻ meta có trong DevTools nhưng không có trong mã nguồn».
Đây là một triệu chứng kinh điển của lỗi Gatsby SEO: tiêu đề và thẻ meta xuất hiện
trong Chrome DevTools nhưng lại không có trong view-source:. Nguyên nhân là DevTools
hiển thị DOM đã được hydrate (sau khi JavaScript chạy), còn chế độ xem mã nguồn hiển
thị HTML thô. Nếu thẻ chỉ xuất hiện trong DevTools, component SEO đang được kết xuất
phía máy khách thay vì được đưa vào đầu ra tĩnh của Gatsby — thường vì nó được dùng như
một component thông thường, thay vì làm hàm Head của trang hoặc nằm trong hàm đó.
Luôn xác minh trong HTML thô, không chỉ trong DevTools.
Kết nối component SEO với lớp dữ liệu GraphQL
Lớp dữ liệu của Gatsby dùng GraphQL; đây là cách bạn đưa metadata vào các trang.
useStaticQuerylấy các giá trị mặc định dùng cho toàn trang web từsiteMetadata(tiêu đề, mô tả,siteUrl) được định nghĩa tronggatsby-config.js.- Truy vấn GraphQL ở cấp trang truyền thẳng prop
datavào hàm xuấtHead— không cần thêm bước kết nối nào. - Mẫu triển khai tiêu chuẩn là prop || giá trị dự phòng trong siteMetadata: dùng giá trị riêng của trang nếu có, nếu không thì dùng giá trị mặc định của trang web.
Một hàm xuất Head nhận dữ liệu trang có dạng như sau:
export const Head = ({ data }) => (
<>
<title>{data.post.title}</title>
<meta name="description" content={data.post.excerpt} />
</>
)Sitemap: gatsby-plugin-sitemap và những điểm dễ mắc lỗi
Cài đặt gatsby-plugin-sitemap rồi cấu hình trong gatsby-config.js. Có một số điểm
dễ gây nhầm lẫn:
- Plugin tạo
sitemap-index.xml, không phải/sitemap.xml. Hãy gửi URL của tệp chỉ mục trong Google Search Console — đừng gửi/sitemap.xmlrồi kỳ vọng URL đó tồn tại. - Plugin chỉ chạy trong bản dựng production. Nó không làm gì cả khi bạn chạy
gatsby develop. Để kiểm thử, hãy chạygatsby build && gatsby serve. Nhiều báo cáo “my sitemap is missing” (bản dịch) «Sitemap của tôi bị thiếu» thực chất chỉ có nghĩa là “I never ran a production build.” (bản dịch) «Tôi chưa từng chạy một bản dựng production.» createLinkInHead: truetheo mặc định tự động thêm tham chiếu đến sitemap vào phần head của HTML.- Plugin luôn loại trừ
/dev-404-page,/404và/offline-plugin-app-shell-fallback. - Google bỏ qua
<priority>và<changefreq>— tài liệu của plugin nêu rõ điều này. Thay vào đó, hãy tập trung cung cấp giá trị<lastmod>chính xác. entryLimitmặc định là 45 000 URL cho mỗi tệp.
Bạn phải tự loại trừ bản nháp. Gatsby dựng mọi nội dung nó tìm thấy, vì vậy nội
dung nháp sẽ đi thẳng vào sitemap nếu bạn không lọc. Hãy lọc trong gatsby-node.js
bằng điều kiện GraphQL (e.g. loại trừ mục không có ngày xuất bản), không phải bằng
cách ẩn nội dung trong một component React — đến lúc đó trang đã được dựng và liệt kê.
Các tuyến DSG, SSR và chỉ chạy phía máy khách cần một quyết định rõ ràng về sitemap.
gatsby-plugin-sitemap phản ánh những gì plugin có thể thấy tại thời điểm dựng. Trang
SSG khá đơn giản — nó tồn tại dưới dạng tệp tĩnh nên đương nhiên có thể được đưa vào
sitemap. HTML của trang DSG chưa tồn tại ở thời điểm dựng (nó được tạo ở yêu cầu đầu
tiên), trang SSR không bao giờ có một tệp HTML cố định, còn tuyến chỉ chạy phía máy khách
ngay từ đầu đã không có nội dung riêng theo tuyến để lập chỉ mục. Đừng mặc định rằng các
tuyến này có trong sitemap (hoặc nên có) chỉ vì tuyến tồn tại. Hãy quyết định cho từng
trang xem nó có thuộc sitemap hay không, rồi xác minh rằng sitemap-index.xml được tạo
ra thực sự phản ánh quyết định đó thay vì một phỏng đoán tại thời điểm dựng.
robots.txt: gatsby-plugin-robots-txt
gatsby-plugin-robots-txt tạo robots.txt tại thời điểm dựng. Chi tiết hữu ích cho
SEO là khả năng nhận biết môi trường: plugin đọc process.env.GATSBY_ACTIVE_ENV, sau
đó đọc process.env.NODE_ENV, nên bạn có thể áp dụng quy tắc khác nhau cho từng môi
trường. Trường hợp sử dụng kinh điển là chặn trình thu thập dữ liệu trên các bản
triển khai xem trước hoặc theo nhánh của Netlify, để URL staging không vô tình được
lập chỉ mục trong khi môi trường production vẫn cho phép thu thập dữ liệu.
URL canonical và lỗi canonical kép
Có hai cách khả thi:
gatsby-plugin-canonical-urlsthêm một<link rel="canonical">vào mỗi trang. ĐặtstripQueryString: trueđể/blog?tag=foovà/blogkhông bị coi là hai trang đã canonical hóa riêng biệt — đây là lựa chọn được khuyến nghị cho hầu hết trang web.- Head API, tự đặt URL canonical từ
location.pathname:
export const Head = ({ location }) => (
<link rel="canonical" href={`https://example.com${location.pathname}`} />
)Lỗi canonical kép. Đây là một lỗi đã biết và rất dễ gặp: nếu bạn dùng
gatsby-plugin-canonical-urls đồng thời với thẻ canonical của react-helmet, trang
sẽ xuất ra hai thẻ <link rel="canonical">. Hãy chọn một cơ chế duy nhất. (Nếu
bạn dùng react-helmet, gatsby-plugin-react-helmet-canonical-urls là lựa chọn có
nhận biết helmet; nếu dùng Head API, hãy đặt canonical tại đó và bỏ plugin.)
Dấu gạch chéo cuối URL. Trang Gatsby có thể truy cập được cả khi có lẫn không có
dấu gạch chéo ở cuối. Component <Link> của Gatsby dùng định tuyến History API phía
máy khách, nên bỏ qua chuyển hướng 301 phía máy chủ mà bạn thường dùng để chuẩn hóa
dấu gạch chéo cuối URL. Hãy chọn một dạng, thực thi nó ở cấp máy chủ lưu trữ/CDN và
giữ URL canonical nhất quán với dạng đó.
Image SEO: gatsby-plugin-image
gatsby-plugin-image thực sự là một trong những điểm mạnh của Gatsby. Plugin cung
cấp hai component:
StaticImage— dành cho hình ảnh có đường dẫn đã biết và được viết cố định tại thời điểm dựng.GatsbyImage— dành cho hình ảnh động lấy từ GraphQL.
Plugin tự động tạo nhiều kích thước, định dạng WebP/AVIF, tải trì hoãn và các điểm ngắt (750/1080/1366/1920px). Nó cũng tạo ảnh giữ chỗ (làm mờ, dùng màu chủ đạo hoặc SVG đồ theo nét) để dành sẵn không gian và ngăn Cumulative Layout Shift — một chỉ số Core Web Vitals. Nhờ kích thước được đặt trước, bạn tránh được CLS; các định dạng hiện đại cùng tải trì hoãn cũng giúp cải thiện LCP.
Điều duy nhất plugin không làm là viết văn bản thay thế. Lần nào bạn cũng phải tự
thực hiện việc này — thiếu văn bản thay thế trên GatsbyImage là một trong những sơ
suất Gatsby SEO phổ biến nhất. (Bạn đang chuyển từ gói gatsby-image cũ? Có sẵn một
codemod: npx gatsby-codemods gatsby-plugin-image.)
Dữ liệu có cấu trúc (JSON-LD)
JSON-LD là định dạng dữ liệu có cấu trúc Google ưu tiên. Trong Gatsby hiện đại, cách gọn gàng để thêm định dạng này là dùng một thẻ script qua Head API:
export const Head = ({ data }) => (
<script type="application/ld+json">
{JSON.stringify({
"@context": "https://schema.org",
"@type": "Article",
"headline": data.post.title,
})}
</script>
)gatsby-plugin-next-seo cung cấp các component JSON-LD dựng sẵn nếu bạn không muốn
tự viết. Cần làm rõ một nhầm lẫn thường gặp: gatsby-plugin-manifest không phải
là plugin dữ liệu có cấu trúc — nó tạo tệp manifest cho ứng dụng web PWA (biểu
tượng, màu chủ đề), hoàn toàn không liên quan đến schema.
React bundle và Core Web Vitals
Đây là điểm yếu thực sự của Gatsby so với các trình tạo trang không gửi JavaScript.
- Hydration toàn phần (mặc định trong Gatsby 1–4) hydrate toàn bộ cây React và gửi môi trường chạy React nặng 200KB+ đến mỗi trang. HTML đã được kết xuất trước nên điều này không ảnh hưởng đến khả năng thu thập dữ liệu, nhưng chắc chắn ảnh hưởng đến tốc độ tải và CWV.
- Hydration từng phần (Gatsby 5, thử nghiệm) chỉ hydrate các component được đánh dấu
"use client", còn phần còn lại giữ nguyên dưới dạng HTML tĩnh; nhờ đó giảm lượng JavaScript được gửi và trực tiếp cải thiện TTI cùng CWV. Những hạn chế là đáng kể: chỉ hoạt động trong bản dựng production, vẫn ở giai đoạn beta và không tương thích với emotion, styled-components cùnggatsby-plugin-offline.
Điểm cần ghi nhớ: tải trọng JavaScript của Gatsby là vấn đề về hiệu suất, không phải về khả năng lập chỉ mục. Googlebot vẫn kết xuất JavaScript để đánh giá các tín hiệu trải nghiệm trang, nên gói mã có thể làm giảm CWV dù nội dung vẫn được lập chỉ mục tốt.
So sánh Gatsby và Astro về SEO
Nếu hôm nay bạn đang chọn một framework tĩnh, đây là phép so sánh quan trọng nhất đối với SEO.
| Khía cạnh | Gatsby | Astro |
|---|---|---|
| JavaScript gửi đến trình duyệt | 200KB+ (toàn bộ môi trường chạy React) | ~5KB (chỉ các đảo tương tác) |
| Mô hình kết xuất | SSG → SPA (hydration toàn phần) | SSG → MPA (mặc định không hydrate) |
| Tốc độ dựng (40 trang) | 2–3 phút | Dưới 10 giây |
| Hệ sinh thái plugin SEO | Trưởng thành (gatsby-plugin-*) | Đang phát triển |
| Ảnh hưởng đến ngân sách thu thập dữ liệu | Cao hơn (Google phải kết xuất nhiều JavaScript hơn) | Thấp hơn |
| Tương lai của framework | Chưa chắc chắn (thuộc sở hữu Netlify, hoạt động chậm lại) | Tích cực, đang phát triển |
Cả hai đều kết xuất trước HTML có thể lập chỉ mục — ở điểm này chúng ngang nhau. Khác biệt nằm ở chi phí JavaScript: các đảo của Astro chỉ gửi một phần nhỏ lượng JavaScript; một bài so sánh của Vaihe mô tả lợi ích này là “Reduced JavaScript execution conserves crawl budget and accelerates page scanning.” (bản dịch) «Giảm lượng JavaScript phải thực thi giúp bảo toàn ngân sách thu thập dữ liệu và tăng tốc quá trình quét trang.» (Có một lưu ý lịch sử theo chiều ngược lại: tại thời điểm so sánh, tính năng xử lý ảnh của Astro chưa tự động thêm chiều rộng/chiều cao nên phát sinh cảnh báo Lighthouse — hãy kiểm tra tài liệu Astro hiện tại vì vấn đề này có thể đã được giải quyết.)
Để có bối cảnh so sánh rộng hơn cho toàn lĩnh vực, hãy xem trung tâm về trình tạo trang tĩnh.
Nhìn thẳng vào quỹ đạo bảo trì của Gatsby
Tôi sẽ không tô hồng vấn đề này, nhưng cũng không cường điệu nó thành thảm họa.
Netlify mua lại Gatsby Inc. vào tháng 2 năm 2023. Gatsby Cloud đã ngừng hoạt động và khách hàng được chuyển sang Netlify; Netlify tuyên bố thương vụ này sẽ “not impact Gatsby JS.” (bản dịch) «không ảnh hưởng đến Gatsby JS.» Kể từ đó, hoạt động phát triển chậm lại rõ rệt. Một thảo luận cộng đồng được đọc rộng rãi trên GitHub (#39062) cho rằng Gatsby trên thực tế đã bị bỏ rơi — rất ít commit, không hỗ trợ React 19, lộ trình năm 2024 không được thực hiện và dịch vụ telemetry đã đóng cửa. Những người bảo trì mô tả trạng thái hiện tại là chỉ sửa lỗi bảo mật, cập nhật một số dependency và xử lý các lỗi dễ khắc phục.
Điều đó có ý nghĩa gì với đội ngũ SEO. Với một trang Gatsby hiện có, đây không
phải tình huống khẩn cấp — trang vẫn dựng được, vẫn được lập chỉ mục và vẫn hoạt động.
Rủi ro là hệ sinh thái suy yếu theo thời gian: SEO phụ thuộc vào các plugin
(gatsby-plugin-sitemap, image, canonical-urls), còn những plugin lâu năm (e.g.
gatsby-source-shopify đối mặt với việc API bị ngừng hỗ trợ) cuối cùng có thể hỏng theo
những cách âm thầm làm suy giảm khả năng lập chỉ mục. Với một dự án mới, hãy cân
nhắc nghiêm túc yếu tố này — Astro và Next.js là những framework mà người dùng đang
chuyển sang.
Danh sách kiểm tra production: xác minh từng phương thức kết xuất
Một phiên gatsby develop cục bộ, hay thậm chí nhật ký gatsby build không có lỗi,
không chứng minh được trình thu thập dữ liệu thực sự nhận gì. Vì các tuyến SSG, DSG,
SSR và chỉ chạy phía máy khách tạo HTML theo những cách khác nhau, hãy kiểm tra hành vi
production theo từng phương thức thay vì cho rằng một trang đại diện bao quát tất cả:
- Nội dung HTML thô. Với mỗi phương thức kết xuất đang dùng, hãy tải một URL
production thực bằng
curl -s <url>hoặcview-source:— không dùng DevTools — rồi xác nhận nội dung, tiêu đề và thẻ meta mà trình thu thập dữ liệu sẽ thấy thực sự có mặt. - Metadata (đầu ra của hàm Head). Xác nhận các thẻ do hàm xuất
Headtạo ra nằm trong HTML thô của phương thức đang xét. Đây là điểm DSG/SSR khác SSG nhiều nhất: thẻ có trong mã nguồn ở cả hai trường hợp, nhưng chỉ một lần tải từ production mới chứng minh chúng đã đi vào phản hồi. - Trạng thái HTTP. Kiểm tra mã trạng thái phản hồi trên production, đặc biệt với các tuyến SSR và DSG — một trang kết xuất tốt ở máy cục bộ vẫn có thể trả về 500 trên production ở yêu cầu đầu tiên hoặc khi chịu tải, theo cách bản dựng không bộc lộ.
- Hành vi bộ nhớ đệm. Đầu ra SSG là tệp tĩnh với cách lưu đệm dễ dự đoán. DSG lưu đệm sau yêu cầu đầu tiên — hãy xác nhận yêu cầu thứ hai vừa nhanh vừa đúng, không chỉ yêu cầu đầu. Phản hồi SSR phụ thuộc vào header bộ nhớ đệm và lớp lưu trữ; hãy xác minh nội dung cũ hoặc nội dung theo yêu cầu không được gửi nhầm cho khách truy cập.
- Hành vi khi lỗi và khi dữ liệu rỗng. Với trang SSR và DSG dựa vào dữ liệu lấy tại thời điểm yêu cầu hoặc yêu cầu đầu tiên, hãy kiểm tra trình thu thập dữ liệu thấy gì nếu việc lấy dữ liệu thất bại hoặc trả về rỗng — trạng thái lỗi chưa được xử lý không phải là trang bạn đã kiểm thử cục bộ với dữ liệu tốt.
- Tạo sitemap và loại trừ URL. Xác nhận lại rằng việc này chỉ diễn ra trong bản
dựng production (
gatsby build && gatsby serve, tuyệt đối không phảigatsby develop), và những mục bạn dự định loại trừ — bản nháp, tuyến chỉ chạy phía máy khách, hay bất kỳ nội dung nào bạn quyết định không liệt kê — thực sự vắng mặt trongsitemap-index.xmlđược tạo ra, chứ không chỉ vắng mặt trong ý định của bạn.
Không mục nào trong số này là tùy chọn đối với từng phương thức kết xuất — một
gatsby build chạy thành công chỉ chứng minh đầu ra SSG, không chứng minh hành vi của
DSG, SSR hay tuyến chỉ chạy phía máy khách.
Những lỗi Gatsby SEO phổ biến
- Vẫn dùng
gatsby-plugin-react-helmet— đây là cách cũ; hãy chuyển sang Head API. - Thẻ meta có trong DevTools nhưng không có trong mã nguồn trang — component SEO
đang kết xuất phía máy khách; hãy kiểm tra
view-source:, không phải DevTools. - Nội dung nháp có trong sitemap — lọc bản nháp bằng GraphQL trong
gatsby-node.js, không phải trong component React. - Trang mồ côi từ
src/pages— Gatsby tự tạo tuyến cho mọi tệp ở đó; tệp cũ vẫn được dựng và đưa vào sitemap. - Thẻ canonical kép — cả
gatsby-plugin-canonical-urlsvà react-helmet đều chạy. - Dấu gạch chéo cuối URL không nhất quán — định tuyến phía máy khách của
<Link>bỏ qua chuyển hướng dấu gạch chéo cuối URL ở phía máy chủ. - Không loại chuỗi truy vấn khỏi canonical — hãy đặt
stripQueryString: true. - Bỏ sót văn bản thay thế trên
GatsbyImage— component không tự tạo nội dung này. - Gửi
/sitemap.xml— tệp thực tế là/sitemap-index.xml. - Kiểm thử sitemap trong
gatsby develop— sitemap chỉ được tạo khi chạygatsby build. - Bật/tắt noindex bằng trạng thái React — Google có thể đã xử lý HTML thô; và
khi thấy
noindextrong HTML thô, Google có thể bỏ qua hoàn toàn bước kết xuất. Hãy giữ quyết định noindex trong HTML tĩnh hoặc header máy chủ.
Để tìm hiểu nền tảng kết xuất JavaScript phía sau tất cả những vấn đề này, hãy xem trung tâm JavaScript SEO cấp trên.
Tóm tắt bằng AI
Bản tóm lược của nội dung Nâng cao:
- Gatsby có bốn phương thức kết xuất — SSG, DSG, SSR và tuyến chỉ chạy phía máy khách.
SSG là mặc định:
gatsby buildkết xuất trước trang thành HTML tĩnh, nên trình thu thập dữ liệu nhận toàn bộ nội dung ngay lần tải đầu — không phải chờ hàng đợi kết xuất, đồng thời có nền tảng lập chỉ mục vững nhất. DSG trì hoãn việc tạo trang đến yêu cầu đầu tiên; SSR tạo trang theo từng yêu cầu; tuyến chỉ chạy phía máy khách không kết xuất nội dung riêng theo tuyến cho đến khi JavaScript chạy trong trình duyệt (giống một ứng dụng React thuần phía máy khách). Hãy xác minh HTML production theo từng phương thức —gatsby buildthành công chỉ chứng minh hành vi SSG. - Chi phí của gói React là vấn đề hiệu suất, không phải khả năng thu thập dữ liệu, và áp dụng bất kể phương thức kết xuất. Gatsby hydrate toàn bộ môi trường chạy React (~200KB+) ở phía máy khách, gây ảnh hưởng đến Core Web Vitals. Các trình tạo không gửi JavaScript (Hugo, Jekyll, Eleventy) không có chi phí này; Astro chỉ gửi ~5KB qua các đảo.
- Dùng Gatsby Head API (v4.19+), tức hàm xuất có tên
Headtừ tệp trang/mẫu, để đặt tiêu đề, thẻ meta, canonical và JSON-LD. API này hoạt động trên cả bốn phương thức kết xuất và thay thếgatsby-plugin-react-helmetcũ. Nó chỉ hoạt động trong trang/mẫu và loại bỏ trùng lặp theoid. - Danh sách kiểm tra production theo từng phương thức: nội dung HTML thô, metadata do hàm Head xuất, trạng thái HTTP, hành vi bộ nhớ đệm và cách xử lý lỗi/trạng thái rỗng — hãy kiểm tra cả năm mục cho phương thức mà tuyến thực sự dùng, đồng thời xác nhận sitemap chỉ được tạo và loại trừ đúng mục trong bản dựng production.
- Sitemap:
gatsby-plugin-sitemaptạositemap-index.xml(hãy gửi tệp đó, không phải/sitemap.xml) và chỉ chạy khigatsby build, không chạy trong môi trường phát triển. Google bỏ qua<priority>/<changefreq>— hãy tập trung vào<lastmod>. Lọc bản nháp tronggatsby-node.js. Mỗi tuyến DSG, SSR và chỉ chạy phía máy khách cần một quyết định rõ ràng về việc đưa vào sitemap — đừng mặc định chúng được xử lý giống trang SSG. - Canonical: dùng Head API +
location.pathname, hoặcgatsby-plugin-canonical-urlsvớistripQueryString: true— không bao giờ dùng cả hai vì sẽ tạo canonical kép. - Hình ảnh:
gatsby-plugin-imagetự xử lý kích thước/WebP/tải trì hoãn và ngăn CLS, nhưng không viết văn bản thay thế — bạn phải tự làm. - Lỗi “DevTools but not view-source” (bản dịch) «Có trong DevTools nhưng không có
trong mã nguồn» = component SEO kết xuất phía máy khách thay vì qua hàm xuất
Head. - Rủi ro bảo trì: Netlify mua lại Gatsby vào năm 2023; hoạt động đã chậm lại (không hỗ trợ React 19, lộ trình không được thực hiện). Các trang hiện có vẫn ổn; với dự án mới, hãy cân nhắc Astro/Next.js.
Tài liệu chính thức
Tài liệu nguồn sơ cấp từ Gatsby và Google.
Gatsby
- Các tùy chọn kết xuất — tổng quan về bốn phương thức kết xuất của Gatsby: SSG, DSG, SSR và tuyến chỉ chạy phía máy khách.
- Sử dụng Deferred Static Generation — hành vi tạo trang ở yêu cầu đầu tiên của DSG.
- Sử dụng Server-Side Rendering — đầu ra theo thời điểm yêu cầu của SSR qua Gatsby Functions.
- Tuyến chỉ chạy phía máy khách và xác thực người dùng — lý do tuyến loại này không cung cấp nội dung riêng theo tuyến trong HTML ban đầu.
- Thêm component SEO — mẫu component SEO được khuyến nghị.
- Tài liệu tham chiếu Gatsby Head API — cách hiện đại, tích hợp sẵn để quản lý thẻ head.
- Giới thiệu Gatsby Head API — lý do API này thay thế react-helmet.
- gatsby-plugin-sitemap — tạo sitemap (chỉ trong bản dựng production).
- gatsby-plugin-image —
StaticImage/GatsbyImage, định dạng và khả năng ngăn CLS. - gatsby-plugin-robots-txt — robots.txt nhận biết môi trường.
- gatsby-plugin-canonical-urls — thẻ canonical trên toàn trang web và
stripQueryString. - gatsby-plugin-react-helmet — cách quản lý metadata cũ.
- gatsby-plugin-next-seo — các component JSON-LD/schema dựng sẵn.
- Hydration React trong Gatsby — cách HTML tĩnh trở nên tương tác.
- Hiểu những kiến thức cơ bản về JavaScript SEO — các giai đoạn thu thập dữ liệu → kết xuất → lập chỉ mục, và lý do kết xuất trước mang lại lợi ích.
Trích dẫn từ nguồn
Các phát biểu công khai áp dụng trực tiếp cho kiến trúc của Gatsby. Vì Gatsby là một SSG dựa trên JavaScript, nguồn sơ cấp phù hợp là hướng dẫn của Google về kết xuất JavaScript và các phát biểu cùng chủ đề từ đại diện Google.
Google Search Central — kiến thức cơ bản về JavaScript SEO
- “Server-side or pre-rendering is still a great idea because it makes your website faster for users and crawlers, and not all bots can run JavaScript.” (bản dịch) «Kết xuất phía máy chủ hoặc kết xuất trước vẫn là một ý tưởng rất hay, vì nó giúp trang web nhanh hơn đối với người dùng lẫn trình thu thập dữ liệu, và không phải bot nào cũng chạy được JavaScript.» — đây chính là lập luận ủng hộ cách Gatsby xử lý trang tại thời điểm dựng.
- “The page may stay on this queue for a few seconds, but it can take longer than that.” (bản dịch) «Trang có thể nằm trong hàng đợi này vài giây, nhưng cũng có thể lâu hơn.» — câu này nói về hàng đợi kết xuất mà HTML được kết xuất trước giúp bạn tránh phải chờ.
Martin Splitt, Google (Chuyên gia quan hệ nhà phát triển)
- “Even though Googlebot can render JavaScript, we don’t want to rely on that.” (bản dịch) «Mặc dù Googlebot có thể kết xuất JavaScript, chúng tôi không muốn phụ thuộc vào khả năng đó.» — nguyên tắc đứng sau việc ưu tiên SSG/SSR. (Theo bài tường thuật của SEJ / Botify.)
- “A lot of people are still looking at view source. That is not what we use for indexing. We use the rendered HTML.” (bản dịch) «Nhiều người vẫn đang xem mã nguồn. Đó không phải nội dung chúng tôi dùng để lập chỉ mục. Chúng tôi dùng HTML đã kết xuất.» — đây chính xác là lý do lỗi “DevTools vs view-source” (bản dịch) «DevTools so với chế độ xem mã nguồn» trong Gatsby gây nhầm lẫn. (Theo SEJ.)
- “The median time in the render queue is only five seconds.” (bản dịch) «Thời gian trung vị trong hàng đợi kết xuất chỉ là năm giây.» — lưu ý đây là giá trị trung vị; độ trễ ở phần đuôi phân phối có thể dài hơn nhiều. (BrightonSEO, theo SEJ.)
John Mueller, Google (Chuyên gia hỗ trợ Tìm kiếm)
- “Server-side rendering is not a requirement there. We can render JavaScript-based pages for the most part.” (bản dịch) «Kết xuất phía máy chủ không phải là yêu cầu bắt buộc trong trường hợp đó. Về cơ bản, chúng tôi có thể kết xuất các trang dựa trên JavaScript.» — bối cảnh: SSR/SSG là phương pháp thực hành tốt nhất chứ không phải yêu cầu tuyệt đối; sau cùng Google vẫn có thể kết xuất nội dung CSR. (Theo SEJ.)
Danh sách kiểm tra Gatsby SEO
Một lượt kiểm tra để xác nhận bản dựng Gatsby thực sự thân thiện với công cụ tìm kiếm:
- Nội dung chính xuất hiện trong View Source (HTML thô), không chỉ trong DevTools — điều này xác nhận nội dung đã được kết xuất trước, không chỉ chạy phía máy khách.
- Metadata được đặt qua Gatsby Head API (hàm xuất
Headtừ trang/mẫu), không dùng react-helmet cũ cho phần triển khai mới. - Mỗi trang có
<title>và mô tả meta riêng ngay từ thời điểm dựng, với giá trị dự phòng từsiteMetadata. - Thẻ canonical được đặt bằng một cách duy nhất — Head API hoặc
gatsby-plugin-canonical-urls, tuyệt đối không dùng cả hai (để tránh lỗi canonical kép). - Đã đặt
stripQueryString: trueđể các biến thể chuỗi truy vấn không phân mảnh canonical. - Đã cài
gatsby-plugin-sitemap; bạn đã xác minh đầu ra bằnggatsby build && gatsby serve(plugin không chạy trong môi trường phát triển). - Bạn đã gửi
/sitemap-index.xml(không phải/sitemap.xml) trong Search Console. - Nội dung nháp được lọc trong
gatsby-node.js(GraphQL), nên không bao giờ lọt vào sitemap. - Không còn tệp cũ/mồ côi trong
src/pagestự động được dựng thành tuyến. -
robots.txtchặn các bản triển khai xem trước/theo nhánh của Netlify nhưng vẫn mở cho production. - Mọi
GatsbyImage/StaticImageđều có văn bản thay thế rõ ràng. - Tài nguyên JS/CSS không bị chặn trong
robots.txt. - Đã chọn và thực thi dạng dấu gạch chéo cuối URL ở máy chủ/CDN (không chỉ qua
<Link>). - Quyết định
noindexnằm trong HTML tĩnh hoặc header máy chủ, không nằm trong trạng thái React. - Đã kiểm tra Core Web Vitals — gói React có thể là lực cản chính; cân nhắc hydration từng phần nếu khả thi.
- Với mọi phương thức kết xuất đang dùng (SSG, DSG, SSR, chỉ chạy phía máy khách),
bạn đã kiểm tra HTML thô, metadata, trạng thái HTTP, hành vi bộ nhớ đệm và cách
xử lý lỗi/trạng thái rỗng trên production — không chỉ xem nhật ký
gatsby buildcục bộ. - Mỗi tuyến DSG, SSR và chỉ chạy phía máy khách đều có quyết định sitemap rõ ràng, đã được xác minh — không tuyến nào được bao quát bởi cùng giả định dành cho trang SSG.
Các mô hình tư duy
1. Khả năng thu thập dữ liệu và hiệu suất là hai bảng điểm riêng biệt. Gatsby làm rất tốt về khả năng thu thập dữ liệu (HTML được kết xuất trước), nhưng phải trả giá về hiệu suất (gói React). Đừng đánh đồng hai khía cạnh — “Gatsby is bad for SEO because React” (bản dịch) «Gatsby không tốt cho SEO vì React» là cách trộn lẫn chúng. Nội dung vẫn được lập chỉ mục tốt; Core Web Vitals mới là nơi chi phí JavaScript bộc lộ.
2. HTML tồn tại càng sớm thì càng ít khả năng xảy ra lỗi. SSG quyết định HTML tại thời điểm dựng — điểm an toàn nhất. Trang Gatsby mặc định dùng SSG nên nằm ở đầu an toàn của phổ kết xuất (chỉ chạy phía máy khách → SSR → DSG → SSG, xếp gần đúng từ rủi ro cao nhất đến an toàn nhất về khả năng lập chỉ mục). Tuy nhiên, Gatsby là framework đa chế độ — một trang cụ thể có thể dùng DSG, SSR hoặc chỉ chạy phía máy khách, và mỗi chế độ có vị trí riêng trên phổ đó. Hãy biết mỗi tuyến thực sự dùng chế độ nào trước khi cho rằng nó nằm ở đầu an toàn.
3. Mặc định dùng Head API; react-helmet chỉ còn do kế thừa từ dự án cũ.
Với mọi phần triển khai mới, lựa chọn đã rõ: Gatsby Head API. react-helmet là thứ bạn
chuyển khỏi, không phải công cụ nên chọn thêm. Nếu một thẻ không xuất hiện trong HTML
thô, câu hỏi đầu tiên là “is this in a Head export, or stuck in a component?”
(bản dịch) «Thẻ này có nằm trong hàm xuất Head hay đang mắc lại trong một component?»
4. Chỉ chọn đúng một cơ chế canonical.
Canonical bằng Head API hoặc gatsby-plugin-canonical-urls — tuyệt đối không dùng
cả hai. Hai cơ chế = hai thẻ canonical = lỗi canonical kép. Hãy áp dụng cùng nguyên tắc
cho mọi nội dung ghi vào <head>: mỗi loại thẻ chỉ có một nguồn dữ liệu chuẩn.
5. Gatsby dựng mọi thứ nó tìm thấy — vì vậy bạn phải tự lọc.
Bản nháp, tệp src/pages cũ, biến thể chuỗi truy vấn: Gatsby không tự phán đoán nội
dung. Nếu bạn không loại trừ chúng (trong gatsby-node.js, cấu hình canonical hoặc
tùy chọn sitemap), chúng sẽ được xuất bản và thu thập dữ liệu.
6. Dự án mới và trang hiện có có bài toán bảo trì khác nhau. Trang Gatsby hiện có: cứ giữ lại, nó vẫn hoạt động. Dự án mới: tốc độ bảo trì chậm lại và nguy cơ hệ sinh thái suy yếu là những yếu tố thực tế — hãy cân nhắc Astro/Next.js trước khi cam kết lựa chọn.
Gatsby SEO — bảng tra nhanh
Metadata: chọn cách nào
| Cách triển khai | Trạng thái | Khi nào nên dùng |
|---|---|---|
Gatsby Head API (hàm xuất Head) | Hiện hành (v4.19+) | Mọi phần triển khai mới; chỉ dùng trong trang/mẫu |
gatsby-plugin-react-helmet | Cũ | Trang hiện có đang chờ chuyển đổi |
Tổng quan nhanh về plugin
| Plugin | Chức năng | Điểm SEO dễ mắc lỗi |
|---|---|---|
gatsby-plugin-sitemap | Tạo sitemap-index.xml | Chỉ chạy trong bản dựng production; gửi URL chỉ mục |
gatsby-plugin-image | Kích thước, WebP/AVIF, tải trì hoãn, ngăn CLS | Không tự tạo văn bản thay thế |
gatsby-plugin-canonical-urls | Thẻ canonical trên toàn trang web | Không dùng cùng canonical của react-helmet |
gatsby-plugin-robots-txt | Tạo robots.txt tại thời điểm dựng | Dùng quy tắc môi trường để chặn bản triển khai xem trước |
gatsby-plugin-next-seo | Component JSON-LD dựng sẵn | — |
gatsby-plugin-manifest | Manifest PWA (biểu tượng/chủ đề) | Không phải dữ liệu có cấu trúc |
Thông tin nhanh
- Tệp sitemap là
/sitemap-index.xml, không phải/sitemap.xml. - Sitemap không được tạo trong
gatsby develop— hãy dùnggatsby build && gatsby serve. - Google bỏ qua
<priority>/<changefreq>— chỉ cần<lastmod>chính xác. - Gói React nặng khoảng 200KB+ cho mỗi trang (hydration toàn phần); đây là chi phí CWV, không phải chi phí thu thập dữ liệu.
- Để so sánh, Astro chỉ gửi ~5KB (chỉ các đảo).
gatsby develop≠ production: sitemap, robots và một số tối ưu hóa hoạt động khác nhau.- Netlify mua lại Gatsby vào tháng 2 năm 2023; hoạt động bảo trì đã chậm lại (chưa hỗ trợ React 19).
Hàm xuất Head SEO gồm hai dòng
export const Head = ({ data, location }) => (
<>
<title>{data.post.title}</title>
<link rel="canonical" href={`https://example.com${location.pathname}`} />
</>
) Kiểm tra các tệp đầu ra production của Gatsby
Chạy đoạn lệnh này sau gatsby build, không chạy với gatsby develop:
find public -name '*.html' -type f | while IFS= read -r file; do
title_count=$(grep -Eio '<title>[^<]*</title>' "$file" | wc -l | tr -d ' ')
canonical_count=$(grep -Eio '<link[^>]+rel=["'"']canonical["'"'][^>]*>' "$file" | wc -l | tr -d ' ')
robots=$(grep -Eio '<meta[^>]+name=["'"']robots["'"'][^>]*>' "$file" | head -1)
if [ "$title_count" -ne 1 ] || [ "$canonical_count" -ne 1 ]; then
printf '%s\ttitles=%s\tcanonicals=%s\t%s\n' "$file" "$title_count" "$canonical_count" "$robots"
fi
doneĐoạn lệnh này phát hiện đầu ra bị thiếu hoặc trùng lặp do các cơ chế Head API/plugin chồng chéo. Hãy kiểm tra riêng giá trị từng thẻ và việc URL có thuộc sitemap hay không.
Công cụ dành cho Gatsby SEO
- Gatsby Head API (tích hợp sẵn, v4.19+) — cách không cần dependency để quản lý
<title>, meta, canonical và JSON-LD theo từng trang/mẫu. gatsby-plugin-sitemap— tạositemap-index.xmltrong bản dựng production.gatsby-plugin-image—StaticImage/GatsbyImage, kích thước đáp ứng, WebP/AVIF, tải trì hoãn và ảnh giữ chỗ ngăn CLS.gatsby-plugin-canonical-urls— thẻ canonical trên toàn trang web cùngstripQueryString.gatsby-plugin-robots-txt— robots.txt nhận biết môi trường (chặn bản triển khai xem trước).gatsby-plugin-next-seo— component JSON-LD/schema dựng sẵn nếu bạn không muốn tự viết dữ liệu có cấu trúc.view-source:/ GSC URL Inspection — căn cứ xác thực cho câu hỏi “is my content and metadata in the raw HTML?” (bản dịch) «Nội dung và metadata của tôi có nằm trong HTML thô không?» (không phải DevTools, vốn hiển thị DOM đã hydrate).- Lighthouse / PageSpeed Insights — để xem chi phí Core Web Vitals của gói React và đánh giá liệu hydration từng phần có đáng triển khai không.
gatsby build && gatsby serve— cách duy nhất để kiểm thử cục bộ sitemap, robots.txt và các tối ưu hóa chỉ có trên production.
Những điều không nên làm trên trang Gatsby
Các lỗi cụ thể thường xảy ra khi xây dựng và đưa trang Gatsby vào hoạt động — nội dung này tập trung vào phòng tránh, không phải chẩn đoán.
Giữ gatsby-plugin-react-helmet trong phần triển khai mới
Sai lầm: dùng react-helmet theo thói quen trên trang mới hoặc dự án mới, vì các hướng dẫn Gatsby cũ vẫn còn minh họa cách này.
Vì sao sai: react-helmet có những vấn đề đã biết với React Hooks và kết xuất đồng
thời, cùng lỗi tiêu đề ở thẻ trình duyệt chạy nền mà bạn phải vá bằng defer={false}.
Đây cũng là một gói bên thứ ba và lớp bọc Provider mà bạn không còn cần nữa.
Nên làm gì thay thế: dùng Gatsby Head API tích hợp sẵn (v4.19+) — xuất một hàm có
tên Head từ tệp trang hoặc mẫu. Chỉ giữ react-helmet cho mã hiện có mà bạn chưa chuyển đổi.
Chạy đồng thời hai cơ chế canonical
Sai lầm: đặt canonical bằng gatsby-plugin-canonical-urls đồng thời với thẻ
canonical của react-helmet (hoặc Head API) trên cùng một trang.
Vì sao sai: cả hai cơ chế đều chạy, khiến trang xuất ra hai thẻ
<link rel="canonical"> — một kiểu lỗi Gatsby nổi tiếng làm mơ hồ URL mà bạn thực sự
muốn chọn làm canonical.
Nên làm gì thay thế: chọn đúng một cơ chế cho toàn trang web (Head API, hoặc plugin
với stripQueryString: true) và loại bỏ hoàn toàn cơ chế còn lại.
Lọc bản nháp trong component React thay vì tại thời điểm dựng
Sai lầm: ẩn nội dung chưa xuất bản bằng phép kiểm tra phía máy khách (e.g.
if (!post.published) return null) và cho rằng như vậy nội dung sẽ không xuất hiện
trong kết quả tìm kiếm.
Vì sao sai: Gatsby dựng mọi thứ nó tìm thấy thành HTML tĩnh trước khi component đó chạy trong trình duyệt — đến lúc phép kiểm tra React được thực thi, trang nháp đã được dựng và liệt kê trong sitemap.
Nên làm gì thay thế: lọc bản nháp trong gatsby-node.js bằng truy vấn GraphQL
(e.g. loại trừ mục không có ngày xuất bản), để ngay từ đầu chúng không được dựng hoặc
liệt kê.
Đưa GatsbyImage vào hoạt động mà không có văn bản thay thế
Sai lầm: tin rằng gatsby-plugin-image xử lý toàn bộ SEO hình ảnh vì plugin tự
tạo kích thước, định dạng và ảnh giữ chỗ.
Vì sao sai: plugin tối ưu việc phân phối — nó không viết văn bản thay thế. Thiếu
văn bản thay thế trên GatsbyImage/StaticImage là một trong những sơ suất Gatsby SEO
phổ biến nhất, chính vì mọi khía cạnh khác của hình ảnh trông như đã được xử lý.
Nên làm gì thay thế: luôn coi văn bản thay thế là trường bắt buộc trên mọi component hình ảnh — đây là phần duy nhất của SEO hình ảnh mà Gatsby để bạn tự xử lý.
Cho rằng gatsby develop hiển thị đầu ra SEO của production
Sai lầm: kiểm tra hành vi sitemap, robots.txt hoặc noindex trong gatsby develop
rồi kết luận chúng bị hỏng vì không thấy đầu ra.
Vì sao sai: gatsby-plugin-sitemap và một số hành vi khác ở thời điểm dựng đơn
giản là không chạy trong chế độ phát triển — đây không phải lỗi; chế độ phát triển chỉ
đang hoạt động đúng theo thiết kế.
Nên làm gì thay thế: chạy gatsby build && gatsby serve trước khi đưa ra bất kỳ
kết luận nào về sitemap, robots.txt hoặc các tối ưu hóa chỉ có trên production.
Để định tuyến phía máy khách của <Link> che giấu dấu gạch chéo cuối URL không nhất quán
Sai lầm: cho rằng quy tắc chuyển hướng dấu gạch chéo cuối URL ở phía máy chủ được áp dụng mọi nơi, kể cả khi điều hướng bên trong ứng dụng.
Vì sao sai: component <Link> của Gatsby dùng định tuyến History API phía máy
khách, nên bỏ qua chuyển hướng 301 phía máy chủ mà bạn thường dựa vào để chuẩn hóa dấu
gạch chéo cuối URL — vì vậy liên kết nội bộ có thể âm thầm phục vụ dạng “wrong”
(bản dịch) «sai» mà không bao giờ kích hoạt quy tắc chuyển hướng.
Nên làm gì thay thế: chọn một dạng dấu gạch chéo cuối URL, thực thi ở cấp máy chủ lưu trữ/CDN và bảo đảm canonical nhất quán với dạng đó bất kể người dùng truy cập trang theo cách nào.
Các vấn đề Gatsby SEO phổ biến
Tra cứu theo triệu chứng đối với vấn đề bạn đang gặp trên trang Gatsby — hãy bắt đầu từ những gì bạn quan sát được.
Thẻ meta có trong DevTools nhưng thiếu trong chế độ xem mã nguồn
Triệu chứng: khi kiểm tra trang trong Chrome DevTools, tiêu đề/mô tả meta trông
đúng; nhưng view-source: (hoặc lệnh curl lấy HTML thô) cho thấy chúng bị thiếu
hoặc chỉ có giá trị khái quát.
Nguyên nhân có thể: component SEO được kết xuất phía máy khách — nó được dùng như
một component thông thường thay vì làm hàm xuất Head của trang hoặc nằm trong hàm
đó, nên chỉ xuất hiện trong DOM sau khi hydrate.
Cách khắc phục: chuyển các thẻ vào hàm xuất có tên Head của trang hoặc mẫu. Xác
nhận bằng view-source: hoặc curl -s <url> — không dùng DevTools, vì công cụ này
hiển thị DOM đã hydrate chứ không phải nội dung mà trình thu thập dữ liệu nhận khi tải
HTML thô.
Sitemap bị thiếu hoặc trống
Triệu chứng: bạn truy cập /sitemap-index.xml (hoặc kiểm tra Search Console) nhưng
không thấy nội dung, hoặc chỉ thấy danh sách không đầy đủ.
Nguyên nhân có thể: hầu như luôn là do bạn kiểm thử trong gatsby develop, nơi
gatsby-plugin-sitemap hoàn toàn không chạy. Trường hợp ít gặp hơn là plugin chưa được
cài đặt/cấu hình trong gatsby-config.js.
Cách khắc phục: chạy gatsby build && gatsby serve rồi kiểm tra lại. Nếu sitemap
vẫn thiếu, hãy xác minh plugin có trong gatsby-config.js. Xác nhận bằng cách yêu cầu
trực tiếp /sitemap-index.xml — hãy nhớ đây là URL chỉ mục, không phải /sitemap.xml.
Một trang có hai thẻ canonical
Triệu chứng: khi xem mã nguồn (hoặc chạy quy trình kiểm tra schema/thẻ), bạn thấy
hai phần tử <link rel="canonical"> trên cùng một trang.
Nguyên nhân có thể: cả gatsby-plugin-canonical-urls lẫn canonical của react-helmet
(hoặc Head API) đều đang chạy trên cùng một trang.
Cách khắc phục: bỏ một cơ chế để canonical chỉ được đặt từ một nguồn. Xác nhận bằng cách xem lại mã nguồn và dùng Công cụ kiểm tra thẻ canonical của Patrick để bảo đảm chỉ có đúng một canonical được phân giải.
Trang nháp hoặc trang mồ côi xuất hiện trong sitemap
Triệu chứng: sitemap (hoặc báo cáo phạm vi trong Search Console) liệt kê những URL
bạn chưa bao giờ định xuất bản — bài nháp hoặc tệp cũ trong src/pages.
Nguyên nhân có thể: Gatsby tự động dựng và tạo tuyến cho mọi thứ nó tìm thấy — một
mục GraphQL chưa xuất bản nhưng không được lọc, hoặc một tệp còn sót trong src/pages,
sẽ được dựng thành trang tĩnh thực và liệt kê như mọi trang khác.
Cách khắc phục: lọc bản nháp trong gatsby-node.js bằng truy vấn GraphQL (e.g.
loại trừ mục không có ngày xuất bản) để chúng không bao giờ được dựng. Với tệp mồ côi
trong src/pages, hãy xóa tệp cũ — lọc trong component là quá muộn vì lúc đó trang đã
được dựng.
Các biến thể chuỗi truy vấn của một trang bị lập chỉ mục như nội dung trùng lặp
Triệu chứng: Search Console cho thấy các URL gần như trùng nhau, chẳng hạn /blog
và /blog?tag=foo, đều được lập chỉ mục hoặc bị gắn cờ là nội dung trùng lặp.
Nguyên nhân có thể: gatsby-plugin-canonical-urls đang chạy mà không có
stripQueryString: true, nên các biến thể chuỗi truy vấn tự trỏ canonical về chính
chúng thay vì URL sạch.
Cách khắc phục: đặt stripQueryString: true trong cấu hình plugin, dựng lại rồi
kiểm tra lại thẻ canonical trên một URL có chuỗi truy vấn — lúc này thẻ phải trỏ đến
đường dẫn sạch.
Một trang bạn định đặt noindex vẫn xuất hiện trong tìm kiếm
Triệu chứng: bạn đặt noindex cho một trang nhưng nhiều tuần sau trang vẫn được lập chỉ mục, hoặc Search Console vẫn báo đã lập chỉ mục dù có thẻ này.
Nguyên nhân có thể: chỉ thị noindex được bật/tắt qua trạng thái React thay vì được
đưa vào HTML tĩnh hoặc header máy chủ — Google có thể đã xử lý HTML thô (không có
noindex), và khi chỉ thấy noindex trong lượt kết xuất phía máy khách, Google có thể
bỏ qua hoàn toàn việc kết xuất lại trang.
Cách khắc phục: chuyển quyết định noindex vào HTML tĩnh (qua hàm xuất Head tại
thời điểm dựng) hoặc header HTTP, không dùng logic React có điều kiện. Kiểm tra lại bằng
view-source: để xác nhận thẻ có trong phản hồi thô.
Tự kiểm tra: Gatsby SEO
Năm câu hỏi nhanh về cách tối ưu trang Gatsby cho tìm kiếm. Chọn một đáp án cho từng câu rồi kiểm tra kết quả.
Những tài nguyên đáng dành thời gian
Các bài viết liên quan của tôi
- JavaScript SEO: Hướng dẫn toàn diện — kết xuất, tính tương đương của DOM và lý do đầu ra tĩnh/kết xuất trước (như Gatsby) nằm ở phía ít rủi ro của phổ.
- Hướng dẫn SEO kỹ thuật cho người mới bắt đầu — vị trí của kiến trúc kết xuất trong bức tranh tổng thể.
Các bài thuyết trình của tôi
- Cách công cụ tìm kiếm hoạt động (SlideShare) — phần trình bày của tôi về thu thập dữ liệu, kết xuất, lập chỉ mục và xếp hạng. (Tuyên bố miễn trừ thường dùng của tôi vẫn áp dụng: “This is my understanding of systems… not going to be 100% complete or accurate.” (bản dịch) «Đây là hiểu biết của tôi về các hệ thống… có thể không đầy đủ hoặc chính xác 100%.»)
Nguồn trong ngành
- Tài liệu tham chiếu Gatsby Head API — nguồn sơ cấp về cách quản lý metadata hiện đại.
- Giới thiệu Gatsby Head API — lời giải thích của chính Gatsby về lý do API này thay thế react-helmet.
- Google Search Central — kiến thức cơ bản về JavaScript SEO — các giai đoạn thu thập dữ liệu → kết xuất → lập chỉ mục mà bản dựng Gatsby giúp nội dung bỏ qua.
- Gatsby gia nhập Netlify — thông báo mua lại năm 2023, cung cấp bối cảnh về hoạt động bảo trì.
- Netlify mua lại nền tảng frontend Gatsby (TechCrunch) — bài tường thuật độc lập về thương vụ mua lại.
- “Is GatsbyJS abandoned?” discussion #39062 (bản dịch) «Thảo luận #39062: “GatsbyJS đã bị bỏ rơi?”» — chuỗi thảo luận cộng đồng về trạng thái bảo trì hiện tại của Gatsby.
- So sánh SEO giữa Gatsby, Next và Astro (Vaihe) — so sánh tải trọng JavaScript và ngân sách thu thập dữ liệu.
- Tìm hiểu hydration từng phần trong Gatsby 5 (LogRocket) — cải tiến hydration liên quan đến CWV và các giới hạn của nó.
Nhật ký thay đổi
Đã cập nhật 22 thg 8, 2026.
Tóm tắt biên tập và chi tiết thay đổi đã ghi nhận.Chi tiết thay đổi
-
Ghi chú thay đổi chi tiết hiện chỉ có bằng tiếng Anh.
Không thể so sánh đầy đủ — không có bản lưu trước đó cho lần sửa đổi này.
Đã cập nhật 22 thg 8, 2026.
Tóm tắt biên tập và chi tiết thay đổi đã ghi nhận.Chi tiết thay đổi
-
Ghi chú thay đổi chi tiết hiện chỉ có bằng tiếng Anh.
Không thể so sánh đầy đủ — không có bản lưu trước đó cho lần sửa đổi này.
Đã cập nhật 8 thg 8, 2026.
Tóm tắt biên tập và chi tiết thay đổi đã ghi nhận.Chi tiết thay đổi
-
Ghi chú thay đổi chi tiết hiện chỉ có bằng tiếng Anh.
Không thể so sánh đầy đủ — không có bản lưu trước đó cho lần sửa đổi này.
Đã cập nhật 18 thg 7, 2026.
Tóm tắt biên tập và chi tiết thay đổi đã ghi nhận.Chi tiết thay đổi
-
Ghi chú thay đổi chi tiết hiện chỉ có bằng tiếng Anh.
-
Ghi chú thay đổi chi tiết hiện chỉ có bằng tiếng Anh.
-
Ghi chú thay đổi chi tiết hiện chỉ có bằng tiếng Anh.
Không thể so sánh đầy đủ — không có bản lưu trước đó cho lần sửa đổi này.