Angular Universal: Server-Side Rendering (SSR)

Server-Side Rendering (SSR) คือการให้ Server สร้าง HTML ที่สมบูรณ์ก่อนส่งให้ Browser ช่วยแก้ปัญหา Client-Side Rendering (CSR) ที่มักมี First Load ช้าและอาจทำให้ Search Engine เห็นเนื้อหาไม่ครบ

Timeline/ประวัติศาสตร์

%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#fabd2f", "primaryTextColor": "#282828", "primaryBorderColor": "#b57614", "lineColor": "#7c6f64", "secondaryColor": "#83a598", "tertiaryColor": "#b8bb26", "background": "#fbf1c7", "mainBkg": "#ebdbb2", "fontFamily": "Tahoma, sans-serif"}}}%%
flowchart LR
  subgraph Era1["ยุค CSR / Client Render"]
    A["SPA Bundle
Browser render ทั้งหมด"] end subgraph Era2["ยุค Angular Universal / SSR"] B["Server Render HTML
ส่ง HTML พร้อมอ่าน"] C["SEO + First Load
ดีขึ้น"] end subgraph Era3["ยุค Hydration / Modern SSR"] D["Hydration
Client รับช่วงต่อ"] E["Transfer State
ส่งข้อมูลจาก server ไป client"] end A --> B --> C --> D --> E

แนวคิดสำคัญ

ตารางเปรียบเทียบ CSR และ SSR

หัวข้อ CSR SSR
HTML แรก มักว่างหรือมี shell มีเนื้อหาพร้อมอ่าน
SEO อาจมีข้อจำกัด ดีขึ้น
First Load ช้าถ้า bundle ใหญ่ เห็นเนื้อหาเร็วขึ้น
Server Cost ต่ำกว่า สูงกว่า
Complexity ง่ายกว่า ต้องระวัง browser-only API

Mermaid Diagram: SSR Flow

%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#fabd2f", "primaryTextColor": "#282828", "primaryBorderColor": "#b57614", "lineColor": "#7c6f64", "secondaryColor": "#83a598", "tertiaryColor": "#b8bb26", "background": "#fbf1c7", "mainBkg": "#ebdbb2", "fontFamily": "Tahoma, sans-serif"}}}%%
flowchart TD
  A["Browser Request
ขอหน้าเว็บ"] --> B["Express SSR Server
server.ts"] B --> C["Angular Render
สร้าง HTML"] C --> D["HTML Response
ส่งหน้าเต็ม"] D --> E["Browser Hydration
รับช่วงต่อ"] E --> F["Interactive App
ใช้งานได้"]

Code Example

# เพิ่ม SSR ให้ Angular project
ng add @angular/ssr

# build แบบ production
ng build --configuration production

# รัน server-side rendered app
npm run serve:ssr:your-project-name

# ตัวอย่างการใช้งาน:
# เปิดหน้าเว็บแล้ว View Source ควรเห็น HTML ที่มีเนื้อหาจริง
// platform-check.component.ts
// แยก logic ตาม platform เพื่อเลี่ยงการใช้ window บน server
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
import { Component, Inject, PLATFORM_ID } from '@angular/core';

@Component({
  selector: 'app-platform-check',
  template: `<p>{{ message }}</p>`
})
export class PlatformCheckComponent {
  message = '';

  constructor(@Inject(PLATFORM_ID) platformId: object) {
    if (isPlatformBrowser(platformId)) {
      this.message = 'ทำงานบน Browser';
    }

    if (isPlatformServer(platformId)) {
      this.message = 'Render จาก Server';
    }
  }
}

// ตัวอย่างการใช้งาน:
// ใช้เมื่อต้องเขียน logic ที่อ้างถึง window, document หรือ localStorage

วิดีโอแนะนำ

กิจกรรมท้ายบท

  1. เพิ่ม SSR ให้โปรเจกต์ Angular
  2. ตรวจ View Source ก่อนและหลังเปิด SSR
  3. ทดลองใช้ isPlatformBrowser() กับ logic ที่อ่าน window
  4. อธิบายว่า Hydration ช่วยให้งานฝั่ง client ต่อจาก server render ได้อย่างไร

กลับสัปดาห์ที่ 13