Qwik has a unique approach to Server-Side Rendering (SSR) and Client-Side Rendering (CSR), with its core innovation being the "Resumability" concept that enables seamless SSR/CSR switching.
1. Qwik's SSR Architecture
Server-Side Rendering Flow
- Execute components on server: Execute Qwik components on the server to generate HTML
- Serialize state: Serialize component state and execution context into HTML
- Inject metadata: Inject metadata needed for resumption (event handler references, state info, etc.) into HTML
- Send HTML: Send complete HTML to the client
SSR Advantages
- Fast first screen load: Server returns complete HTML directly, no need to wait for JavaScript execution
- SEO friendly: Search engines can directly crawl page content
- Reduced client burden: Most work is done on the server
2. Qwik's CSR Architecture
Client-Side Resumption Flow
- HTML parsing: Browser parses HTML returned by server
- State restoration: Deserialize state and execution context from HTML
- On-demand loading: Only load JavaScript code needed for user interaction
- Event binding: Bind events directly through HTML attributes, no hydration needed
CSR Features
- Zero hydration: No traditional hydration process needed
- On-demand execution: Only execute relevant code when user interacts
- Fine-grained updates: Only update changed DOM nodes
3. Seamless Integration of SSR and CSR
Resumability
Qwik's core innovation is resumability, which allows applications to seamlessly switch between server and client:
tsx// Server-side execution export const App = component$(() => { const count = useSignal(0); return ( <div> <p>Count: {count.value}</p> <button onClick$={() => count.value++}> Increment </button> </div> ); });
- When rendering on server,
countvalue is serialized to HTML - When loading on client,
countvalue is directly restored from HTML - When clicking button, only load and execute
onClick$handler function
Code Splitting Strategy
Qwik compiler automatically splits code into multiple small chunks:
- Component code: Each component split independently
- Event handlers: Each event handler function split independently
- State update logic: Fine-grained state update code
4. Qwik City Routing and SSR
Qwik City is Qwik's full-stack framework, providing powerful routing and SSR capabilities:
Route Loaders
tsx// routes/index.tsx import { component$ } from '@builder.io/qwik'; import { routeLoader$ } from '@builder.io/qwik-city'; export const useProductData = routeLoader$(async ({ params, url, env }) => { const response = await fetch(`https://api.example.com/products/${params.id}`); return response.json(); }); export default component$(() => { const product = useProductData(); return ( <div> <h1>{product.value.name}</h1> <p>{product.value.description}</p> </div> ); });
Server Actions
tsximport { action$ } from '@builder.io/qwik-city'; export const useAddToCart = action$(async (data, { requestEvent }) => { const session = requestEvent.sharedMap.get('session'); // Execute server-side logic return { success: true }; });
5. Performance Optimization
First Screen Performance
- Zero JavaScript startup cost: No need to download and execute large amounts of JavaScript
- Instant interaction: HTML contains all necessary information, can interact immediately
- Progressive enhancement: Gradually load more features as user interacts
Runtime Performance
- Fine-grained updates: Only update changed DOM nodes
- On-demand loading: Only load code users actually need
- Smart caching: Automatically cache loaded code
6. Comparison with Traditional Frameworks
| Feature | Qwik | React | Vue |
|---|---|---|---|
| SSR support | Native, zero hydration | Requires Next.js, etc. | Requires Nuxt.js, etc. |
| Hydration process | Not needed | Required | Required |
| First screen JS | Near zero | Large | Medium |
| Code splitting | Automatic fine-grained | Manual configuration | Manual configuration |
| State restoration | Automatic | Manual handling required | Manual handling required |
7. Best Practices
SSR Optimization
- Use
routeLoader$to fetch data on server - Avoid executing large amounts of computation on server
- Set reasonable caching strategies
CSR Optimization
- Use
useVisibleTask$for client-specific logic - Avoid loading unnecessary code on first screen
- Use
useResource$for asynchronous data
Hybrid Strategy
- Use SSR for static content
- Use CSR for dynamic content
- Adjust strategy based on user device capabilities
Summary: Qwik achieves seamless integration of SSR and CSR through the resumability concept, providing excellent performance and developer experience. Developers can focus on business logic without worrying about low-level rendering optimization details.