1. Pengenalan Netlify
Netlify adalah platform hosting dan deployment modern yang dirancang untuk web developer. Dengan Netlify, Anda bisa meng-deploy website dan web applications dari Git repository dalam hitungan detik, mendapatkan CDN global otomatis, SSL/HTTPS, serverless functions, form handling, dan fitur-fitur lain yang biasanya memerlukan konfigurasi server yang rumit.
Netlify mempopulerkan konsep JAMstack (JavaScript, APIs, Markup) β arsitektur web yang mengandalkan prerendering dan menyajikan konten statis dari CDN, dengan dynamic functionality ditangani oleh serverless functions atau APIs. Pendekatan ini menghasilkan website yang sangat cepat, aman, dan mudah di-scale.
Mengapa Netlify?
| Keunggulan | Penjelasan |
|---|---|
| Git-based Deploy | Deploy otomatis setiap kali push ke Git β zero configuration |
| Global CDN | Content didistribusikan ke edge nodes di seluruh dunia |
| Free SSL | HTTPS otomatis dengan Let's Encrypt untuk semua domain |
| Serverless Functions | Backend logic tanpa server β support Node.js, Go, Rust |
| Form Handling | Terima form submissions tanpa backend β langsung di Netlify |
| Identity | Authentication built-in β sign up, login, roles, JWT |
| Edge Functions | Custom logic di edge nodes β ultra-low latency |
| Branch Deploys | Deploy setiap branch ke URL terpisah untuk testing |
| Deploy Previews | Preview deploy untuk setiap Pull Request |
| Split Testing | A/B testing dengan traffic splitting antar branches |
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β NETLIFY PLATFORM β β β β ββββββββββββ ββββββββββββββββββββββββββββββββ β β β Git Repo ββββββββββΊβ Build Pipeline β β β β (GitHub, β β - Install dependencies β β β β GitLab, β β - Run build command β β β β Bitbucket) β - Generate static files β β β ββββββββββββ ββββββββββββββββ¬ββββββββββββββββ β β β β β βΌ β β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β β β GLOBAL CDN β β β β ββββββββββββ ββββββββββββ ββββββββββββ β β β β β US Edge β β EU Edge β β Asia Edgeβ β β β β ββββββββββββ ββββββββββββ ββββββββββββ β β β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β β β β Features: β β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββ β β β Serverless β β Forms β β Identity β β β β Functions β β (built-in) β β (auth) β β β ββββββββββββββββ€ ββββββββββββββββ€ ββββββββββββββββββββ€ β β β Edge β β Redirects β β Split β β β β Functions β β & Headers β β Testing β β β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββ β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Perbandingan dengan Platform Lain
| Fitur | Netlify | Vercel | Cloudflare Pages |
|---|---|---|---|
| Free Tier | 100 GB bandwidth/bln | 100 GB bandwidth/bln | Unlimited bandwidth |
| Build Minutes | 300 min/bln | 6000 min/bln | 500 min/bln |
| Functions | Serverless + Edge | Serverless + Edge | Workers |
| Forms | β Built-in | β Tidak | β Tidak |
| Identity | β Built-in | β Tidak | β Tidak |
| Frameworks | Semua (React, Vue, dll) | Next.js focused | Semua |
2. Memulai dengan Netlify
Prerequisites
# Install Netlify CLI npm install -g netlify-cli # Atau gunakan npx (tanpa install global) npx netlify-cli --version # Login ke Netlify netlify login # Inisialisasi project baru (di dalam project directory) netlify init # Atau clone starter template git clone https://github.com/netlify-templates/eleventy-base-blog my-blog cd my-blog npm install
Inisialisasi Project
# Inisialisasi Netlify di project yang sudah ada
cd my-project
netlify init
# Pilihan:
# β Create & configure a new site
# β Link to an existing site
# Pilih team, masukkan site name
# Atau manual: buat file netlify.toml
cat > netlify.toml << 'EOF'
[build]
command = "npm run build"
publish = "dist"
functions = "netlify/functions"
[build.environment]
NODE_VERSION = "20"
[[redirects]]
from = "/api/*"
to = "/.netlify/functions/:splat"
status = 200
[[headers]]
for = "/*"
[headers.values]
X-Frame-Options = "DENY"
X-Content-Type-Options = "nosniff"
EOF
3. Deploy Website
Manual Deploy
# Deploy directory langsung
netlify deploy --prod --dir=./dist
# Deploy dengan draft (preview URL)
netlify deploy --dir=./build
# Output: Deploy draft URL: https://6654abc123--my-site.netlify.app
# Setelah puas dengan preview, promote ke production
netlify deploy --prod --dir=./build
# Deploy single page app (SPA)
netlify deploy --prod --dir=./build --functions=./netlify/functions
# Lihat deploy history
netlify api listSiteDeploys --data '{ "site_id": "my-site-id" }'
netlify.toml Lengkap
# netlify.toml β Konfigurasi lengkap Netlify
# ====================================
# BUILD SETTINGS
# ====================================
[build]
command = "npm run build"
publish = "dist"
functions = "netlify/functions"
[build.environment]
NODE_VERSION = "20"
NODE_ENV = "production"
# Variabel dari Netlify UI akan di-merge otomatis
# ====================================
# CONTEXT-SPECIFIC BUILDS
# ====================================
[context.production]
command = "npm run build:prod"
[context.deploy-preview]
command = "npm run build:staging"
[context.branch-deploy]
command = "npm run build:dev"
# ====================================
# REDIRECTS
# ====================================
# SPA fallback
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
# API proxy ke functions
[[redirects]]
from = "/api/users"
to = "/.netlify/functions/users"
status = 200
# Wildcard API proxy
[[redirects]]
from = "/api/*"
to = "/.netlify/functions/:splat"
status = 200
# Redirect www ke non-www
[[redirects]]
from = "https://www.mydomain.com/*"
to = "https://mydomain.com/:splat"
status = 301
force = true
# Redirect old pages
[[redirects]]
from = "/old-page"
to = "/new-page"
status = 301
# ====================================
# HEADERS
# ====================================
[[headers]]
for = "/*"
[headers.values]
X-Frame-Options = "DENY"
X-Content-Type-Options = "nosniff"
X-XSS-Protection = "1; mode=block"
Referrer-Policy = "strict-origin-when-cross-origin"
Permissions-Policy = "camera=(), microphone=(), geolocation=()"
Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
# Cache static assets
[[headers]]
for = "/assets/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"
# Cache images
[[headers]]
for = "/images/*"
[headers.values]
Cache-Control = "public, max-age=86400"
# ====================================
# PLUGINS
# ====================================
[[plugins]]
package = "@netlify/plugin-lighthouse"
[[plugins]]
package = "netlify-plugin-submit-sitemap"
[plugins.inputs]
baseUrl = "https://mydomain.com"
sitemapPath = "/sitemap.xml"
4. Git-based Deployment
Continuous Deployment
Fitur paling powerful dari Netlify adalah Git-based continuous deployment. Setiap kali Anda push ke Git repository, Netlify otomatis build dan deploy. Untuk setiap Pull Request, Netlify membuat Deploy Preview dengan URL unik yang bisa Anda review sebelum merge.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β GIT-BASED DEPLOYMENT FLOW β β β β Developer β β ββββββββ β β git push main ββββββββββββββββββββββββββββββ β β git push feature/a βββββββββββββββββββ β β β PR: feature/a βββββββββββββββ β β β β β β β β β βΌ βΌ βΌ β β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β β β NETLIFY BUILD PIPELINE β β β β β β β β Trigger: Branch push / PR β β β β 1. Clone repo β β β β 2. Install dependencies (npm install) β β β β 3. Run build (npm run build) β β β β 4. Process redirects & headers β β β β 5. Deploy to CDN β β β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β β β β β βββββββββββββββββββΌββββββββββββββββββ β β βΌ βΌ βΌ β β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β β β Deploy Previewβ β Branch Deployβ β Production β β β β β β β β β β β β PR#42-preview β β feature/a β β main β β β β .netlify.app β β .netlify.app β β .netlify.app β β β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β β Review dulu! Testing staging Live production β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Branch Deploy & Deploy Previews
Branch Deploy URLs: main β my-site.netlify.app (production) staging β staging--my-site.netlify.app (branch deploy) dev β dev--my-site.netlify.app (branch deploy) feature/blog β feature-blog--my-site.netlify.app (branch deploy) Deploy Preview URLs (dari Pull Request): PR #1 β deploy-preview-1--my-site.netlify.app PR #2 β deploy-preview-2--my-site.netlify.app PR #3 β deploy-preview-3--my-site.netlify.app Split Testing: main (50%) + redesign (50%) Netlify CDN otomatis split traffic antar branches Berguna untuk A/B testing di production
Gunakan Deploy Preview untuk testing sebelum merge ke main. Anda bisa share URL preview ke team untuk review. Branch deploy juga berguna untuk environment staging β deploy branch staging ke URL terpisah sebelum promote ke production.
5. Serverless Functions
Netlify Functions memungkinkan Anda menjalankan backend code tanpa server. Functions berjalan di AWS Lambda di bawah permukaan, tetapi Netlify menyederhanakan deployment dan integrasi.
Membuat Function
// netlify/functions/hello.js
// Function sederhana β dipanggil via /.netlify/functions/hello
export default async (request, context) => {
const { name = 'World' } = await request.json().catch(() => ({}));
return new Response(
JSON.stringify({
message: `Hello, ${name}!`,
timestamp: new Date().toISOString(),
method: request.method,
url: request.url,
headers: Object.fromEntries(request.headers),
}),
{
status: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
}
);
};
export const config = {
path: '/api/hello', // Custom URL path
};
Function dengan Database
// netlify/functions/users.js
// CRUD API untuk users dengan PostgreSQL
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL);
export default async (request, context) => {
try {
switch (request.method) {
case 'GET': {
const users = await sql`SELECT * FROM users ORDER BY created_at DESC`;
return Response.json({ users });
}
case 'POST': {
const { name, email } = await request.json();
const [user] = await sql`
INSERT INTO users (name, email) VALUES (${name}, ${email})
RETURNING *
`;
return Response.json({ user }, { status: 201 });
}
case 'PUT': {
const { id, name, email } = await request.json();
const [updated] = await sql`
UPDATE users SET name = ${name}, email = ${email}
WHERE id = ${id} RETURNING *
`;
return Response.json({ user: updated });
}
case 'DELETE': {
const { searchParams } = new URL(request.url);
const id = searchParams.get('id');
await sql`DELETE FROM users WHERE id = ${id}`;
return Response.json({ deleted: true });
}
default:
return Response.json({ error: 'Method not allowed' }, { status: 405 });
}
} catch (error) {
return Response.json({ error: error.message }, { status: 500 });
}
};
export const config = {
path: '/api/users',
};
Scheduled Functions
// netlify/functions/cleanup.js
// Scheduled function β berjalan otomatis berdasarkan cron
export default async (request, context) => {
console.log('Running scheduled cleanup...');
// Cleanup old data
const result = await cleanupOldRecords();
return new Response(
JSON.stringify({
message: 'Cleanup completed',
deletedRecords: result.count,
})
);
};
export const config = {
schedule: '@daily', // Berjalan setiap hari
// Atau: '0 */6 * * *' (setiap 6 jam)
// Atau: '@hourly' (setiap jam)
};
Trigger Functions
// netlify/functions/deploy-notification.js
// Triggered setelah deploy selesai
export default async (request, context) => {
const { site_id, deploy_id, state } = await request.json();
if (state === 'ready') {
console.log(`Deploy ${deploy_id} is ready!`);
// Kirim notifikasi, update database, dll.
}
return new Response('OK');
};
export const config = {
path: '/.netlify/functions/deploy-notification',
};
Memanggil Functions dari Client
// Dari frontend (React, Vue, vanilla JS, dll.)
// Simple GET request
const response = await fetch('/.netlify/functions/hello');
const data = await response.json();
console.log(data.message); // "Hello, World!"
// POST request dengan body
const result = await fetch('/.netlify/functions/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Budi', email: 'budi@email.com' }),
});
const newUser = await result.json();
// Dengan custom path (jika config.path diset)
const res = await fetch('/api/users');
const users = await res.json();
// Error handling
try {
const res = await fetch('/.netlify/functions/hello', {
method: 'POST',
body: JSON.stringify({ name: 'Netlify' }),
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
} catch (err) {
console.error('Function call failed:', err);
}
6. Form Handling
Netlify Forms memungkinkan Anda menerima form submissions tanpa backend. Cukup tambahkan atribut data-netlify="true" pada HTML form, dan Netlify akan otomatis menangkap submissions. Data bisa dilihat di Netlify dashboard dan dikirim ke email/Webhook.
HTML Form dengan Netlify
<!-- Form kontak sederhana -->
<form name="contact" method="POST" data-netlify="true" netlify-honeypot="bot-field">
<!-- Honeypot field untuk spam protection (hidden) -->
<p class="hidden" style="display:none">
<label>Jangan isi ini: <input name="bot-field"></label>
</p>
<!-- Fields -->
<label for="name">Nama:</label>
<input type="text" id="name" name="name" required>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<label for="subject">Subjek:</label>
<select id="subject" name="subject">
<option value="general">Pertanyaan Umum</option>
<option value="support">Dukungan Teknis</option>
<option value="feedback">Feedback</option>
</select>
<label for="message">Pesan:</label>
<textarea id="message" name="message" rows="5" required></textarea>
<!-- File upload (optional, max 1 file per submission) -->
<label for="attachment">Lampiran (opsional):</label>
<input type="file" id="attachment" name="attachment" accept=".pdf,.png,.jpg">
<button type="submit">Kirim Pesan</button>
</form>
<!-- Redirect ke halaman thank-you setelah submit -->
<!-- Bisa juga via netlify.toml: -->
<!--
[[redirects]]
from = "/contact"
to = "/thank-you"
status = 302
-->
JavaScript Form Submission (AJAX)
// Submit form via JavaScript (tanpa redirect)
const form = document.getElementById('contactForm');
form.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(form);
try {
const response = await fetch('/', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams(formData).toString(),
});
if (response.ok) {
alert('Pesan berhasil dikirim!');
form.reset();
} else {
throw new Error('Gagal mengirim pesan');
}
} catch (error) {
alert('Error: ' + error.message);
}
});
7. Identity & Authentication
Netlify Identity menyediakan authentication yang terintegrasi langsung dengan site Anda. Support email/password signup, login via provider (Google, GitHub, GitLab, Bitbucket), JWT tokens, dan role-based access control.
Mengaktifkan Identity
# Aktifkan Identity via CLI netlify sites:update --site-id my-site-id --with-identity # Atau aktifkan via Netlify Dashboard: # Site Settings β Identity β Enable Identity # Set registration: # - Open: Anyone can sign up # - Invite only: Admin harus mengundang user
Menggunakan Identity di Frontend
<!-- Tambahkan Netlify Identity Widget -->
<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
<!-- Tombol login/logout (Netlify auto-inject jika diperlukan) -->
<div data-netlify-identity-button>
Login with Netlify Identity
</div>
<script>
// Initialize Identity
netlifyIdentity.init({
APIUrl: 'https://my-site.netlify.app/.netlify/identity',
locale: 'en',
});
// Event listeners
netlifyIdentity.on('init', (user) => {
console.log('User init:', user);
});
netlifyIdentity.on('login', (user) => {
console.log('User logged in:', user);
console.log('JWT Token:', user.token.access_token);
netlifyIdentity.close();
});
netlifyIdentity.on('logout', () => {
console.log('User logged out');
window.location.href = '/';
});
netlifyIdentity.on('error', (err) => {
console.error('Identity error:', err);
});
// Programmatic login
function login(email, password) {
return netlifyIdentity.login(email, password);
}
// Get current user
const currentUser = netlifyIdentity.currentUser();
if (currentUser) {
console.log('Logged in as:', currentUser.email);
console.log('Roles:', currentUser.app_metadata.roles);
}
</script>
Protecting Pages & Functions
# Protect pages dengan JWT Gatekeeper # Tambahkan di netlify.toml: # Protect /admin pages [[redirects]] from = "/admin/*" to = "/.netlify/functions/auth-check" status = 200 # Protect /dashboard pages [[redirects]] from = "/dashboard/*" to = "/.netlify/functions/auth-check" status = 200
8. Edge Functions
Netlify Edge Functions berjalan di edge nodes (dekat dengan user), menggunakan Deno runtime. Edge Functions cocok untuk: A/B testing, personalization, geolocation-based content, authentication middleware, dan rewrites/redirects yang kompleks.
Membuat Edge Function
// netlify/edge-functions/geo-redirect.js
// Redirect user berdasarkan lokasi geografis
export default async (request, context) => {
const country = context.geo.country?.code || 'US';
const city = context.geo.city || 'Unknown';
console.log(`Visitor from: ${city}, ${country}`);
// Redirect ke halaman bahasa yang sesuai
const localeMap = {
ID: '/id',
JP: '/ja',
KR: '/ko',
DE: '/de',
FR: '/fr',
};
const locale = localeMap[country] || '/en';
// Hanya redirect jika di halaman utama
const url = new URL(request.url);
if (url.pathname === '/') {
return new Response(null, {
status: 302,
headers: { Location: locale },
});
}
// Tambahkan header geo info
const response = await context.next();
response.headers.set('X-Country', country);
response.headers.set('X-City', city);
return response;
};
export const config = {
path: '/*',
};
Edge Function: A/B Testing
// netlify/edge-functions/ab-test.js
// A/B testing di edge β ultra fast, zero flicker
const COOKIE_NAME = 'ab-test-variant';
export default async (request, context) => {
// Cek apakah user sudah punya variant
const existingVariant = context.cookies.get(COOKIE_NAME);
if (existingVariant) {
// User sudah di-assign variant
return context.next();
}
// Assign variant baru (50:50 split)
const variant = Math.random() < 0.5 ? 'A' : 'B';
// Set cookie agar konsisten
context.cookies.set({
name: COOKIE_NAME,
value: variant,
httpOnly: true,
secure: true,
sameSite: 'Lax',
path: '/',
maxAge: 60 * 60 * 24 * 30, // 30 hari
});
// Tambahkan header untuk analytics
const response = await context.next();
response.headers.set('X-AB-Test', variant);
return response;
};
export const config = {
path: '/',
};
Edge Function: Response Transform
// netlify/edge-functions/personalize.js
// Inject personalized content ke halaman
export default async (request, context) => {
const response = await context.next();
const contentType = response.headers.get('content-type');
// Hanya proses HTML pages
if (!contentType?.includes('text/html')) {
return response;
}
// Transform HTML response
return new HTMLRewriter()
.on('[data-personalize]', {
element(element) {
const key = element.getAttribute('data-personalize');
if (key === 'greeting') {
const country = context.geo.country?.name || 'World';
element.setInnerContent(`Welcome, visitor from ${country}!`);
}
},
})
.transform(response);
};
export const config = {
path: '/',
};
9. Custom Domains & HTTPS
# Tambah custom domain via CLI netlify domains:add mydomain.com # DNS Configuration: # Type | Name | Value # A | @ | 75.2.60.5 # CNAME | www | my-site.netlify.app # Tambah subdomain netlify domains:add app.mydomain.com # Cek DNS status netlify domains:list # HTTPS akan otomatis dikonfigurasi oleh Netlify # Let's Encrypt certificate di-provision otomatis # Force HTTPS (redirect HTTP ke HTTPS) # Di Netlify Dashboard: Site Settings β HTTPS β Force HTTPS # DNSSEC juga didukung # Di Netlify Dashboard: Domain Settings β Enable DNSSEC
10. Environment Variables
# Set environment variable netlify env:set DATABASE_URL "postgres://user:pass@host/db" # Set untuk context tertentu netlify env:set API_KEY "prod-key-123" --context production netlify env:set API_KEY "dev-key-456" --context dev # Set untuk branch tertentu netlify env:set FEATURE_FLAG "true" --scope functions --context branch:staging # List semua environment variables netlify env:list # Import dari .env file netlify env:import .env.production # Delete environment variable netlify env:unset DATABASE_URL # Akses di functions # process.env.DATABASE_URL tersedia secara otomatis # Akses di build # Tersedia sebagai environment variable saat build # Scopes: # - builds: Tersedia saat build # - functions: Tersedia di serverless functions # - runtime: Tersedia di edge functions # - post_processing: Tersedia saat post-processing
11. Best Practices
| Best Practice | Detail |
|---|---|
| Gunakan netlify.toml | Simpan semua konfigurasi dalam version control β redirects, headers, build settings |
| Deploy Preview | Review setiap PR dengan preview sebelum merge ke main |
| Cache headers | Set cache headers yang tepat untuk static assets (immutable) dan HTML (no-cache) |
| SPA redirects | Selalu tambahkan SPA fallback redirect (/* β /index.html) |
| Honeypot forms | Gunakan netlify-honeypot untuk mencegah spam pada forms |
| Secrets di env vars | Jangan commit secrets β simpan di Netlify environment variables |
| Functions timeout | Default timeout 10 detik. Untuk long-running tasks, pertimbangkan Background Functions |
| Image optimization | Gunakan Netlify Image CDN untuk optimasi gambar otomatis |
| Force HTTPS | Selalu aktifkan force HTTPS di production |
| Monitor builds | Pantau build minutes dan bandwidth usage di dashboard |
Netlify menyediakan free tier yang sangat generous β 100 GB bandwidth, 300 build menit, dan 125K serverless function calls per bulan. Ini lebih dari cukup untuk kebanyakan project personal dan startup. Upgrade ke Pro plan ($19/bln) untuk fitur lebih lanjut seperti role-based access dan priority support.
12. Quiz Pemahaman
π Quiz: Pemahaman Netlify
1. Bagaimana cara Netlify melakukan deploy otomatis?
2. Apa fungsi atribut data-netlify="true" pada HTML form?
3. Dimana Netlify Functions berjalan?
4. Apa perbedaan antara Edge Functions dan Serverless Functions?
5. Apa itu Deploy Preview di Netlify?