Qwik Resumability
Qwik Framework Resumability Hydration Serialization Lazy Loading TTI Performance SSR QwikCity Edge Rendering
| Framework | Loading Strategy | TTI | Bundle Size | Complexity |
|---|---|---|---|---|
| Qwik | Resumability (O(1)) | เร็วมาก | เล็กมาก (ตาม Interaction) | ปานกลาง |
| React (Next.js) | Hydration (O(n)) | ช้าตาม App Size | ใหญ่ (Full Bundle) | ต่ำ (คุ้นเคย) |
| Vue (Nuxt) | Hydration (O(n)) | ปานกลาง | ปานกลาง | ต่ำ |
| Astro | Islands (Partial) | เร็ว | เล็ก (Islands only) | ต่ำ |
| SolidJS | No VDOM Fine-grained | เร็ว | เล็ก | ปานกลาง |
ปัญหาและวิธีแก้
# === Qwik Common Issues & Fixes ===
# Issue 1: Serialization Error
# ❌ Wrong - Function in store
# const store = useStore({
# data: [],
# fetchData: async () => { ... } // Cannot serialize function!
# });
#
# ✅ Correct - Use separate handler
# const store = useStore({ data: [] });
# const fetchData = $(() => {
# // ... fetch logic
# store.data = await response.json();
# });
# Issue 2: useSignal vs React useState
# ❌ Wrong - React style
# const [count, setCount] = useState(0);
#
# ✅ Correct - Qwik style
# const count = useSignal(0);
# // Read: count.value
# // Write: count.value = count.value + 1;
# Issue 3: Event Handler without $
# ❌ Wrong
#
#
# ✅ Correct
#
# Issue 4: Third-party library not compatible
# ❌ Wrong - Direct import
# import Chart from 'chart.js';
#
# ✅ Correct - Use useVisibleTask$ for client-only
# useVisibleTask$(() => {
# const Chart = await import('chart.js');
# // Use Chart here
# });
from dataclasses import dataclass
@dataclass
class QwikIssue:
issue: str
symptom: str
cause: str
fix: str
prevention: str
issues = [
QwikIssue("Serialization Error",
"Error: Cannot serialize Function/Class/DOM",
"เก็บ Object ที่ Serialize ไม่ได้ใน State",
"ใช้ noSerialize() หรือย้ายไป useVisibleTask$",
"เก็บเฉพาะ Primitive, Array, Plain Object ใน State"),
QwikIssue("Closure Scope Issue",
"ตัวแปรใน Handler มีค่าเก่า/ผิด",
"Closure ไม่ถูก Capture ถูกต้องเมื่อ Resume",
"ใช้ useSignal/useStore แทน Local Variable",
"ใช้ Reactive State เสมอ ไม่ใช่ let/const"),
QwikIssue("SSR Mismatch",
"Hydration mismatch warning ใน Console",
"Server render HTML ไม่ตรงกับ Client",
"ใช้ useVisibleTask$ สำหรับ Client-only Logic",
"หลีกเลี่ยง window/document ใน Component Body"),
QwikIssue("Third-party Library Error",
"Library ใช้ window/document ตอน Import",
"Library ไม่รองรับ SSR/Serialization",
"Dynamic import ใน useVisibleTask$",
"ตรวจสอบ SSR Compatibility ก่อนใช้"),
QwikIssue("Slow Initial Load",
"Prefetch มากเกินไป หรือ Bundle ใหญ่",
"ไม่ใช้ component$ ครอบ หรือ Import ทั้ง Library",
"ใช้ component$ ทุกที่ ใช้ Dynamic Import",
"ดู Qwik Insights วิเคราะห์ Bundle"),
]
print("=== Common Issues ===")
for i in issues:
print(f"\n [{i.issue}]")
print(f" Symptom: {i.symptom}")
print(f" Cause: {i.cause}")
print(f" Fix: {i.fix}")
print(f" Prevention: {i.prevention}")
Performance Optimization
# === Qwik Performance Checklist ===
@dataclass
class PerfTip:
area: str
action: str
impact: str
code_hint: str
tips = [
PerfTip("Component Lazy Loading",
"ใช้ component$ ห่อทุก Component",
"ลด Initial Bundle ลงมาก โหลดเมื่อจำเป็น",
"export const MyComponent = component$(() => { ... })"),
PerfTip("Event Handler Code Split",
"ใช้ $ suffix ทุก Handler",
"Handler Code แยก Chunk โหลดเมื่อ Interact",
"onClick$={() => { ... }} ไม่ใช่ onClick={() => { ... }}"),
PerfTip("Data Fetching",
"ใช้ routeLoader$ ใน QwikCity แทน useTask$",
"Data พร้อมตอน SSR ไม่ต้อง Client Fetch",
"export const useData = routeLoader$(async () => { ... })"),
PerfTip("Image Optimization",
"ใช้ @unpic/qwik สำหรับ Responsive Image",
"ลด Image Size Lazy Load Format Optimization",
"npm add @unpic/qwik"),
PerfTip("Prefetch Strategy",
"ใช้ PrefetchServiceWorker ใน entry.ssr.tsx",
"Prefetch เฉพาะ Module ที่น่าจะใช้",
" ใน entry.ssr.tsx"),
PerfTip("Edge Rendering",
"Deploy บน Cloudflare Workers / Deno Deploy",
"Low Latency ใกล้ User ทุกที่ในโลก",
"npm run qwik add cloudflare-pages"),
]
print("=== Performance Tips ===")
for t in tips:
print(f" [{t.area}] {t.action}")
print(f" Impact: {t.impact}")
print(f" Code: {t.code_hint}")
Debugging
# === Debugging Qwik Apps ===
@dataclass
class DebugTool:
tool: str
purpose: str
how_to_use: str
tip: str
tools = [
DebugTool("Qwik Devtools",
"ตรวจสอบ Serialization Graph, Component Tree",
"ติดตั้ง Chrome Extension Qwik Devtools",
"ดู Serialize Tab หา Object ที่ Serialize ไม่ได้"),
DebugTool("Console Error Messages",
"Qwik แสดง Error ชัดเจน บอก Property ที่มีปัญหา",
"เปิด Browser Console ดู Error Detail",
"อ่าน Error Message ให้ละเอียด มัก Point ถูกจุด"),
DebugTool("Qwik Insights (Build Analysis)",
"วิเคราะห์ Bundle Size แต่ละ Chunk",
"npm run build -- --analyze",
"หา Module ที่ใหญ่ผิดปกติ ลด Import"),
DebugTool("Network Tab",
"ดู Lazy Loaded Chunks เมื่อ User Interact",
"Chrome DevTools → Network Tab → JS Filter",
"Chunk ที่โหลดควรเล็ก ถ้าใหญ่ = ลด Code"),
DebugTool("Lighthouse",
"วัด Performance Score TTI LCP CLS",
"Chrome DevTools → Lighthouse Tab",
"Qwik ควรได้ Performance 95+ Score"),
]
print("=== Debug Tools ===")
for t in tools:
print(f" [{t.tool}] {t.purpose}")
print(f" How: {t.how_to_use}")
print(f" Tip: {t.tip}")
เคล็ดลับ
- component$: ห่อทุก Component ด้วย component$ เสมอ
- $: ใช้ $ suffix ทุก Handler และ Task
- State: เก็บเฉพาะ Serializable Data ใน useSignal/useStore
- Client-only: ใช้ useVisibleTask$ สำหรับ Client-only Code
- routeLoader$: ใช้ routeLoader$ สำหรับ Data Fetching ใน QwikCity
Qwik Resumability คืออะไร
Framework ใช้ Resumability แทน Hydration Serialize State ใน HTML Lazy Load เมื่อ Interact TTI O(1) JSX QwikCity SSR Edge
ปัญหาที่พบบ่อยมีอะไร
Serialization Error Closure Scope SSR Mismatch Third-party Library useSignal Event $ suffix Routing CSS-in-JS
แก้ Serialization Error อย่างไร
useSignal useStore Primitive noSerialize() useVisibleTask$ Client-only Console Error Qwik Devtools Serialization Graph
Optimize Performance อย่างไร
component$ $ suffix routeLoader$ Dynamic Import Image @unpic/qwik PrefetchServiceWorker Edge Cloudflare Qwik Insights Lighthouse 95+
สรุป
Qwik Resumability Troubleshooting Serialization Closure SSR useSignal component$ $ suffix routeLoader$ Edge Rendering Performance Lazy Loading
