ai

WordPress Headless กับ Distributed System —

WordPress Headless กับ Distributed System —

WordPress Headless CMS

WordPress Headless กับ Distributed System —

WordPress Headless คือการใช้ WordPress เป็น Content Management System ที่ให้ข้อมูลผ่าน API เท่านั้น ไม่ใช้ Theme แสดงผล Frontend สร้างด้วย Framework สมัยใหม่เช่น Next.js, Nuxt.js หรือ Astro ทำให้เว็บเร็วขึ้นมากและ Scale ได้ดี

ในระบบ Distributed กระจาย WordPress ข้าม Regions, Database Replication, CDN, Redis Cache ทำให้ระบบ High Availability และเร็วสำหรับผู้ใช้ทั่วโลก

WordPress Headless Setup

=== WordPress Headless Setup ===

1. ติดตั้ง WordPress + WPGraphQL

docker-compose.yml

version: '3.8'

services:

wordpress:

image: wordpress:6.5-php8.3-apache

ports:

  • "8080:80"

environment:

WORDPRESS_DB_HOST: mysql

WORDPRESS_DB_NAME: wordpress

WORDPRESS_DB_USER: wp

WORDPRESS_DB_PASSWORD: SecurePass123

WORDPRESS_CONFIG_EXTRA: |

define('WP_HOME', 'https://cms.example.com');

define('WP_SITEURL', 'https://cms.example.com');

define('HEADLESS_MODE', true);

define('GRAPHQL_JWT_AUTH_SECRET_KEY', 'your-secret-key');

volumes:

  • wp-data:/var/www/html

depends_on:

  • mysql
  • redis

mysql:

image: mysql:8.0

environment:

WordPress Headless กับ Distributed System —

MYSQL_DATABASE: wordpress

MYSQL_USER: wp

MYSQL_PASSWORD: SecurePass123

MYSQL_ROOT_PASSWORD: RootPass123

volumes:

  • db-data:/var/lib/mysql

command: >

--default-authentication-plugin=mysql_native_password

--innodb-buffer-pool-size=256M

--max-connections=200

redis:

image: redis:7-alpine

command: redis-server --maxmemory 128mb --maxmemory-policy allkeys-lru

volumes:

wp-data:

db-data:

2. ติดตั้ง Plugins

เนื้อหาเกี่ยวข้อง — TTS Coqui Batch Processing Pipeline

wp plugin install wp-graphql --activate

wp plugin install wp-graphql-jwt-authentication --activate

wp plugin install redis-cache --activate

3. Headless Mode (functions.php)

Redirect frontend to API

add_action('template_redirect', function() {

if (!defined('HEADLESS_MODE') || !HEADLESS_MODE) return;

if (is_admin() || wp_doing_ajax() || wp_doing_cron()) return;

แนะนำเพิ่มเติม — แหล่งความรู้ Forex iCafeForex

if (strpos($_SERVER['REQUEST_URI'], '/graphql') !== false) return;

if (strpos($_SERVER['REQUEST_URI'], '/wp-json') !== false) return;

wp_redirect('https://www.example.com', 301);

exit;

});

4. CORS Headers

Allow frontend domain

add_action('init', function() {

header('Access-Control-Allow-Origin: https://www.example.com');

header('Access-Control-Allow-Methods: GET, POST, OPTIONS');

header('Access-Control-Allow-Headers: Content-Type, Authorization');

});

5. ทดสอบ GraphQL

curl -X POST https://cms.example.com/graphql \

-H "Content-Type: application/json" \

-d '{"query": "{ posts { nodes { title slug excerpt date } } }"}'

echo "WordPress Headless CMS configured"

echo " REST API: https://cms.example.com/wp-json/wp/v2/"

echo " GraphQL: https://cms.example.com/graphql"

Next.js Frontend สำหรับ Headless WordPress

// === Next.js Frontend สำหรับ Headless WordPress ===
// npx create-next-app@latest frontend --typescript --tailwind

// lib/wordpress.ts — WordPress API Client
const API_URL = process.env.WORDPRESS_GRAPHQL_URL || "https://cms.example.com/graphql";

interface Post {
  title: string;
  slug: string;
  excerpt: string;
  date: string;
  content: string;
  featuredImage?: {
    node: { sourceUrl: string; altText: string };
  };
  categories: { nodes: { name: string; slug: string }[] };
}

async function fetchGraphQL(query: string, variables?: Record<string, any>) {
  const res = await fetch(API_URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ query, variables }),
    next: { revalidate: 60 }, // ISR: Revalidate ทุก 60 วินาที
  });

  if (!res.ok) throw new Error(`GraphQL error: `);
  const json = await res.json();
  if (json.errors) throw new Error(json.errors[0].message);
  return json.data;
}

// ดึง Posts ทั้งหมด
export async function getPosts(first = 20): Promise<Post[]> {
  const data = await fetchGraphQL(`
    query GetPosts($first: Int!) {
      posts(first: $first, where: { status: PUBLISH }) {
        nodes {
          title
          slug
          excerpt
          date
          featuredImage {
            node { sourceUrl altText }
          }
          categories {
            nodes { name slug }
          }
        }
      }
    }
  `, { first });
  return data.posts.nodes;
}

// ดึง Post เฉพาะ
export async function getPost(slug: string): Promise<Post> {
  const data = await fetchGraphQL(`
    query GetPost($slug: ID!) {
      post(id: $slug, idType: SLUG) {
        title
        slug
        content
        date
        excerpt
        featuredImage {
          node { sourceUrl altText }
        }
        categories {
          nodes { name slug }
        }
      }
    }
  `, { slug });
  return data.post;
}

// ดึง Slugs สำหรับ Static Generation
export async function getAllSlugs(): Promise<string[]> {
  const data = await fetchGraphQL(`
    query GetSlugs {
      posts(first: 1000, where: { status: PUBLISH }) {
        nodes { slug }
      }
    }
  `);
  return data.posts.nodes.map((p: { slug: string }) => p.slug);
}

// === app/page.tsx — Homepage ===
// export default async function Home() {
//   const posts = await getPosts(12);
//   return (
//     <main className="max-w-6xl mx-auto px-4 py-8">
//       <h1 className="text-4xl font-bold mb-8">Blog</h1>
//       <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
//         {posts.map((post) => (
//           <PostCard key={post.slug} post={post} />
//         ))}
//       </div>
//     </main>
//   );
// }

// === app/blog/[slug]/page.tsx — Single Post ===
// export async function generateStaticParams() {
//   const slugs = await getAllSlugs();
//   return slugs.map((slug) => ({ slug }));
// }
//
// export default async function BlogPost({ params }) {
//   const post = await getPost(params.slug);
//   return (
//     <article className="max-w-3xl mx-auto px-4 py-8">
//       <h1 className="text-4xl font-bold">{post.title}</h1>
//       <div dangerouslySetInnerHTML={{ __html: post.content }} />
//     </article>
//   );
// }

console.log("Next.js Headless WordPress Frontend");
console.log("  ISR: Revalidate every 60 seconds");
console.log("  SSG: Pre-render all posts at build time");

Distributed Architecture

=== Distributed WordPress Architecture ===

เนื้อหาเกี่ยวข้อง — อ่านต่อ: Fivetran Connector Career Development IT

1. MySQL Replication (Primary-Replica)

Primary: Write Queries (INSERT, UPDATE, DELETE)

Replica: Read Queries (SELECT) — สำหรับ GraphQL Queries

my.cnf (Primary)

[mysqld]

server-id = 1

log-bin = mysql-bin

binlog-format = ROW

gtid-mode = ON

enforce-gtid-consistency = ON

my.cnf (Replica)

[mysqld]

server-id = 2

relay-log = mysql-relay

read-only = ON

แนะนำเพิ่มเติม — คู่มือเทรดจาก SiamCafeBook

gtid-mode = ON

enforce-gtid-consistency = ON

2. Redis Cluster สำหรับ Object Cache

redis-cluster.conf

cluster-enabled yes

cluster-config-file nodes.conf

cluster-node-timeout 5000

appendonly yes

redis-cli --cluster create \

node1:6379 node2:6379 node3:6379 \

node4:6379 node5:6379 node6:6379 \

--cluster-replicas 1

3. S3-compatible Object Storage สำหรับ Media

เนื้อหาเกี่ยวข้อง — บทความที่เกี่ยวข้อง: stable diffusion install

wp-config.php

define('AS3CF_SETTINGS', serialize(array(

'provider' => 'aws',

'access-key-id' => 'YOUR_KEY',

'secret-access-key' => 'YOUR_SECRET',

'bucket' => 'wp-media-bucket',

'region' => 'ap-southeast-1',

'copy-to-s3' => true,

'serve-from-s3' => true,

'remove-local-file' => true,

)));

4. Nginx Load Balancer

upstream wordpress {

least_conn;

server wp-node1:8080 weight=5;

server wp-node2:8080 weight=5;

server wp-node3:8080 weight=3; # Smaller instance

}

server {

listen 443 ssl http2;

server_name cms.example.com;

# GraphQL Endpoint — Cache 60s

location /graphql {

proxy_pass http://wordpress;

proxy_cache wp_cache;

proxy_cache_valid 200 60s;

proxy_cache_key "$request_body";

proxy_cache_methods POST;

เนื้อหาเกี่ยวข้อง — แนะนำให้อ่าน chatgpt prompt engineering

add_header X-Cache $upstream_cache_status;

}

# REST API — Cache 60s

location /wp-json/ {

proxy_pass http://wordpress;

proxy_cache wp_cache;

proxy_cache_valid 200 60s;

}

# Admin — No Cache

location /wp-admin {

proxy_pass http://wordpress;

}

}

5. CDN สำหรับ Frontend

Vercel, Cloudflare Pages, Netlify

Frontend Deploy เป็น Static/ISR บน CDN

ผู้ใช้โหลดจาก Edge ใกล้ที่สุด

WordPress API ถูกเรียกตอน Revalidation เท่านั้น

print("Distributed WordPress Architecture:")

print(" WordPress (3 nodes) -> Nginx LB")

print(" MySQL Primary -> 2 Replicas")

print(" Redis Cluster (6 nodes)")

print(" S3 Object Storage for Media")

print(" CDN for Frontend (Next.js ISR)")

print(" GraphQL Cache at Nginx (60s TTL)")

Best Practices

  • ISR (Incremental Static Regeneration): ใช้ ISR ใน Next.js Revalidate ทุก 60 วินาที ไม่ต้อง Rebuild ทั้งเว็บ
  • GraphQL over REST: ใช้ WPGraphQL ดึงข้อมูลตรงตามต้องการ ลด Over-fetching
  • Cache GraphQL: Cache GraphQL Responses ที่ Nginx หรือ CDN ลด Load บน WordPress
  • Database Replication: แยก Read/Write ส่ง GraphQL Queries ไป Replica
  • Media on S3: เก็บ Media Files บน S3 ส่งผ่าน CDN ไม่ใช้ Disk บน WordPress
  • Webhook Revalidation: ใช้ Webhook เมื่อ Publish/Update Post เรียก Revalidation บน Next.js

WordPress Headless คืออะไร

ใช้ WordPress เป็น Backend CMS ไม่ใช้ Theme แสดงผล ใช้ REST API หรือ WPGraphQL ส่งข้อมูลไป Frontend ที่สร้างด้วย Next.js Vue Nuxt แยก Backend กับ Frontend

XM Legend · เทรดเดอร์ & ผู้สอน Forex 13 ปี

ผู้ก่อตั้ง SiamCafe ตั้งแต่ปี 1997 · เทรดเดอร์สาย Forex มากกว่า 13 ปี ได้รับการยกย่องเป็น XM Legend · แบ่งปันความรู้ Forex, ไอที, AI และการเทรด จากประสบการณ์จริงในตลาดจริง