N

Nokfa Docs

Current: framework-next.js

ไม่มีชื่อบทความ

🔐 ใช้ Next.js Server Actions / API Route บันทึกข้อมูลแทน Client เพื่อความปลอดภัย

🔎 ทำไมต้องย้าย logic ไปฝั่ง Server?

  • ซ่อนข้อมูลลับ: เช่น Service Account Key ที่ไม่ควรเปิดเผยใน bundle
  • 📦 ลดขนาด bundle ฝั่ง client: ไม่ต้องโหลด Firebase SDK ทั้งชุดใน browser
  • 🔐 ควบคุมความปลอดภัย: ป้องกันการแก้ไข payload โดยตรงจาก client

💡 ตัวอย่าง Server Action: app/actions/saveContact.js

// app/actions/saveContact.js
'use server';
import { adminDB } from '@/lib/firebaseAdmin';

export async function saveContact(formData) {
  try {
    const name = formData.get('name');
    const email = formData.get('email');
    const message = formData.get('message');

    if (!name || !email || !message) {
      throw new Error('ข้อมูลไม่ครบ');
    }

    await adminDB.collection('contacts').add({ name, email, message });
    return { success: true };
  } catch (err) {
    console.error('🔥 saveContact error:', err);
    return { success: false, message: err.message };
  }
}

🧾 เรียกใช้จาก client component

'use client';
import { useState } from 'react';
import { saveContact } from '@/app/actions/saveContact';

export default function ContactForm() {
  const [status, setStatus] = useState(null);

  async function handleSubmit(e) {
    e.preventDefault();
    const formData = new FormData(e.target);
    const res = await saveContact(formData);
    setStatus(res.success ? '✅ ส่งแล้ว' : `❌ ${res.message}`);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input name="name" required />
      <input name="email" type="email" required />
      <textarea name="message" required />
      <button type="submit">ส่ง</button>
      {status && <p>{status}</p>}
    </form>
  );
}

⚖️ เปรียบเทียบ: Client vs Server

ด้าน เขียนตรงจาก Client ใช้ Server Action / API
ความปลอดภัย 🔴 เสี่ยง key รั่ว, bypass rules ✅ ซ่อน credentials, มีการควบคุม
ขนาด bundle ใหญ่ขึ้น (Firebase SDK) เล็กลง
Latency เร็วกว่า (เรียกตรง) ช้ากว่านิด (ผ่าน server)
Validation ต้องทำฝั่ง client เอง ทำฝั่ง server ได้เลย

🛑 ทำความเข้าใจ Error Boundary

ในกรณี Server Action ล้มเหลว เช่น throw error หรือเชื่อม Firestore ไม่ได้:

  • ถ้าไม่ได้ catch → App อาจแสดงหน้า error หรือ fallback
  • ควรห่อ Server Action ด้วย try/catch แล้วส่งผลลัพธ์ { success: false, message } กลับมาให้ UI ตัดสินใจแสดงข้อความที่เหมาะสม
try {
  ... // save
} catch (err) {
  return { success: false, message: 'เกิดข้อผิดพลาด' }
}

✅ ช่วยให้ UX ดีกว่า redirect หรือ crash ทันที


แนวทางนี้เหมาะกับฟอร์มสำคัญ เช่น สมัครสมาชิก, แบบสอบถาม, คำติชม ที่ต้องป้องกันข้อมูลปลอมจาก client และไม่ควรโหลด Firebase SDK ฝั่งเบราว์เซอร์โดยไม่จำเป็น