REST API là giao diện có sẵn trong WordPress lõi. Nó trả dữ liệu dạng JSON, và mỗi endpoint trả một khối dữ liệu cố định theo cấu trúc của endpoint đó. WPGraphQL là plugin miễn phí, mã nguồn mở, thêm một schema GraphQL vào site, để ứng dụng chọn đúng trường cần lấy trong một lần gọi. Không bên nào tốt hơn tuyệt đối. Việc cần làm, số loại nội dung và kỹ năng sẵn có của đội mới quyết định bên nào hợp hơn. Bài này đi qua cách mỗi bên trả dữ liệu, phần cài đặt và cache của WPGraphQL, điểm mạnh có sẵn của REST, rồi đưa ra cách chọn theo tình huống. Các nguồn được tra ngày 13/10/2026. Nếu cần nhắc lại mô hình headless, xem headless WordPress là gì và khác WordPress thường ở đâu.
REST API và WPGraphQL lấy dữ liệu khác nhau thế nào
Với REST API, dữ liệu nằm theo endpoint. Yêu cầu /wp/v2/posts trả danh sách bài viết, còn thông tin tác giả nằm ở /wp/v2/users/{id}. Nếu chỉ gọi endpoint bài viết, một trang hiện bài kèm tác giả sẽ cần thêm một request cho mỗi tác giả. Tài liệu chính thức của WordPress có tham số _embed để nhúng các tài nguyên liên quan như tác giả, danh mục vào cùng phản hồi. Số request giảm, nhưng phản hồi cũng kèm trường mà màn hình đó không dùng, trừ khi thêm _fields để chọn trường. Từ WordPress 5.4, _embed còn nhận tham số loại liên kết, ví dụ ?_embed=author, và từ WordPress 5.3, _fields lọc được meta theo cú pháp meta.ten-khoa.
WPGraphQL làm ngược lại. Ứng dụng gửi một truy vấn tới endpoint GraphQL và liệt kê đúng các trường cần, kể cả trường nằm trong quan hệ như tác giả của bài. Tài liệu WPGraphQL so sánh đúng tình huống này: lấy năm bài kèm tác giả và avatar bằng REST cần sáu request (một request danh sách và năm request tới từng tác giả), còn WPGraphQL cần một request. Đây là phép thử của chính WPGraphQL, tra ngày 13/10/2026. Trang không nêu phần cứng, phiên bản WordPress hay điều kiện mạng, vì vậy số liệu chỉ dùng để hình dung cơ chế, không dùng làm kết luận về tốc độ của một site cụ thể.
Ví dụ dưới đây viết cùng một nhu cầu theo ba cách. Tên trường trong truy vấn GraphQL là schema mặc định của WPGraphQL, cần kiểm lại trong GraphiQL của site trước khi đưa vào code.
REST, không _embed: 1 request lấy danh sách bài, rồi 1 request cho mỗi tác giả
GET /wp-json/wp/v2/posts?per_page=5
GET /wp-json/wp/v2/users/{id}
REST, có _embed: 1 request, phản hồi kèm cả trường không dùng
GET /wp-json/wp/v2/posts?per_page=5&_embed&_fields=title,_embedded,_links
WPGraphQL: 1 request, chọn đúng trường
POST /graphql
{ posts(first: 5) { nodes { title author { node { name avatar { url } } } } } }
WPGraphQL: cài đặt, truy vấn, phân quyền và cache
Theo trang giới thiệu của WPGraphQL, plugin cài từ mục Plugins, chọn Add New rồi tìm WPGraphQL, hoặc cài bằng Composer qua wpackagist. Cách chọn và quản lý plugin đã cài có trong bài plugin WordPress là gì. Với kiểu permalink Plain, endpoint nằm ở /index.php?graphql. Muốn có đường dẫn /graphql, đổi kiểu permalink trong Settings, Permalinks. Trên thanh admin có nút GraphiQL IDE để viết và chạy truy vấn. Nút Docs liệt kê các type và field của schema, vì vậy người mới có chỗ tra cứu ngay trên site.

Danh sách có phân trang theo mô hình connection của chuẩn Relay. Mỗi kết quả nằm trong nodes hoặc edges, kèm pageInfo có hasNextPage và endCursor. Để lấy trang kế tiếp, ứng dụng gửi lại first và truyền endCursor của trang trước vào after. Tài liệu không nêu giới hạn tối đa cho mỗi trang, do đó đội cần đo số bản ghi phù hợp trên dữ liệu thật.
Về quyền, truy vấn không đăng nhập vẫn chạy được với dữ liệu công khai. Dữ liệu riêng tư như email hay bài nháp chỉ lộ khi có xác thực. Phân quyền đi theo từng trường: trường nào thiếu quyền trả về null, còn các trường khác trong cùng truy vấn vẫn được xử lý. Với thao tác ghi, WPGraphQL kiểm capability của WordPress trước khi chạy, ví dụ tạo bài cần quyền publish_posts. Ứng dụng bên ngoài có thể xác thực bằng Application Passwords (có từ WordPress 5.6), JWT, Basic Auth qua HTTPS hoặc OAuth1. Trình duyệt đã đăng nhập vào WordPress dùng cookie kèm nonce qua header X-WP-Nonce.
Cache thuộc về một plugin mở rộng riêng là WPGraphQL Smart Cache, không nằm trong lõi WPGraphQL. Theo tài liệu object cache của plugin này (tra ngày 13/10/2026), phản hồi được lưu theo cặp truy vấn và biến, vào object cache như Redis hoặc Memcached, và nếu môi trường không hỗ trợ thì dùng transients. Khi có sự kiện như xuất bản bài, các bản ghi gắn tag liên quan bị xoá, và request kế tiếp chạy lại đầy đủ. Trong cài đặt có thể đặt thời gian sống (max age) tính bằng giây. Để biết một phản hồi có lấy từ cache hay không, kiểm trường extensions.graphqlSmartCache.graphqlObjectCache trong kết quả. Tài liệu khuyến nghị network cache trước, chỉ dùng object cache khi không dùng được network cache, vì phần lớn host không áp dụng network cache cho request POST. Cách tổ chức cache khi nội dung đổi có thể đối chiếu với bài về ISR và Draft Mode trên WordPress, vì cả hai đều phải trả lời câu hỏi sửa bài thì trang đổi khi nào.
Chi phí học của WPGraphQL nằm ở schema. Đội phải hiểu type, field, connection, cách truyền biến và cách đọc lỗi GraphQL. Với đội đã làm GraphQL ở phía khác của hệ thống thì việc này nhẹ. Với đội chỉ quen gọi REST, đây là một bộ khái niệm mới. Trang WPGraphQL không nêu nhược điểm của GraphQL, và không bàn chi phí bảo trì khi schema thay đổi, vì vậy phần này phải tự đánh giá trên dự án cụ thể.
REST API: có sẵn trong WordPress nhưng phải gọi nhiều endpoint
REST API có sẵn trong WordPress lõi, nên không cần cài thêm gì để đọc bài viết, trang, taxonomy và media ở chế độ công khai. Tài liệu chính thức mô tả nó là giao diện để ứng dụng bên ngoài, app JavaScript và ứng dụng di động tương tác với site, và đây cũng là nền tảng của Block Editor. Quyền truy cập theo đúng hạn chế của giao diện: nội dung công khai đọc được ngay, còn nội dung riêng tư, có mật khẩu, custom post type và metadata cần xác thực hoặc phải được mở rõ ràng.
Nếu chưa rõ WordPress lõi gồm những phần nào, đọc WordPress là gì trước sẽ dễ theo hơn. Ưu điểm lớn nhất là không có gì phải cài, và công cụ quen thuộc như trình duyệt, curl, Postman hay mọi thư viện HTTP đều gọi được. Nhược điểm nằm ở cách dữ liệu được chia. Mỗi endpoint trả đúng cấu trúc của nó, vì vậy màn hình cần dữ liệu từ nhiều loại đối tượng phải gọi nhiều lần, hoặc dùng _embed và chấp nhận trường thừa. Theo tài liệu phân trang của WordPress (tra ngày 13/10/2026), per_page giới hạn 100 bản ghi mỗi request, cùng page hoặc offset. Phản hồi có hai header X-WP-Total và X-WP-TotalPages để biết tổng số bản ghi và số trang.

Custom post type không tự vào REST API. Tham số show_in_rest của register_post_type mặc định là false, và phải đặt bằng true lúc đăng ký thì post type mới có endpoint. Đường dẫn của endpoint lấy từ rest_base, mặc định là tên post type. Bước này dễ bị bỏ sót khi site có nhiều loại nội dung riêng, do đó cần kiểm sớm. Nếu dùng custom field kiểu ACF để gắn dữ liệu vào các loại nội dung đó, cần kiểm luôn dữ liệu đó có đi qua REST hay không.
So sánh theo tiêu chí
Bảng dưới đặt các tiêu chí thường quyết định khi chọn công cụ. Ô nào nguồn đã đọc không nêu thì ghi rõ là không nêu, không suy đoán thay nguồn.
| Tiêu chí | REST API (lõi WordPress) | WPGraphQL |
|---|---|---|
| Plugin cần cài | Không cần, có sẵn trong WordPress lõi | Cài plugin miễn phí, mã nguồn mở |
| Điều đội phải học | Endpoint, tham số truy vấn, header phân trang | Schema, type, field, connection, cursor và biến truy vấn |
| Cách cache | Gọi bằng GET theo URL vì vậy lớp cache HTTP áp dụng dễ hơn; tài liệu WordPress không bàn cấu hình cache | Object cache qua WPGraphQL Smart Cache; phần lớn host không cache network cho POST; tài liệu khuyến nghị network cache trước |
| Đọc tài liệu và thử nghiệm | Tài liệu chính thức của WordPress; nguồn WPGraphQL nói REST không có đặc tả chính thức | Schema tự mô tả; GraphiQL trong admin có nút Docs để tra type và field |
| Custom post type | Phải đặt show_in_rest bằng true khi đăng ký |
Trang đã đọc hôm nay không nêu cách bật; cần kiểm trong GraphiQL của từng site |
| Lấy nhiều đối tượng trong một lần | Thường phải gọi nhiều endpoint, hoặc dùng _embed và nhận trường thừa |
Một truy vấn lấy được nhiều quan hệ, chỉ đúng trường cần |
| Phân quyền | Theo hạn chế truy cập của site và xác thực cho nội dung riêng | Theo từng trường; thiếu quyền thì trường đó trả về null |
| Công cụ Faust.js | Tài liệu Faust.js không nói Faust dùng REST làm nguồn dữ liệu | Faust.js lấy dữ liệu bằng GraphQL và yêu cầu cài WPGraphQL |
| Rủi ro khi chuyển sau này | Mỗi endpoint một lời gọi; chuyển tầng dữ liệu phải viết lại các lời gọi | Phụ thuộc plugin và schema; gỡ plugin thì endpoint GraphQL mất theo (suy luận từ việc plugin tạo ra schema) |
Khi nào chọn cái nào
Quyết định cần đi theo việc cần làm, không theo xu hướng. Có 6 bước dưới đây, đi từ câu hỏi đơn giản đến câu hỏi cần đo:
- Liệt kê các loại nội dung cần đưa ra ngoài, và loại nào cần kéo theo quan hệ như tác giả, danh mục, ảnh đại diện.
- Đếm số màn hình cần dữ liệu cùng lúc. Nếu mỗi màn hình chỉ cần một endpoint, REST đủ dùng.
- Kiểm đội đang biết gì. Đội đã quen GraphQL thì WPGraphQL bớt chi phí học. Đội chỉ quen REST thì bắt đầu từ endpoint có sẵn sẽ nhẹ hơn.
- Xem dự án đã chọn công cụ nào ở phía giao diện. Faust.js lấy dữ liệu qua WPGraphQL, nên dự án đã chọn Faust.js thường đi cùng WPGraphQL.
- Tìm nghiệp vụ không khớp mô hình nội dung của WordPress, như giỏ hàng hay đặt lịch. Với các thao tác này, endpoint riêng mô tả đúng việc cần làm thường rõ hơn việc cố ép vào bài viết.
- Đo trên site thật: số request, kích thước phản hồi và thời gian đến khi trang dùng được, trước khi chốt.
Site nhỏ, ít loại nội dung. Một site có bài, trang và vài taxonomy thường đủ với REST API. Không cần cài thêm, và các endpoint có sẵn đã trả đúng dữ liệu cho từng trang. Cái giá là đội phải nhớ endpoint nào trả gì. Với số endpoint ít, chi phí này nhỏ.
Đội đã biết GraphQL. Khi đội đã làm việc với GraphQL ở các phần khác của hệ thống, WPGraphQL giảm bớt một bộ khái niệm cần học. GraphiQL trong admin cũng giúp kiểm truy vấn trước khi đưa vào code, do đó vòng thử nghiệm ngắn.
Ứng dụng cần gom nhiều dữ liệu. Một trang chủ cần bài mới, sản phẩm nổi bật, tác giả và menu trong một lần tải thì truy vấn GraphQL gọn hơn nhiều request REST. Đây là tình huống mà chênh lệch số request trong ví dụ phía trên thể hiện rõ nhất.

Dự án đã dùng Faust.js. Tài liệu Faust.js (tra ngày 13/10/2026) mô tả việc lấy dữ liệu bằng GraphQL qua WPGraphQL, và yêu cầu cài đặt FaustWP cùng WPGraphQL trong bước chuẩn bị. Nếu dự án đã chọn Faust.js, WPGraphQL gần như là lựa chọn có sẵn. Tài liệu không nói Faust.js dùng được với REST API làm nguồn dữ liệu, vì vậy không viết điều đó trước khi thử.

Cần endpoint riêng cho nghiệp vụ. Giỏ hàng, đặt lịch hay tra cứu tồn kho là các thao tác có quy tắc riêng, không phải thao tác đọc hoặc ghi bài viết đơn thuần. Endpoint riêng mô tả đúng việc cần làm, dù viết bằng REST hay thêm vào schema GraphQL. Phần khó của giỏ hàng thường nằm ở phiên và xác thực giữa hai miền, vì vậy việc chọn công cụ chỉ là một phần. Bài WooCommerce headless: giỏ hàng và thanh toán cần hỏi gì liệt kê những câu cần trả lời trước khi làm.
Cách MONA chọn cho dự án headless của mình
Ngày 09/10/2026, MONA quyết định dùng REST API cho các dự án headless WordPress của mình. Lý do là lớp REST có sẵn trong WordPress, do đó không cần cài thêm, các endpoint riêng có thể viết theo đúng từng trang để một trang một lần gọi, và lớp bảo mật của site có thể khai báo chính xác các route được mở cho khách vãng lai. Đây là lựa chọn cho dự án của MONA, không phải chuẩn chung cho mọi site WordPress.
WPGraphQL được để dành cho khách đã dùng sẵn WPGraphQL hoặc Faust.js. Khi ứng dụng của khách đã có truy vấn GraphQL, việc viết lại sang REST không mang lại lợi ích rõ ràng, vì vậy MONA giữ GraphQL ở chỗ đó. Một số chi tiết triển khai vẫn đang chờ đội kỹ thuật xác nhận. Các con số về hiệu năng sẽ được đo trên dự án thật trước khi nói ra.
Nếu site đang có nhiều loại nội dung, cần nhiều màn hình gom dữ liệu, hoặc đã dùng Faust.js, phần chọn công cụ cần làm cùng lúc với thiết kế API. Muốn có một đánh giá cho site hiện có, xem dịch vụ lập trình website headless WordPress của MONA, hoặc gọi hotline 1900 636 648 để trao đổi trước khi chốt.
Hỏi đáp
WPGraphQL có làm site chậm hơn REST không?
Tài liệu WPGraphQL đưa một phép thử 100 bài: REST 335 KB và 7,91 giây, WPGraphQL 6,4 KB và 67 ms. Trang không nêu môi trường đo, và số này là của WPGraphQL. Cách đáng tin hơn là đo trên site thật, đếm số request, kích thước phản hồi và thời gian đến khi trang dùng được, với cả hai cách cùng điều kiện. Truy vấn GraphQL chọn quá nhiều quan hệ vẫn có thể nặng, vì vậy cần giới hạn số bản ghi và số trường ngay từ đầu.
Đội chỉ quen REST thì có cần học GraphQL không?
Nếu dự án chỉ cần vài endpoint và ít loại nội dung, không cần học GraphQL. Nếu chọn WPGraphQL, đội phải hiểu schema, cách truyền biến, connection và cursor. GraphiQL trong admin có nút Docs để tra type và field, vì vậy việc học có chỗ bám từ đầu. Thời gian học phụ thuộc vào từng người, và các nguồn đã đọc không nêu con số nào.
REST API có đủ cho một ứng dụng headless không?
Đủ, khi mỗi màn hình đọc được dữ liệu cần thiết từ một đến hai endpoint và số loại nội dung không nhiều. REST có sẵn trong WordPress, dùng được với mọi công cụ HTTP, và tài liệu chính thức mô tả nó là giao diện cho ứng dụng bên ngoài và app di động. Khi một màn hình phải gom nhiều đối tượng, số request hoặc trường thừa mới thành vấn đề thật.
Sau này chuyển từ REST sang WPGraphQL có khó không?
Dữ liệu trong WordPress không đổi khi đổi cách lấy dữ liệu, do đó phần khó nằm ở code gọi API phía ứng dụng. Chuyển sang GraphQL là viết lại các lời gọi và ánh xạ lại trường, và chiều ngược lại cũng vậy. Vì thế cần tách lớp gọi API khỏi giao diện từ đầu, để đổi công cụ chỉ ảnh hưởng một chỗ. Đây là suy luận từ cách hai công cụ hoạt động. Không có nguồn nào đã đọc đo chi phí chuyển đổi. Chuyển cả website sang headless còn kéo theo giữ link và SEO, xem bài về chuyển WordPress sang headless và giữ link.
WPGraphQL có mở dữ liệu ra cho mọi người không?
Truy vấn không đăng nhập chạy được với dữ liệu công khai, còn dữ liệu riêng tư như email hay bài nháp cần xác thực. Đây là cơ chế phân quyền. Có một điểm cần lưu ý: Faust.js yêu cầu bật Enable Public Introspection trong cài đặt WPGraphQL để tải schema. Khi bật, người ngoài cũng đọc được cấu trúc schema, do đó cần cân nhắc với site có dữ liệu nhạy cảm.




















































