SiamCafe.net Blog
Technology

Qwik Resumability Interview Preparation

qwik resumability interview preparation
Qwik Resumability Interview Preparation | SiamCafe Blog
2025-09-12· อ. บอม — SiamCafe.net· 9,798 คำ

Qwik Resumability

Qwik Resumability Interview Framework Hydration Lazy Loading Serialization QwikCity Performance Lighthouse TTI E-commerce Production

FeatureQwikReact/Next.jsAstroSolidJS
RenderingResumabilityHydrationIslandsFine-grained
Initial JS~1KB~80-200KB~0KB static~10-30KB
TTINear instant1-5s (app size)Near instantFast
State MgmtuseSignal useStoreuseState ReduxFramework-specificcreateSignal
RoutingQwikCityNext.js App RouterFile-basedSolidStart
Learningปานกลางง่าย (mature)ง่ายปานกลาง
EcosystemGrowingใหญ่มากGrowingเล็ก

Core Concepts

# === Qwik Core Concepts ===

# Component with $ (Lazy Loading Boundary)
# import { component$, useSignal } from '@builder.io/qwik';
#
# export const Counter = component$(() => {
#   const count = useSignal(0);
#
#   return (
#     <div>
#       <p>Count: {count.value}</p>
#       <button onClick$={() => count.value++}>
#         Increment
#       </button>
#     </div>
#   );
# });

# useSignal — Reactive primitive
# const name = useSignal('');  // Simple reactive value
# name.value = 'Qwik';        // Update triggers re-render

# useStore — Reactive object
# const state = useStore({
#   items: [],
#   loading: false,
#   error: null,
# });
# state.loading = true;  // Deep reactive

# useTask$ — Side effects (like useEffect)
# useTask$(({ track }) => {
#   track(() => count.value);
#   console.log('Count changed:', count.value);
# });

# useVisibleTask$ — Client-only task
# useVisibleTask$(() => {
#   // Runs only in browser, when component is visible
#   const chart = new Chart(canvasRef.value, config);
# });

from dataclasses import dataclass

@dataclass
class QwikConcept:
    concept: str
    syntax: str
    react_equivalent: str
    purpose: str
    lazy: bool

concepts = [
    QwikConcept("component$", "component$(() => JSX)", "function Component()", "Define component with lazy boundary", True),
    QwikConcept("useSignal", "useSignal(initial)", "useState(initial)", "Simple reactive value", False),
    QwikConcept("useStore", "useStore({...})", "useState({...}) or Redux", "Reactive object/array", False),
    QwikConcept("onClick$", "onClick$={() => ...}", "onClick={() => ...}", "Event handler with lazy loading", True),
    QwikConcept("useTask$", "useTask$(({track}) => ...)", "useEffect(() => ...)", "Side effect on server+client", True),
    QwikConcept("useVisibleTask$", "useVisibleTask$(() => ...)", "useEffect (client only)", "Client-only when visible", True),
    QwikConcept("routeLoader$", "routeLoader$(() => fetch)", "getServerSideProps", "Server data loading", True),
    QwikConcept("routeAction$", "routeAction$(() => ...)", "Server Actions", "Form handling server-side", True),
]

print("=== Qwik Concepts ===")
for c in concepts:
    lazy = "LAZY $" if c.lazy else "Eager"
    print(f"  [{c.concept}] {lazy}")
    print(f"    Syntax: {c.syntax}")
    print(f"    React: {c.react_equivalent}")
    print(f"    Purpose: {c.purpose}")

Interview Questions

# === Qwik Interview Questions ===

@dataclass
class InterviewQ:
    question: str
    difficulty: str
    key_points: str
    common_mistake: str

questions = [
    InterviewQ("Resumability คืออะไร ต่างจาก Hydration อย่างไร",
        "Medium",
        "Serialize state+listeners ใน HTML, ไม่ re-execute, O(1) vs O(n)",
        "บอกว่า Qwik ไม่ใช้ JS เลย (ใช้แต่ lazy load)"),
    InterviewQ("$ suffix ใน Qwik หมายความว่าอะไร",
        "Medium",
        "Lazy loading boundary, optimizer แยกเป็น chunk, โหลดเมื่อต้องใช้",
        "คิดว่าเป็นแค่ naming convention ไม่ใช่ functional"),
    InterviewQ("useSignal กับ useStore ต่างกันอย่างไร",
        "Easy",
        "Signal = primitive value, Store = reactive object/array, Store deep reactive",
        "ใช้ Store สำหรับทุกอย่าง ทั้งที่ Signal เพียงพอ"),
    InterviewQ("อธิบาย Serialization ใน Qwik",
        "Hard",
        "State serialized เป็น JSON ใน HTML attribute, ไม่ต้อง hydrate, resume ได้ทันที",
        "ไม่รู้ว่า Closure ก็ serialize ได้ด้วย"),
    InterviewQ("QwikCity routeLoader$ ทำงานอย่างไร",
        "Medium",
        "Run on server, return data, available in component via useRouteLoader$",
        "สับสนกับ routeAction$ ซึ่งสำหรับ mutation"),
    InterviewQ("Qwik เหมาะกับ Use Case ไหน",
        "Easy",
        "E-commerce, content sites, apps ที่ต้อง fast TTI, SEO important",
        "บอกว่าเหมาะทุกอย่าง ไม่พูดถึง trade-offs เช่น ecosystem เล็ก"),
    InterviewQ("Trade-offs ของ Qwik มีอะไร",
        "Hard",
        "Ecosystem เล็ก, mental model ใหม่, $ syntax, community เล็กกว่า React",
        "บอกว่าไม่มี trade-offs"),
]

print("=== Interview Questions ===")
for q in questions:
    print(f"  [{q.difficulty}] {q.question}")
    print(f"    Key: {q.key_points}")
    print(f"    Avoid: {q.common_mistake}")

Performance Comparison

# === Performance Benchmark ===

@dataclass
class PerfBenchmark:
    framework: str
    initial_js_kb: float
    tti_ms: int
    lcp_ms: int
    lighthouse: int
    build_time_s: int

benchmarks = [
    PerfBenchmark("Qwik + QwikCity", 1.2, 200, 800, 99, 15),
    PerfBenchmark("Next.js (App Router)", 85, 1800, 1200, 88, 25),
    PerfBenchmark("Astro (Static)", 0, 150, 600, 100, 10),
    PerfBenchmark("Astro + React Islands", 25, 800, 900, 95, 12),
    PerfBenchmark("SolidStart", 12, 500, 850, 96, 8),
    PerfBenchmark("Nuxt 3", 65, 1500, 1100, 90, 20),
]

print("=== Performance Comparison ===")
for b in benchmarks:
    print(f"  [{b.framework}]")
    print(f"    JS: {b.initial_js_kb}KB | TTI: {b.tti_ms}ms | LCP: {b.lcp_ms}ms")
    print(f"    Lighthouse: {b.lighthouse} | Build: {b.build_time_s}s")

# Interview Prep Checklist
prep = {
    "Concept": "Resumability, $, Serialization, Signals, QwikCity",
    "Code": "Build a Todo app or E-commerce page with Qwik",
    "Compare": "Qwik vs React/Next.js — pros, cons, trade-offs",
    "Performance": "Run Lighthouse, compare scores, explain why",
    "Deploy": "Deploy to Vercel or Cloudflare, show live demo",
    "Questions": "Prepare 5 questions to ask interviewer about their Qwik usage",
}

print(f"\n\nInterview Prep Checklist:")
for k, v in prep.items():
    print(f"  [{k}]: {v}")

เคล็ดลับ

Qwik Resumability คืออะไร

Frontend Framework Resumability แทน Hydration Serialize State HTML User Interact โหลด JS เฉพาะส่วน Initial Load เร็ว Lighthouse E-commerce Content

Resumability ต่างจาก Hydration อย่างไร

Hydration โหลด JS ทั้งหมด Re-execute Component O(n) Resumability Serialize State Listener HTML ไม่ Re-execute โหลดเฉพาะส่วน O(1)

QwikCity คืออะไร

Meta-framework Qwik เหมือน Next.js File-based Routing Layout routeLoader$ Data routeAction$ Form Middleware SSR SSG Hybrid Vercel Cloudflare

เตรียมสัมภาษณ์ Qwik อย่างไร

Resumability vs Hydration $ suffix Lazy Boundary Serialization QwikCity Demo Project Lighthouse Compare React Trade-offs Ecosystem

สรุป

Qwik Resumability Interview Hydration Lazy Loading $ Serialization QwikCity routeLoader$ Performance Lighthouse E-commerce Production Deployment

📖 บทความที่เกี่ยวข้อง

Whisper Speech Interview Preparationอ่านบทความ → Vue Nuxt Server Interview Preparationอ่านบทความ → Qwik Resumability Internal Developer Platformอ่านบทความ → Qwik Resumability Infrastructure as Codeอ่านบทความ → Qwik Resumability Best Practices ที่ต้องรู้อ่านบทความ →

📚 ดูบทความทั้งหมด →