SSR dan SSG
Server-Side Rendering dan Static Site Generation menggunakan Node.js tanpa framework
SSR (Server-Side Rendering) dan SSG (Static Site Generation) adalah dua pendekatan untuk menghasilkan HTML yang berbeda. Keduanya bertujuan meningkatkan performa dan SEO dibandingkan CSR (Client-Side Rendering) murni.
Perbedaan Fundamental
| Aspek | SSR | SSG | CSR |
|---|---|---|---|
| Waktu render | Setiap request | Build time | Browser |
| HTML awal | Lengkap dari server | Lengkap dari file/CDN | Kosong, diisi JS |
| SEO | Baik | Terbaik | Buruk tanpa prerender |
| Dynamic data | Real-time | Perlu rebuild | Real-time |
| Server load | Tinggi | Rendah | Rendah |
SSR dengan Node.js Murni
SSR menghasilkan HTML di server untuk setiap request.
const http = require("http");
function renderPage(title, content) {
return `<!DOCTYPE html>
<html>
<head><title>${title}</title></head>
<body>
<h1>${title}</h1>
<main>${content}</main>
<script src="/app.js"></script>
</body>
</html>`;
}
const server = http.createServer((req, res) => {
if (req.url === "/") {
// Data bisa dari database, API, atau mana saja
const posts = [
{ id: 1, title: "Hello" },
{ id: 2, title: "World" },
];
const content = posts
.map((p) => `<article><h2>${p.title}</h2></article>`)
.join("");
res.writeHead(200, { "Content-Type": "text/html" });
res.end(renderPage("Blog", content));
}
});
server.listen(3000);Hydration
HTML yang di-render server perlu "dihidupkan" kembali di browser agar interaktif. Proses ini disebut hydration.
<!-- HTML dari server -->
<div id="root"><button>Click me</button></div>
<!-- JS di browser meng-attach event listener ke DOM yang sudah ada -->
<script>
document.querySelector("button").addEventListener("click", () => {
alert("clicked!");
});
</script>Di framework modern seperti React, hydration dilakukan oleh ReactDOM.hydrateRoot().
SSG dengan Node.js Murni
SSG menghasilkan file HTML saat build time.
const fs = require("fs");
const path = require("path");
function generatePage(route, content) {
const html = `<!DOCTYPE html>
<html>
<head><title>${route}</title></head>
<body>${content}</body>
</html>`;
const dir = path.join(__dirname, "dist", route);
fs.mkdirSync(dir, { recursive: true });
fs.writeFileSync(path.join(dir, "index.html"), html);
}
// Build time: generate semua halaman
const pages = [
{ route: "", content: "<h1>Home</h1>" },
{ route: "about", content: "<h1>About</h1>" },
{ route: "blog/hello", content: "<h1>Hello World</h1>" },
];
pages.forEach((p) => generatePage(p.route, p.content));Hasil: folder dist/ dengan struktur seperti static file yang bisa di-serve oleh web server biasa.
Incremental Static Regeneration (ISR)
Kombinasi SSR dan SSG: halaman di-generate di build time, tapi dapat di-revalidate secara periodis atau on-demand tanpa full rebuild.
const cache = new Map();
const REVALIDATE_SECONDS = 60;
function getCachedPage(route, generator) {
const cached = cache.get(route);
const now = Date.now();
if (cached && now - cached.time < REVALIDATE_SECONDS * 1000) {
return cached.html;
}
const html = generator();
cache.set(route, { html, time: now });
return html;
}Kapan Menggunakan Apa?
- SSG — Blog, landing page, dokumentasi. Konten jarang berubah.
- SSR — E-commerce, dashboard, sosial media. Konten personal atau sering berubah.
- CSR — SPA internal, tool admin, aplikasi yang jarang butuh SEO.
- ISR — Kombinasi yang ideal: performa SSG + freshness SSR.
Praktik Terbaik
- Gunakan CDN untuk SSG output agar edge caching maksimal
- Streaming SSR untuk Time to First Byte (TTFB) lebih cepat
- Prioritaskan critical CSS di
<head>HTML yang di-render server - Lazy load non-critical JS untuk mengurangi blocking