Headless WordPress เป็นแนวทางใหม่ในการใช้ WordPress ที่แยกเนื้อหา (CMS backend) ออกจากการแสดงผลหน้าเว็บ (frontend) แทนที่จะแสดงผลเนื้อหาผ่าน WordPress Theme แบบดั้งเดิม เราใช้ REST API หรือ GraphQL เพื่อให้ Next.js หรือ frontend framework อื่น ๆ ดึงเนื้อหามาแสดงผลแทน ระบบนี้เปิดโอกาสให้สร้างเว็บไซต์ที่มีประสิทธิภาพ ยืดหยุ่นได้มากกว่า และสามารถใช้ WordPress เป็น CMS สำหรับหลาย platform พร้อมกัน
การรวม Headless WordPress กับ Next.js บน Cloud VPS นั้นเป็นการสร้างสถาปัตยกรรมที่ทรงพลัง ซึ่งให้คุณควบคุมเต็มที่ทั้ง backend, frontend และ infrastructure ในบทความนี้ เราจะสำรวจวิธีการตั้งค่าระบบนี้ตั้งแต่การสร้าง WordPress API จนถึงการ Deploy Next.js บนเซิร์ฟเวอร์
ทำไมต้อง Headless WordPress?
การใช้ Headless Architecture มีข้อดีมากมาย เมื่อเทียบกับ WordPress ปกติ:
- ความเร็ว (Performance): Next.js สามารถแสดงผลหน้าแบบ Static Site Generation (SSG) หรือ Incremental Static Regeneration (ISR) ทำให้เว็บไซต์รวดเร็วมาก เพราะไม่ต้องประมวลผล PHP ทุกครั้งที่มีการเข้าชม
- ความยืดหยุ่น (Flexibility): คุณสามารถใช้ WordPress เป็น CMS ให้กับหลาย frontend ในเวลาเดียวกัน เช่น เว็บไซต์ React, Mobile App, หรือ Progressive Web App
- ความปลอดภัย (Security): WordPress backend ไม่ต้องเปิด direct access ต่อ public ลดการถูกโจมตี Plugin backdoor หรือ Theme malicious
- การ Scale และ Caching: Next.js เก่งในการ Cache ที่ layer application และ edge level (เช่น CDN) ลดการดึง API ที่ไม่จำเป็น
- SEO ที่ดี: Next.js มี built-in metadata API และ Server-Side Rendering ที่ช่วยให้ Search Engine เข้าใจเพจได้ดี
- Multi-platform CMS: ใช้ WordPress API เดียว เพื่อ supply content ให้ web, mobile, chatbot, หรือ API consumers อื่น
สถาปัตยกรรม Headless WordPress + Next.js
ในสถาปัตยกรรม Headless WordPress + Next.js บน Cloud VPS นั้น ระบบจะประกอบด้วย 3 ส่วนหลัก:
- WordPress Backend (CMS): ทำหน้าที่เป็น Content Management System ที่จัดเก็บ posts, pages, media, และ custom fields สามารถเขียน, แก้ไข, และจัดการเนื้อหาผ่าน WordPress Admin Panel ตามปกติ WordPress จะเปิด REST API endpoint (เช่น /wp-json/wp/v2/posts) เพื่อให้ frontend ดึงเนื้อหามาได้
- Next.js Frontend: เป็น Application ที่ดึง content จาก WordPress API และแสดงผลบนเบราว์เซอร์ มี Server Component สำหรับ Server-Side Rendering และ Static Generation สำหรับ Pre-render บาง page ล่วงหน้าในเวลา Build
- Cloud VPS Server: เป็นเซิร์ฟเวอร์เดียวที่ host ทั้ง WordPress (ด้วย PHP + MySQL) และ Next.js (ด้วย Node.js runtime) คุณควบคุมการ Config ทั้งหมด มี Nginx เป็น reverse proxy เพื่อ route traffic ไปยัง application ที่เหมาะสม
สถาปัตยกรรมนี้ใช้ Domain Strategy เช่น cms.yourdomain.com สำหรับ WordPress Admin และ API, yourdomain.com สำหรับ Next.js Frontend เพื่อให้แยกได้ชัดเจน
ติดตั้ง WordPress สำหรับ Headless CMS
ขั้นแรก ติดตั้ง WordPress ปกติบนเซิร์ฟเวอร์ของคุณ สามารถใช้ script อย่าง wp-cli หรือติดตั้งผ่าน Plesk/DirectAdmin ได้ตามปกติ
ขั้นตอนการตั้งค่า REST API:
- WordPress จะเปิด REST API โดยค่าเริ่มต้นตั้งแต่ version 4.7+ ไป เรียก endpoint เช่น https://cms.yourdomain.com/wp-json/wp/v2/posts
- แต่เราควรติดตั้ง WPGraphQL plugin เพื่อให้ client สามารถ query data ด้วย GraphQL ซึ่งเก่งกว่า REST ในเรื่องของการ specify field ที่ต้องการ ลด over-fetching
- ไปที่ WordPress Admin → Plugins → Add New → ค้นหา “WPGraphQL” และ install + activate
- หลังจากติดตั้ง GraphQL endpoint จะอยู่ที่ https://cms.yourdomain.com/graphql
สามารถทดสอบ GraphQL endpoint ด้วยการเปิด https://cms.yourdomain.com/graphql ในเบราว์เซอร์ จะเห็น GraphiQL IDE ที่สามารถเขียน query ได้
ตัวอย่าง GraphQL Query เพื่อดึงรายชื่อ Posts:
query GetPosts {
posts(first: 10) {
edges {
node {
id
title
slug
content
excerpt
date
featuredImage {
node {
sourceUrl
altText
}
}
}
}
}
}
สร้างโปรเจค Next.js
สร้าง Next.js project ด้วยคำสั่งต่อไปนี้:
npx create-next-app@latest my-headless-app --typescript --eslint --tailwind
เลือก options เช่น Use TypeScript = Yes, Use ESLint = Yes, Use Tailwind CSS = Yes เป็นต้น
ตั้งค่า Environment Variables: สร้างไฟล์ .env.local ที่ root ของ project:
NEXT_PUBLIC_WP_API_URL=https://cms.yourdomain.com
WP_API_KEY=your_optional_api_key_here
สร้าง WordPress API Helper: สร้างไฟล์ lib/wordpress.ts เพื่อ wrap การดึง data จาก WordPress:
const WP_API_URL = process.env.NEXT_PUBLIC_WP_API_URL;
export async function fetchWordPressAPI(query: string) {
const response = await fetch(`${WP_API_URL}/graphql`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ query }),
next: { revalidate: 3600 }, // ISR: revalidate every hour
});
if (!response.ok) {
throw new Error('Failed to fetch from WordPress');
}
const { data, errors } = await response.json();
if (errors) {
throw new Error(errors[0]?.message || 'GraphQL error');
}
return data;
}
export async function getPosts() {
const query = `
query {
posts(first: 10) {
edges {
node {
id
title
slug
content
excerpt
date
featuredImage {
node {
sourceUrl
altText
}
}
}
}
}
}
`;
const data = await fetchWordPressAPI(query);
return data.posts.edges.map((edge: any) => edge.node);
}
export async function getPostBySlug(slug: string) {
const query = `
query {
postBy(slug: "${slug}") {
id
title
slug
content
excerpt
date
featuredImage {
node {
sourceUrl
altText
}
}
}
}
`;
const data = await fetchWordPressAPI(query);
return data.postBy;
}
สร้าง Pages และ Components
Home Page (app/page.tsx):
import { getPosts } from '@/lib/wordpress';
import Link from 'next/link';
import Image from 'next/image';
export const revalidate = 3600; // ISR
export default async function Home() {
const posts = await getPosts();
return (
<main className="max-w-4xl mx-auto px-4 py-12">
<h1 className="text-4xl font-bold mb-8">Headless WordPress Blog</h1>
<div className="grid gap-6">
{posts.map((post: any) => (
<article key={post.id} className="border rounded-lg p-6 hover:shadow-lg transition">
{post.featuredImage?.node && (
<Image
src={post.featuredImage.node.sourceUrl}
alt={post.featuredImage.node.altText || post.title}
width={600}
height={400}
className="mb-4 rounded"
/>
)}
<h2 className="text-2xl font-bold mb-2">{post.title}</h2>
<p className="text-gray-600 mb-4 line-clamp-2" dangerouslySetInnerHTML={{ __html: post.excerpt }} />
<div className="text-sm text-gray-500 mb-4">
{new Date(post.date).toLocaleDateString('th-TH')}
</div>
<Link href={`/post/${post.slug}`} className="text-blue-600 hover:underline">
อ่านต่อ →
</Link>
</article>
))}
</div>
</main>
);
}
Single Post Page (app/post/[slug]/page.tsx):
import { getPostBySlug, getPosts } from '@/lib/wordpress';
import Image from 'next/image';
import { notFound } from 'next/navigation';
export const revalidate = 3600; // ISR
export async function generateStaticParams() {
const posts = await getPosts();
return posts.map((post: any) => ({
slug: post.slug,
}));
}
export async function generateMetadata({ params }: { params: { slug: string } }) {
const post = await getPostBySlug(params.slug);
if (!post) {
return {};
}
return {
title: post.title,
description: post.excerpt?.replace(/<[^>]*>/g, '') || '',
image: post.featuredImage?.node?.sourceUrl,
};
}
export default async function PostPage({ params }: { params: { slug: string } }) {
const post = await getPostBySlug(params.slug);
if (!post) {
notFound();
}
return (
<article className="max-w-2xl mx-auto px-4 py-12">
{post.featuredImage?.node && (
<Image
src={post.featuredImage.node.sourceUrl}
alt={post.featuredImage.node.altText || post.title}
width={800}
height={400}
className="mb-8 rounded"
/>
)}
<h1 className="text-4xl font-bold mb-4">{post.title}</h1>
<div className="text-gray-600 mb-8">
{new Date(post.date).toLocaleDateString('th-TH')}
</div>
<div className="prose max-w-none" dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
);
}
Deploy Next.js บน Cloud VPS
เมื่อ Next.js project พร้อมแล้ว ต่อมาให้อัพโหลดไปยัง Cloud VPS และ run application:
1. ติดตั้ง Node.js บนเซิร์ฟเวอร์:
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
2. Clone project หรือ upload ไปยัง เซิร์ฟเวอร์:
cd /var/www
git clone https://github.com/your-repo/my-headless-app.git
cd my-headless-app
npm install
3. Build Next.js Application:
npm run build
4. ติดตั้ง PM2 เพื่อ run application ในพื้นหลัง:
sudo npm install -g pm2
pm2 start npm --name "nextjs-app" -- start
pm2 save
pm2 startup
5. ตั้งค่า Nginx Reverse Proxy: สร้างไฟล์ /etc/nginx/sites-available/nextjs:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
server {
listen 80;
server_name cms.yourdomain.com;
root /var/www/wordpress;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
6. Enable Nginx Configuration และ test:
sudo ln -s /etc/nginx/sites-available/nextjs /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
7. Setup SSL Certificate ด้วย Certbot:
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com -d cms.yourdomain.com
การจัดการ Domain สำหรับ Headless Architecture
ในระบบ Headless WordPress + Next.js นั้น domain strategy มีความสำคัญ:
- yourdomain.com: ชี้ไปยัง Next.js Frontend (Port 3000 ผ่าน Nginx proxy)
- cms.yourdomain.com: ชี้ไปยัง WordPress CMS (Port 80/443 สำหรับ WordPress)
- api.yourdomain.com (optional): ถ้าต้องการแยก API endpoint ออกมา หรือใช้ GraphQL federation
ข้อดีของการแยก domain นี้:
- สามารถ scale WordPress backend และ Next.js frontend บนเซิร์ฟเวอร์คนละเครื่องได้ในอนาคต
- WordPress Admin ไม่ต้อง expose ต่อ public หากใช้ VPN หรือ private network
- Caching strategy ต่างกัน เช่น Next.js ใช้ ISR 1 ชั่วโมง แต่ WordPress มี cache plugin อื่น
- SEO: Frontend domain (yourdomain.com) เป็น primary site ที่ Google จะ crawl
Caching และ Performance Optimization
Headless WordPress + Next.js ให้โอกาสในการทำ caching ที่หลากหลาย:
- Static Site Generation (SSG): build time, next.js prerender ทุก page เป็น HTML static ความเร็วสูงสุด แต่ต้อง rebuild เมื่อ content เปลี่ยน
- Incremental Static Regeneration (ISR): หากเขียน revalidate = 3600 next.js จะ regenerate page โดยอัตโนมัติ ทุก 3600 วินาที (1 ชั่วโมง)
- WordPress Query Caching: ติดตั้ง Redis หรือ Memcached บน VPS เพื่อ cache WordPress query result ลด database load
- CDN Caching: ใส่ Cloudflare หรือ CDN service อื่นไว้หน้า yourdomain.com เพื่อ serve static asset และ cache HTTP response
- Browser Caching: ตั้ง Cache-Control header ใน Nginx เพื่อให้ browser cache asset นาน ๆ
ตัวอย่าง: ติดตั้ง Redis สำหรับ WordPress:
sudo apt-get install -y redis-server
sudo systemctl start redis-server
# ติดตั้ง Redis Object Cache Pro plugin ใน WordPress Admin
# หรือ Redis Cache plugin ฟรี
# หลังจากติดตั้ง WordPress จะ cache query โดยอัตโนมัติ
SEO และ Meta Tags
Next.js 13+ มี Metadata API ที่ช่วยให้ SEO ดี ไม่ต้องใช้ react-helmet อีกต่อไป:
// app/layout.tsx
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Headless WordPress Blog',
description: 'A modern blog powered by WordPress and Next.js',
openGraph: {
title: 'Headless WordPress Blog',
description: 'A modern blog powered by WordPress and Next.js',
url: 'https://yourdomain.com',
siteName: 'My Blog',
images: [
{
url: 'https://yourdomain.com/og-image.jpg',
width: 1200,
height: 630,
},
],
type: 'website',
},
twitter: {
card: 'summary_large_image',
title: 'Headless WordPress Blog',
description: 'A modern blog powered by WordPress and Next.js',
images: ['https://yourdomain.com/og-image.jpg'],
},
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="th">
<body>{children}</body>
</html>
);
}
อีกเทคนิค SEO ที่สำคัญคือ Sitemap และ robots.txt เพื่อให้ Search Engine crawl ได้ดี:
// app/sitemap.ts
import { getPosts } from '@/lib/wordpress';
export default async function sitemap() {
const posts = await getPosts();
const postUrls = posts.map((post: any) => ({
url: `https://yourdomain.com/post/${post.slug}`,
lastModified: new Date(post.date),
}));
return [
{
url: 'https://yourdomain.com',
lastModified: new Date(),
changeFrequency: 'daily',
priority: 1,
},
...postUrls,
];
}
สรุป
Headless WordPress + Next.js บน Cloud VPS เป็นสถาปัตยกรรมที่ทรงพลังสำหรับเว็บไซต์สมัยใหม่ คุณได้ประโยชน์จากความเก่งของ WordPress ในการจัดการเนื้อหา รวมกับความเร็วและความยืดหยุ่นของ Next.js สำหรับ frontend ระบบนี้สเกลได้ดี ปลอดภัย และ SEO-friendly
ประเด็นหลัก ได้แก่ การแยก WordPress เป็น headless CMS ผ่าน REST API หรือ GraphQL, สร้าง Next.js frontend ที่ fetch content จาก API, ใช้ ISR สำหรับ optimal caching, และ deploy ทั้ง WordPress และ Next.js บนเซิร์ฟเวอร์เดียว โดยใช้ Nginx เป็น reverse proxy เพื่อ route traffic ไปยังแต่ละ application ตามธรรมชาติ เมื่อเข้าใจแล้ว คุณสามารถขยายระบบไปยังหลาย frontend หรือ migration ไปยัง infrastructure ที่ซับซ้อนได้ในอนาคต
แนะนำบริการ DE
หากคุณต้องการ Deploy Headless WordPress + Next.js บนเซิร์ฟเวอร์ที่ควบคุมได้เต็มที่ Cloud VPS ของ DE เป็นตัวเลือกที่เหมาะสม เพราะคุณสามารถติดตั้ง Node.js, PM2, Nginx, Redis และจัดการทุกอย่างได้ตามต้องการ รองรับการ Scale เมื่อเว็บไซต์เติบโต และให้ความมั่นใจในด้าน uptime และ performance
สำหรับผู้ที่ต้องการใช้ WordPress แบบดั้งเดิมโดยไม่ต้องจัดการเซิร์ฟเวอร์เอง Cloud Hosting ของ DE ก็เป็นอีกทางเลือกที่สะดวกและพร้อมใช้งาน หากคุณต้องการเริ่มต้นด้วยความง่ายก่อน

