← Tất cả bài viết

[ Blog ]

27 tháng 6, 2026

10 phút đọc

Headless WordPress + Next.js Cho Web Chuyển Động

Cách dựng website chuyển động đẳng cấp giải thưởng trên stack headless WordPress + Next.js với Three.js và GSAP — kiến trúc, caching, ngân sách hiệu năng và đánh đổi thật.

Next.jsWordPressHeadless CMSThree.jsGSAPKiến trúc
Headless WordPress + Next.js Cho Web Chuyển Động

Khi ra mắt Iventions — dự án đầu tiên tôi hợp tác cùng studio SERIOUS.BUSINESS và nhà thiết kế Huy Phan — bản brief đòi hỏi hai thứ thường "đá" nhau: một front end nghệ thuật, đầy 3D và chuyển động, đồng thời một CMS mà đội của khách có thể tự sửa không cần gọi developer. Lời giải là stack headless WordPress Next.js kết hợp Three.js và GSAP. Bài này là phần kỹ thuật đi kèm case study Iventions: các mảnh ghép lắp với nhau ra sao, làm sao giữ một CMS headless cho web chuyển động chạy mượt 60fps, và khi nào kiến trúc này là lựa chọn đúng thay vì thừa thãi.

Một lưu ý về công sức: ở Iventions tôi là developer. Phần thiết kế và art direction là của Huy Phan + SERIOUS.BUSINESS. Mọi thứ bên dưới là góc kỹ thuật của sự hợp tác đó.

Vì sao chọn headless WordPress + Next.js

Bản năng của nhiều creative developer là chọn một headless CMS bóng bẩy (Sanity, Contentful, Payload) rồi không bao giờ động vào WordPress nữa. Tôi hiểu mà. Nhưng trong dự án thật, yếu tố quyết định hiếm khi là gu của dev — mà là ai sẽ sửa nội dung sau khi ra mắt. Và cực kỳ nhiều đội marketing, agency, founder đang sống trong WordPress mỗi ngày.

"Headless" nghĩa là giữ WordPress thuần làm back end nội dung và bỏ luôn lớp theme PHP. Editor giữ lại dashboard, thư viện media, phân quyền và quy trình biên tập họ đã quen. Còn người dùng nhận một front end tùy biến dựng bằng Next.js/React — toàn quyền kiểm soát render, chuyển động và hiệu năng mà một theme truyền thống không bao giờ cho bạn.

Sự tách bạch đó chính là toàn bộ giá trị:

  • Editor giữ WordPress. Không phải đào tạo lại, phân quyền trưởng thành, hệ sinh thái plugin khổng lồ cho SEO, form, custom field.
  • Người dùng nhận front end nhanh, riêng biệt. React Server Components, caching chi tiết, WebGL được code-split, và một hệ thống motion bạn thật sự sở hữu.
  • Hai bên tách rời. Bạn có thể thiết kế lại front end mà không cần di trú nội dung, hoặc đổi CMS sau này mà không đụng vào lớp UI. Đó là phần "future-proof" — có thật, không phải khẩu hiệu.

Các mảnh ghép lắp lại: kiến trúc

Mô hình tư duy là một pipeline gọn. WordPress chỉ là API nội dung. Next.js là toàn bộ trải nghiệm. Three.js và GSAP là các lớp trình bày mà front end sở hữu trọn vẹn.

WordPress (headless)        Next.js front end            Trình duyệt
┌──────────────────┐        ┌────────────────────┐       ┌─────────────┐
│ Bài / trang      │        │ RSC: fetch + cache │       │ UI React    │
│ ACF custom field │ ──API─▶│ render HTML/JSON   │ ────▶ │ Motion GSAP │
│ Thư viện media   │ GraphQL│ revalidate (ISR)   │       │ 3D Three.js │
└──────────────────┘  /REST └────────────────────┘       └─────────────┘

Có hai cách đã được tài liệu hóa để đọc nội dung từ WordPress:

CáchLà gìHợp khi nào
WPGraphQLEndpoint GraphQL trên WP + ACFMuốn lấy đúng các field một component cần, trong một request
WP REST APIEndpoint /wp-json có sẵnMuốn không thêm plugin, URL đơn giản dễ cache

Với các build nặng chuyển động, tôi chọn WPGraphQL vì front end hướng component ăn rơ tự nhiên với query chính xác từng field — một block Hero xin tiêu đề, media và config 3D của nó trong một lượt, không thừa gì cả. Với site nhỏ thì REST API hoàn toàn ổn và bớt một thứ phải lo.

Trong App Router, việc fetch trở thành chuyện của server, nên thông tin đăng nhập WordPress và trọng lượng query không bao giờ chạm tới trình duyệt:

// app/lib/wp.ts — chỉ chạy trên server
export async function getPage(slug: string) {
  const res = await fetch(process.env.WP_GRAPHQL_URL!, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      query: /* GraphQL */ `
        query Page($slug: ID!) {
          page(id: $slug, idType: URI) {
            title
            blocks { __typename ...HeroFields ...GalleryFields }
          }
        }`,
      variables: { slug },
    }),
    // ISR: trả HTML đã cache, làm mới ngầm mỗi 60s
    next: { revalidate: 60, tags: [`page:${slug}`] },
  })
  if (!res.ok) throw new Error('WP fetch failed')
  return (await res.json()).data.page
}

Dòng next: { revalidate, tags } đó gánh phần nặng nhất. Tài liệu caching của Next.js cho phép bạn phục vụ một trang tĩnh hoàn toàn, cache trên CDN, mà vẫn làm mới nội dung — và một webhook WordPress gọi revalidateTag('page:home') khi đăng bài sẽ khiến thay đổi xuất hiện trong vài giây mà không cần deploy lại. Chính sự kết hợp này giúp site chạy nền WordPress đạt Core Web Vitals ngang với site tĩnh hoàn toàn.

Phần "modular, mở rộng được": block ánh xạ thành component

Câu "modular, mở rộng được, future-proof" không phải PR nếu bạn mô hình hóa nội dung thành block và ánh xạ mỗi loại block tới đúng một component React. Trong WordPress bạn định nghĩa flexible content (ACF Flexible Content hoặc Gutenberg block gốc); ở front end bạn render một registry:

const REGISTRY = {
  HeroBlock: Hero,
  GalleryBlock: Gallery,
  Scene3DBlock: Scene3D, // một section Three.js
} as const

export function Blocks({ blocks }: { blocks: Block[] }) {
  return blocks.map((b, i) => {
    const Comp = REGISTRY[b.__typename as keyof typeof REGISTRY]
    return Comp ? <Comp key={i} {...b} /> : null
  })
}

Giờ editor ghép trang từ những block họ hiểu, và mỗi block mang theo config motion và 3D của chính nó dưới dạng dữ liệu. Thêm một loại section mới một lần, là nó dùng được khắp nơi. Đây cũng là tinh thần hướng component tôi mô tả trong bài React Three Fiber cho người mới — một scene 3D chỉ là một component khác, chỉ là nó render ra canvas.

Giữ 3D + chuyển động ở 60fps trên nền CMS

Headless không khiến hiệu năng tự dưng miễn phí — nếu có thì 3D và motion được dàn dựng còn làm mọi thứ khó hơn. Những điều tôi không nhân nhượng:

  • Chỉ animate transformopacity. Chúng được GPU composite, bỏ qua layout/paint, để main thread rảnh cho scroll và hydrate dữ liệu.
  • Khởi tạo WebGL lười. Scene Three.js chỉ mount khi section gần viewport và dừng vòng render khi ra khỏi màn hình. Không đốt chu kỳ GPU cho thứ không ai nhìn.
  • Giới hạn device pixel ratioMath.min(devicePixelRatio, 2) — trên 2 bạn trả chi phí fill-rate khổng lồ cho khác biệt gần như không ai thấy.
  • Giữ dữ liệu ở server. Vì RSC fetch và render nội dung WordPress phía server, bundle client gọn hơn và chạm tới tương tác nhanh hơn.
const mm = gsap.matchMedia()
mm.add('(prefers-reduced-motion: no-preference)', () => {
  // toàn bộ choreography WebGL + GSAP nằm ở đây, mặc định tắt với người dùng reduced-motion
})

Tôi đi sâu vào ngân sách — LCP, INP, CLS dưới chuyển động nặng — trong Core Web Vitals cho web nhiều chuyển động, và phần lớp scroll trong cuộn mượt Next.js với GSAP & Lenis. Tóm lại: một front end WordPress nhanh chủ yếu là đừng đẩy việc xuống client — cache mạnh tay, hydrate ít, và chỉ render chuyển động khi nó xứng đáng.

Những phần khó và đánh đổi

Headless WordPress là công cụ đúng đắn nhiều hơn bạn tưởng, nhưng không miễn phí. Danh sách thành thật:

  • Fetch và cache dữ liệu mới là việc thật. Làm đúng revalidate và invalidate theo tag, nếu không bạn sẽ hoặc trả nội dung cũ, hoặc dội bom WordPress mỗi request. Đa số build headless hỏng ở đây.
  • Preview khó hơn WordPress nguyên khối. Bản nháp không còn "tự hiện ra". Bạn cần một route preview lấy nội dung không cache, có xác thực qua preview token của WordPress — lên kế hoạch từ ngày đầu, không thì editor sẽ bực.
  • Bạn vận hành hai hệ thống. Hosting WordPress deploy Next.js, hai bộ cập nhật, hai bề mặt bảo mật. Với một site brochure tí hon thì thừa — chỉ chọn khi có lượng biên tập thật hoặc front end quá tùy biến cho theme.
  • Plugin giả định có theme. Vài plugin WordPress chèn markup không bao giờ tới front end headless. Kiểm tra plugin SEO/form xem có hỗ trợ headless trước khi cam kết.

Khi nào nên chọn: một site flagship giàu nội dung, editor cập nhật thường xuyên, front end nghệ thuật nặng chuyển động — đúng kiểu Iventions. Khi nào thừa: một site đơn giản hiếm khi đổi nội dung, nơi build tĩnh từ Markdown hoặc CMS nhẹ ít phải bảo trì hơn.

Bằng chứng nó hoạt động

Iventions — dựng đúng trên stack headless WordPress + Next.js + Three.js + GSAP này — đoạt CSS Design Awards Website of the MonthAwwwards Site of the Day + Developer Award, trong khi đội biên tập quản lý nội dung bằng WordPress suốt quá trình. Toàn bộ câu chuyện dự án, điểm số và phân tích thủ pháp nằm trong case study Iventions, và thêm nhiều dự án đã ra mắt trong kho dự án.

Câu hỏi thường gặp

Headless WordPress có hợp với website nhiều chuyển động không?

Có — đây là một trong những lựa chọn hợp nhất. WordPress lo nội dung; Next.js sở hữu render, nên bạn toàn quyền với motion GSAP và 3D Three.js cộng thêm caching mạnh cho Core Web Vitals. Editor giữ CMS quen thuộc còn người dùng nhận front end tùy biến hoàn toàn.

Nên dùng WPGraphQL hay WordPress REST API với Next.js?

Dùng WPGraphQL khi muốn query chính xác từng field cho mỗi component (lý tưởng cho build dạng block, nặng chuyển động). Dùng REST API cho site đơn giản khi bớt một plugin và URL dễ cache quan trọng hơn độ chính xác query.

Headless WordPress có hại SEO hay hiệu năng không?

Không, nếu cache đúng. Với ISR của Next.js (revalidate + invalidate theo tag) bạn phục vụ HTML tĩnh cache trên CDN và làm mới khi đăng bài qua webhook — nhanh ngang site tĩnh hoàn toàn mà vẫn giữ trải nghiệm sửa bài của WordPress.

Khi nào headless WordPress là thừa?

Với site nhỏ hiếm khi đổi nội dung, chạy cả WordPress lẫn deploy Next.js là bảo trì nhiều hơn mức đáng. Chỉ chọn khi có lượng biên tập thật hoặc front end quá tùy biến và nhiều chuyển động cho một theme truyền thống.

Cùng dựng nhé

Nếu bạn cần một site headless WordPress + Next.js với Three.js và GSAP mà đội của bạn tự sửa được vẫn thắng về thủ pháp, đó chính là việc tôi làm với vai trò creative developer.


Viết bởi Hon Tran — creative developer, sáng lập hontran.dev, và giám khảo Awwwards. Hơn 11 năm xây dựng trải nghiệm web đoạt giải, ưu tiên hiệu năng (Next.js, GSAP, Three.js / WebGL) cho khách hàng toàn cầu. hontran.dev · Behance.