Pernahkah kamu membuka View Page Source di website buatanmu sendiri, lalu menemukan isinya hampir kosong? Hanya satu baris <div id="app"></div>, beberapa tag <script>, dan tidak ada satu pun kalimat dari konten yang kamu tulis dengan susah payah.
Kalau kamu pernah mengalaminya, kamu baru saja bertemu dengan masalah yang membuat Server-Side Rendering (SSR) lahir. Dan kalau belum pernah, tenang. Artikel ini akan membawamu ke sana, lalu menunjukkan jalan keluarnya.
Di akhir tulisan ini kamu akan paham apa itu SSR, bagaimana Nuxt menjalankannya tanpa kamu repot, kapan harus memilih SSR, SSG, atau SPA, dan jebakan apa saja yang sering membuat pemula frustrasi. Semuanya dengan bahasa sehari-hari dan contoh kode yang bisa langsung dicoba.
Kenapa SSR Selalu Bikin Pemula Bingung#
Ketika pertama kali belajar Nuxt.js, hampir semua orang melewati fase yang sama. Awalnya semua terasa mudah: buat halaman, tulis komponen Vue, jalankan npm run dev, selesai. Lalu muncul pesan error yang aneh seperti window is not defined, atau peringatan hydration mismatch yang tidak jelas maksudnya. Di titik itu, banyak pemula merasa Nuxt "lebih ribet" daripada Vue biasa.
Sumber kebingungannya hampir selalu sama: kode kita ternyata berjalan di dua tempat. Sebagian dijalankan di server, sebagian lagi di browser. Padahal selama ini kita terbiasa membayangkan kode JavaScript front-end hanya berjalan di browser.
Padahal, inilah alasan utama banyak developer memilih Nuxt dibandingkan Single-Page Application (SPA) murni. SSR memberi tiga hal yang sulit didapat dari SPA biasa:
- Konten langsung terlihat. Pengunjung melihat halaman yang sudah terisi, bukan layar putih yang menunggu JavaScript selesai dimuat.
- Fondasi SEO yang lebih kuat. Mesin pencari dan crawler menerima HTML yang sudah berisi konten.
- Pratinjau tautan yang benar. Saat tautanmu dibagikan ke WhatsApp, Telegram, atau media sosial, judul dan gambar yang muncul sesuai harapan.
Selain itu, Nuxt mengurus sebagian besar pekerjaan beratnya. Kita tidak perlu menyiapkan server rendering dari nol. Kita cukup fokus menulis komponen Vue dan memahami beberapa aturan main.
Tulisan ini disusun dalam tiga bagian besar:
- Prolog (bagian ini): kenapa topik ini penting dan bagaimana cara membacanya.
- Inti: konsep, cara kerja, kode, mode rendering, SEO, jebakan umum, dan FAQ.
- Epilog: rangkuman, langkah belajar berikutnya, dan daftar sumber.
Kamu boleh membaca berurutan, atau melompat ke bagian yang kamu butuhkan. Satu catatan kecil: contoh kode di sini mengacu pada Nuxt 4, yang memakai struktur folder app/. Jika proyekmu masih Nuxt 3, konsepnya sama persis, hanya letak foldernya sedikit berbeda.
Memahami SSR Nuxt Langkah demi Langkah#
1. Apa Itu Server-Side Rendering? Analogi Restoran#
SSR pada dasarnya adalah teknik merender halaman di sisi server sebelum dikirim ke browser. Kalimat itu benar, tapi mudah terlupakan. Mari pakai analogi yang lebih mudah dibayangkan.
Bayangkan dua restoran.
Restoran pertama menyajikan bahan mentah beserta resep di atas meja. Kamu harus memasak sendiri di meja itu. Prosesnya baru selesai setelah kamu selesai merakit semuanya. Inilah SPA: server mengirim kerangka kosong dan paket JavaScript, lalu browser yang "memasak" tampilan halaman.
Restoran kedua memasak di dapur, lalu mengantar piring yang sudah jadi ke mejamu. Kamu bisa langsung makan. Setelah itu, pelayan baru memberikan sendok, garpu, dan saus agar kamu bisa menyesuaikan rasa sesukamu. Inilah SSR: server menyiapkan HTML lengkap, browser langsung menampilkannya, lalu JavaScript menyusul agar halaman bisa diklik dan berinteraksi.
Perbedaan inti keduanya ada pada siapa yang memasak lebih dulu. Pada SSR, hasil masakan sudah tersedia saat pengunjung tiba.
Dalam bahasa teknis, rendering adalah proses mengubah kode (komponen Vue, data, template) menjadi HTML yang bisa dibaca browser. Pada SSR, proses itu terjadi di server. Pada SPA, proses itu terjadi di browser pengunjung.
Hasilnya terasa langsung bagi pengguna: mereka melihat konten tanpa harus menunggu JavaScript dimuat dan dijalankan. Ini sangat penting untuk SEO dan juga untuk kesan pertama yang cepat.
Ada satu hal yang sering terlewat, dan akan kita bahas lebih dalam nanti: "langsung terlihat" tidak sama dengan "langsung bisa diklik". Halaman SSR tampil cepat, tapi tombol dan form baru benar-benar hidup setelah JavaScript selesai dimuat. Proses "menghidupkan" halaman inilah yang disebut hydration.
2. Alur Kerja SSR di Nuxt: Dari Request sampai Halaman Hidup#
Supaya kamu tidak sekadar menghafal definisi, mari kita ikuti perjalanan satu halaman dari awal sampai akhir. Anggap pengunjung membuka https://contoh.com/artikel/belajar-nuxt.
Langkah 1: Browser mengirim request. Pengunjung mengetik alamat atau mengklik tautan. Browser meminta halaman itu ke server.
Langkah 2: Server Nuxt menerima request. Nuxt memakai mesin server bernama Nitro. Nitro menentukan halaman mana yang cocok dengan alamat tersebut berdasarkan struktur file di folder pages/.
Langkah 3: Server menjalankan aplikasi Vue-mu. Di sinilah keajaiban terjadi. Server menjalankan komponen halaman, termasuk logika pengambilan data seperti useAsyncData. Data diambil, komponen dirender, dan hasilnya adalah string HTML yang sudah berisi konten.
Langkah 4: Server mengirim HTML lengkap. Respons yang diterima browser sudah berisi judul, paragraf, daftar, gambar, dan meta tag. Selain HTML, server menyertakan data yang tadi diambil (disebut payload) agar browser tidak perlu mengambilnya lagi.
Langkah 5: Browser menampilkan halaman. Karena HTML sudah lengkap, browser bisa langsung menggambar halaman. Pengunjung sudah bisa membaca, bahkan sebelum JavaScript selesai diunduh.
Langkah 6: Browser mengunduh dan menjalankan JavaScript. Paket JavaScript Nuxt dan Vue dimuat di latar belakang.
Langkah 7: Hydration. Vue "mengambil alih" HTML yang sudah ada. Ia menyambungkan event listener ke tombol dan elemen interaktif, tanpa membangun ulang seluruh halaman dari nol. Setelah ini selesai, halaman berubah dari sekadar "gambar yang bisa dibaca" menjadi aplikasi yang hidup.
Langkah 8: Navigasi selanjutnya terasa seperti SPA. Setelah halaman pertama dimuat, perpindahan antarhalaman lewat <NuxtLink> ditangani di browser. Tidak ada muat ulang penuh, sehingga terasa mulus.
Poin terakhir ini penting: Nuxt dengan SSR bukan pilihan "SSR atau SPA". Pemuatan pertama memakai SSR, sedangkan navigasi sesudahnya memakai gaya SPA. Banyak orang menyebut pendekatan ini universal rendering, dan inilah mode bawaan Nuxt.
Ringkasnya, kode yang kamu tulis berjalan dua kali: sekali di server untuk menghasilkan HTML, sekali lagi di browser untuk hydration. Keputusan penting soal "di mana kode ini boleh berjalan" akan menjadi tema berulang di sisa artikel.
3. SSR, SSG, dan SPA: Tiga Cara Merender Halaman#
Sebelum memilih mode, kita perlu mengenal ketiganya dengan jelas. Ketiganya sering disebut bersamaan, dan tidak ada yang otomatis paling bagus. Yang ada hanyalah yang paling cocok untuk kebutuhanmu.
SPA (Single-Page Application)#
Server mengirim HTML kerangka yang nyaris kosong dan paket JavaScript. Browser menjalankan JavaScript, lalu menyusun tampilan. Hasilnya, setelah dimuat, aplikasi terasa sangat responsif karena perpindahan halaman hanya menukar komponen.
Kelebihannya: hosting murah (cukup file statis), interaksi mulus, dan cocok untuk aplikasi di balik login. Kekurangannya: pemuatan awal bisa terasa lambat karena konten baru muncul setelah JavaScript berjalan, dan SEO bergantung pada kemampuan crawler menjalankan JavaScript.
SSR (Server-Side Rendering)#
Setiap kali ada request, server merender halaman menjadi HTML lengkap. Data selalu bisa segar karena diambil saat request masuk.
Kelebihannya: konten langsung terlihat, SEO dan pratinjau tautan baik, data selalu terbaru. Kekurangannya: kamu butuh server yang berjalan (atau platform serverless), dan setiap request memakai sumber daya server.
SSG (Static Site Generation)#
Halaman dirender satu kali saat proses build, lalu hasilnya berupa file HTML statis yang bisa ditaruh di hosting mana pun atau di CDN. Saat pengunjung datang, tidak ada proses rendering sama sekali. File tinggal dikirim.
Kelebihannya: sangat cepat, murah, dan aman. Kekurangannya: setiap perubahan konten mengharuskan build ulang, sehingga kurang cocok untuk data yang berubah terus-menerus.
Perbandingan Singkat#
| Aspek | SPA | SSR | SSG |
|---|---|---|---|
| Kapan HTML dibuat | Di browser | Setiap request, di server | Sekali saat build |
| Konten di HTML awal | Hampir kosong | Lengkap | Lengkap |
| Kesegaran data | Segar (ambil di browser) | Segar (ambil di server) | Sesuai waktu build |
| Kebutuhan server | File statis saja | Server atau serverless | File statis saja |
| Biaya hosting | Rendah | Lebih tinggi | Paling rendah |
| Cocok untuk | Dashboard, aplikasi internal | Situs dinamis butuh SEO | Blog, dokumentasi, landing page |
Kabar baiknya, di Nuxt kamu tidak terkunci pada satu pilihan untuk seluruh website. Pada bagian pemilihan mode nanti, kita akan lihat bagaimana halaman yang berbeda bisa memakai mode berbeda dalam satu proyek.
4. Kenapa SSR Penting? Tiga Alasan yang Bisa Kamu Rasakan#
Alasan 1: SEO yang lebih aman#
Mesin pencari bekerja dengan membaca halaman. Bila halaman yang diterima crawler sudah berisi teks, judul, dan tautan, proses memahaminya jauh lebih sederhana.
Supaya adil, ada satu nuansa yang perlu kamu tahu. Google memang mampu menjalankan JavaScript dan merender halaman SPA. Namun dokumentasi resmi Google sendiri menyebut bahwa SSR atau pre-rendering tetap ide yang bagus, karena membuat situs lebih cepat bagi pengguna dan crawler, dan tidak semua bot mampu menjalankan JavaScript. Jadi SSR bukan syarat mutlak agar muncul di Google, tetapi ia menghilangkan banyak ketidakpastian, terutama untuk situs baru, situs konten, dan situs yang mengandalkan trafik organik.
Sebagai pertimbangan tambahan, tidak semua "pembaca otomatis" sepintar mesin pencari utama. Pembuat pratinjau tautan di aplikasi pesan, misalnya, umumnya hanya membaca HTML awal. Di sinilah SSR terasa manfaatnya.
Alasan 2: Kesan pertama yang cepat#
Pengguna tidak peduli seberapa canggih arsitekturmu. Mereka peduli apakah halaman terlihat siap dibaca dengan cepat. Karena HTML dari SSR sudah berisi konten, browser bisa menampilkan sesuatu yang bermakna lebih awal. Ini berhubungan dengan metrik seperti Largest Contentful Paint (LCP) dalam Core Web Vitals, yaitu waktu hingga elemen konten terbesar tampil.
Catatan jujur: SSR tidak otomatis membuat situsmu cepat. Server yang lambat, data yang berat, atau gambar yang tidak dioptimalkan tetap bisa merusak pengalaman. SSR memberi peluang untuk cepat, bukan jaminan.
Alasan 3: Berbagi tautan yang rapi#
Saat tautan artikelmu dibagikan, aplikasi pesan dan media sosial mengambil judul, deskripsi, dan gambar dari meta tag di HTML awal. Dengan SSR, tag itu sudah terisi sesuai halaman. Pada SPA murni, tag-nya sering sama untuk semua halaman karena diisi belakangan lewat JavaScript.
Bila ketiga alasan ini relevan dengan proyekmu, SSR layak dipertimbangkan serius. Jika tidak, misalnya aplikasi admin di balik login, SPA atau mode lain bisa jadi pilihan yang lebih efisien. Kita akan bahas cara memutuskannya secara sistematis di bagian berikutnya.
5. Dalam Nuxt, Kita Tidak Perlu Mengatur Semuanya dari Nol#
Bagian terbaik dari Nuxt adalah ini: SSR sudah aktif secara bawaan. Kamu tidak perlu menginstal server rendering, mengatur bundler untuk dua lingkungan, atau menulis konfigurasi routing yang rumit. Nuxt mengerjakannya untukmu.
Mari kita buktikan. Buka terminal dan buat proyek baru:
Setelah server pengembangan berjalan, buka http://localhost:3000. Hanya dengan perintah npm run dev, Nuxt otomatis menangani rendering sisi server untuk setiap halaman. Tidak ada langkah tambahan.
Struktur folder yang perlu kamu kenal#
Pada Nuxt 4, kode aplikasi berada di folder app/. Tiga hal yang paling sering kamu sentuh di awal:
app/app.vue: titik masuk aplikasi, tempat tata letak dasar.app/pages/: setiap file.vuedi sini otomatis menjadi rute. Fileapp/pages/index.vuemenjadi halaman utama, danapp/pages/artikel/[slug].vuemenjadi rute dinamis.nuxt.config.ts: tempat pengaturan global, termasuk mode rendering.
Coba buat halaman sederhana di app/pages/index.vue:
Cara membuktikan SSR benar-benar bekerja#
Ini trik yang sebaiknya kamu biasakan, karena akan sangat berguna saat men-debug.
- Buka halamanmu di browser.
- Klik kanan, pilih View Page Source (jangan Inspect, keduanya berbeda).
- Cari teks "Halo dari Nuxt".
Jika teks itu ada di sumber halaman, berarti HTML-nya memang dikirim lengkap dari server. Itulah SSR.
Perbedaan keduanya sering membingungkan pemula. View Page Source menampilkan HTML mentah yang diterima dari server. Inspect menampilkan kondisi halaman setelah JavaScript berjalan. Jadi untuk menguji SSR, gunakan View Page Source.
Bila ingin membandingkan, buka nuxt.config.ts dan matikan SSR sementara:
Simpan, muat ulang, lalu lihat lagi View Page Source. Kini isinya nyaris kosong, persis seperti SPA pada umumnya. Kembalikan ke ssr: true (atau hapus barisnya) setelah selesai bereksperimen. Percobaan sederhana ini sering menjadi momen "oh, ternyata begitu" bagi banyak pemula.
Dengan fondasi ini, kita tinggal fokus menulis komponen Vue dan memanfaatkan fitur seperti useAsyncData untuk mengambil data sebelum halaman dirender. Mari kita bahas fitur itu lebih dalam.
6. Mengambil Data dengan useAsyncData dan useFetch#
Hampir semua halaman nyata butuh data: daftar artikel, detail produk, profil pengguna. Di sinilah pemula paling sering tersandung, karena cara mengambil data di aplikasi SSR berbeda dari kebiasaan SPA.
Kebiasaan lama yang bermasalah#
Di SPA, kita biasa mengambil data di dalam onMounted:
Masalahnya, onMounted hanya berjalan di browser. Saat server merender halaman, artikel masih kosong. HTML yang dikirim tidak berisi daftar artikel, sehingga manfaat SSR hilang. Pengunjung melihat halaman kosong sebentar, lalu data muncul setelah JavaScript selesai. Crawler pun hanya melihat halaman kosong.
Cara yang benar: useAsyncData#
Nuxt menyediakan useAsyncData agar data diambil sebelum halaman dirender, baik di server maupun di klien:
Beberapa hal penting dari contoh di atas:
- Argumen pertama adalah kunci (key). Kunci ini harus unik untuk setiap pengambilan data. Nuxt memakainya untuk menyimpan hasil ke dalam payload dan mencegah pengambilan ganda.
- Argumen kedua adalah fungsi pengambil data. Fungsi ini harus mengembalikan nilai (biasanya hasil dari
$fetch). - Gunakan
awaitdi level atas<script setup>. Dengan begitu server menunggu data siap sebelum merender HTML. - Hasilnya berupa beberapa nilai reaktif:
data,status,error, dan fungsirefreshuntuk mengambil ulang.
Karena data diambil di server lalu dikirim sebagai payload, browser tidak perlu mengulang permintaan yang sama saat hydration. Inilah alasan halamanmu tidak "berkedip" dan tidak memicu dua kali pengambilan data.
Jalan pintas: useFetch#
Untuk kasus paling umum, yaitu mengambil data dari sebuah URL, Nuxt menyediakan useFetch. Ia pada dasarnya gabungan useAsyncData dan $fetch, dengan kunci yang dibuat otomatis:
Sederhana, bukan? Rule of thumb yang mudah diingat:
- Pakai
useFetchsaat kamu cukup memanggil satu URL. - Pakai
useAsyncDatasaat logikanya lebih rumit, misalnya menggabungkan beberapa sumber data, memakai pustaka klien tertentu, atau mengolah hasil sebelum disimpan. - Pakai
$fetchlangsung untuk aksi yang dipicu pengguna, seperti mengirim form atau menekan tombol. Jangan memakainya di level atas komponen untuk data awal halaman, karena data itu bisa terambil dua kali (di server dan lagi di browser).
Membuat endpoint sendiri di Nuxt#
Salah satu kekuatan Nuxt adalah kamu bisa membuat API di proyek yang sama. File di folder server/api/ otomatis menjadi endpoint:
Endpoint ini bisa dipanggil dengan useFetch('/api/artikel'). Pada saat SSR, Nuxt cukup cerdas untuk memanggil fungsi server tersebut secara langsung tanpa melewati jaringan, sehingga lebih cepat.
Menangani data tidak ditemukan#
Pada halaman detail, kamu perlu memastikan halaman yang tidak ada mengembalikan status 404 yang benar. Ini penting untuk SEO, karena halaman "tidak ditemukan" yang mengembalikan status 200 membingungkan mesin pencari.
Dengan SSR, status 404 itu benar-benar dikirim dari server, sehingga crawler tahu bahwa halaman tersebut memang tidak ada.
7. Hydration dan Jebakan yang Sering Menjebak Pemula#
Sekarang kita sampai pada bagian yang membuat banyak orang menyerah di awal. Jangan khawatir. Hampir semua masalah SSR bersumber dari satu prinsip: kode yang sama berjalan di server dan di browser, padahal keduanya lingkungan yang berbeda.
Jebakan 1: window is not defined#
Di server tidak ada window, document, atau localStorage. Itu adalah API browser. Jika kamu memakainya langsung di level atas <script setup>, server akan error saat merender.
Salah:
Benar, jalankan di browser saja:
onMounted hanya berjalan di browser, sehingga aman memakai API browser di dalamnya. Alternatif lain adalah membungkus kode dengan pengecekan lingkungan:
Untuk komponen yang memang hanya masuk akal di browser (misalnya peta interaktif atau grafik berbasis canvas), bungkus dengan <ClientOnly>:
Jebakan 2: Hydration mismatch#
Peringatan ini muncul ketika HTML yang dibuat server berbeda dari yang dihasilkan browser saat hydration. Vue mengharapkan keduanya identik. Jika berbeda, ia tidak tahu mana yang benar.
Penyebab paling umum:
- Nilai yang berubah tiap eksekusi, seperti
Date.now(),new Date(), atauMath.random()dipakai langsung di template. Waktu di server dan di browser pasti berbeda. - Format tanggal dan angka yang bergantung zona waktu atau bahasa, karena server dan browser bisa memiliki pengaturan yang berbeda.
- Struktur HTML yang tidak valid, misalnya menaruh
<div>di dalam<p>. Browser otomatis memperbaikinya, sehingga hasilnya berbeda dari yang dikirim server. - Konten yang bergantung pada kondisi browser, seperti ukuran layar atau data di
localStorage.
Solusi umumnya: pastikan nilai awal sama di kedua sisi, lalu perbarui nilai khusus-browser setelah onMounted. Contoh:
Pada HTML dari server, nilainya masih ..., sama seperti saat hydration. Setelah halaman hidup, barulah jam yang sebenarnya muncul. Mismatch pun hilang.
Jebakan 3: State yang bocor antar pengguna#
Ini jebakan paling halus, dan paling berbahaya. Di browser, setiap pengunjung punya salinan aplikasinya sendiri. Di server, satu proses melayani banyak pengunjung. Jika kamu menaruh variabel di luar fungsi komponen, nilainya bisa terbagi di antara pengguna yang berbeda.
Contoh yang berisiko:
Pada SSR, keranjang ini hidup selama server berjalan, sehingga isi keranjang satu pengguna bisa terlihat oleh pengguna lain. Untuk state yang dipakai bersama di banyak komponen, gunakan useState, yang aman untuk SSR karena terpisah per request:
Selain useState, kamu juga bisa memakai pustaka state management yang mendukung SSR seperti Pinia. Intinya: hindari menyimpan state pengguna di variabel global modul.
Jebakan 4: Plugin dan pustaka pihak ketiga#
Beberapa pustaka JavaScript hanya bekerja di browser. Bila dimuat di server, aplikasi bisa error. Nuxt menyediakan akhiran nama file untuk plugin: nama.client.ts hanya berjalan di browser, nama.server.ts hanya di server. Untuk komponen, .client.vue memiliki efek serupa. Cukup ingat bahwa kamu punya alat untuk mengatur di mana kode berjalan.
Semua jebakan ini punya pola sama. Tanyakan pada dirimu: "Apakah kode ini aman dijalankan di server?" Bila jawabannya tidak, pindahkan ke onMounted, import.meta.client, atau <ClientOnly>.
8. Memilih Mode Rendering: SSR, SSG, SPA, atau Campuran#
Satu hal yang perlu diingat adalah cara memilih antara mode SSR, SSG, dan SPA. Tidak ada jawaban universal, tetapi ada pertanyaan-pertanyaan yang membuat keputusannya jauh lebih mudah.
Empat pertanyaan penentu#
- Seberapa sering kontennya berubah? Bila berubah tiap menit atau tiap pengguna melihat hal berbeda, SSR atau SPA lebih masuk akal. Bila berubah beberapa kali seminggu, SSG sudah cukup.
- Apakah halaman ini perlu ditemukan lewat mesin pencari? Jika ya, pilih SSR atau SSG. Jika halaman berada di balik login, SEO tidak relevan.
- Apakah halaman bergantung pada data pribadi pengguna? Dashboard dan halaman akun biasanya cocok untuk SPA atau SSR tanpa cache bersama.
- Apa yang tersedia di infrastruktur dan anggaranmu? SSG hanya butuh hosting file statis. SSR butuh server atau platform serverless.
Dari pertanyaan itu, aturan praktisnya begini. Untuk website yang sering berubah dan butuh SEO kuat, SSR adalah pilihan tepat. Untuk konten statis seperti blog, SSG bisa lebih hemat biaya server.
Contoh keputusan nyata#
| Jenis proyek | Mode yang cocok | Alasan singkat |
|---|---|---|
| Blog pribadi atau dokumentasi | SSG | Konten jarang berubah, hosting statis murah dan cepat |
| Toko online | SSR atau hybrid | Stok dan harga berubah, halaman produk butuh SEO |
| Portal berita | SSR atau hybrid dengan cache | Konten sering baru, SEO sangat penting |
| Dashboard admin | SPA | Di balik login, SEO tidak diperlukan |
| Landing page + aplikasi | Hybrid | Halaman publik statis, area aplikasi SPA |
Mode statis: nuxt generate#
Untuk membuat situs statis (SSG), jalankan:
Perintah ini merender halaman-halamanmu saat build dan menghasilkan file HTML statis yang siap diunggah ke hosting statis mana pun. Kamu tetap menulis kode yang sama. Bedanya hanya kapan rendering terjadi.
Hybrid rendering dengan routeRules#
Bagian paling menarik: satu proyek Nuxt boleh memakai mode berbeda untuk rute berbeda. Pengaturannya ada di nuxt.config.ts lewat routeRules:
Cara membacanya:
prerender: true: halaman dibuat saat build, seperti SSG.swr: 3600: halaman dirender di server, lalu hasilnya di-cache selama 3600 detik. Pengunjung berikutnya menerima versi cache dengan cepat, sementara versi baru dibuat di latar belakang. Polanya disebut stale-while-revalidate.isr: miripswr, tetapi pada platform yang mendukungnya (misalnya Vercel dan Netlify) hasilnya disimpan di cache CDN platform tersebut. Ketersediaannya bergantung pada platform hosting yang kamu pakai.ssr: false: rute itu tidak dirender di server dan berperilaku seperti SPA.
Dengan cara ini kamu tidak perlu memilih satu mode untuk seluruh website. Beranda dan halaman "Tentang" bisa statis, artikel bisa memakai cache, dan dashboard bisa SPA. Kamu mendapatkan kecepatan dan SEO di tempat yang butuh, serta kesederhanaan di tempat yang tidak.
Saran untuk pemula: mulailah dengan SSR bawaan. Setelah aplikasi berjalan dan kamu tahu halaman mana yang jarang berubah, barulah optimalkan dengan routeRules. Optimasi dini tanpa data biasanya hanya menambah kerumitan.
9. SEO Praktis di Nuxt: Dari Meta Tag sampai Status Halaman#
SSR menyediakan fondasi, tapi SEO tidak terjadi otomatis. Berikut langkah-langkah yang paling berdampak, disusun dari yang paling sederhana.
Atur judul dan deskripsi per halaman#
Setiap halaman butuh judul dan deskripsi yang unik. Nuxt menyediakan useSeoMeta, yang aman untuk SSR dan memiliki nama properti yang mudah dibaca:
Perhatikan urutannya: data diambil lebih dulu dengan await, baru meta tag diisi. Karena berjalan di server, tag ini sudah ada di HTML awal. Itulah yang dibaca crawler dan pembuat pratinjau tautan.
Tambahkan canonical dan atribut bahasa#
Untuk menghindari masalah duplikasi URL, tambahkan tautan canonical memakai useHead:
Gunakan struktur heading yang jelas#
Satu halaman sebaiknya punya satu <h1> yang mewakili topik utama, lalu <h2> dan <h3> untuk subtopik. Struktur ini membantu pembaca memindai halaman dan membantu mesin pencari memahami hierarkinya.
Pastikan tautan memakai NuxtLink#
Gunakan <NuxtLink to="/artikel"> untuk navigasi internal. Di HTML, hasilnya adalah tag <a href> biasa yang bisa diikuti crawler, sekaligus memberi navigasi cepat di browser.
Kembalikan status HTTP yang benar#
Seperti dibahas sebelumnya, halaman yang tidak ada harus mengembalikan 404 lewat createError. Halaman yang dipindahkan sebaiknya memakai pengalihan yang tepat. Status yang akurat adalah sinyal penting bagi mesin pencari.
Lengkapi dengan sitemap dan robots.txt#
Sitemap membantu mesin pencari menemukan seluruh halamanmu, sedangkan robots.txt mengatur apa yang boleh dirayapi. Untuk Nuxt tersedia modul komunitas seperti Nuxt SEO yang membantu membuat keduanya, beserta fitur SEO lain.
Jangan lupakan konten itu sendiri#
Teknik secanggih apa pun tidak menggantikan konten yang membantu. Tulis untuk manusia lebih dulu: jawab pertanyaan nyata, gunakan bahasa yang dipakai pembacamu, dan perbarui secara berkala. SSR memastikan konten itu sampai ke mesin pencari. Kualitas kontenlah yang membuatnya layak diperhitungkan.
10. Dari Laptop ke Internet: Build dan Deployment#
Saat proyek siap dipublikasikan, perintah yang kamu butuhkan bergantung pada mode yang dipilih.
Untuk SSR (butuh server):
Perintah build menghasilkan folder .output yang berisi server siap jalankan. Kamu bisa menjalankannya di VPS atau di server Node.js biasa.
Untuk SSG (hosting statis):
Hasilnya berupa file statis yang bisa diunggah ke layanan hosting statis atau CDN.
Karena Nuxt memakai Nitro, aplikasi yang sama dapat disesuaikan dengan banyak platform lewat preset, termasuk platform serverless dan edge. Biasanya Nitro mendeteksi platform secara otomatis saat kamu melakukan deployment ke layanan yang didukung. Daftar platform dan langkah detailnya selalu berubah, jadi rujuk dokumentasi deployment Nuxt versi terbaru sebelum memilih.
Pertimbangan biaya juga perlu masuk hitungan. Hosting statis jauh lebih murah, sehingga SSG atau prerender untuk halaman yang jarang berubah adalah cara hemat. SSR murni memberi fleksibilitas lebih, dengan konsekuensi server yang harus tetap berjalan atau penagihan berdasarkan penggunaan pada platform serverless.
11. Kesalahan Umum Pemula (dan Cara Menghindarinya)#
Sebelum menutup bagian inti, berikut daftar jebakan yang paling sering muncul. Anggap ini daftar periksa singkat yang bisa kamu simpan.
- Mengambil data di
onMounteduntuk konten yang butuh SEO. GunakanuseFetchatauuseAsyncDataagar data ikut dirender di server. - Lupa memakai
await. Tanpaawait, server tidak menunggu data dan HTML bisa terkirim kosong. - Kunci
useAsyncDatayang sama untuk data berbeda. Gunakan kunci unik, misalnya menyertakanslugatauid. - Memakai
window,document, ataulocalStoragedi level atas. Pindahkan keonMountedatau bungkus denganimport.meta.client. - Memakai
Date.now()atauMath.random()langsung di template. Ini sumber utama hydration mismatch. - Menyimpan state pengguna di variabel global. Pakai
useStateatau Pinia. - Mengira SSR otomatis membuat situs cepat. Ukur, optimalkan gambar, dan perhatikan ukuran JavaScript.
- Menguji dengan Inspect, bukan View Page Source. Untuk memastikan SSR, lihat HTML mentah dari server.
- Menerapkan SSR ke semua halaman tanpa berpikir. Halaman di balik login sering tidak membutuhkannya.
12. Pertanyaan yang Sering Diajukan (FAQ)#
Apa itu Server-Side Rendering di Nuxt?#
Server-Side Rendering adalah teknik merender halaman Vue menjadi HTML di server sebelum dikirim ke browser. Di Nuxt, fitur ini aktif secara bawaan. Setelah HTML tampil, JavaScript memuat dan melakukan hydration agar halaman menjadi interaktif.
Apakah SSR membuat website otomatis lebih cepat?#
Tidak otomatis. SSR membuat konten tampil lebih awal karena HTML sudah lengkap, tetapi kecepatan keseluruhan juga dipengaruhi performa server, ukuran JavaScript, gambar, dan cara kamu mengambil data.
Apakah Google bisa membaca website SPA tanpa SSR?#
Google mampu menjalankan JavaScript dan merender halaman SPA. Namun SSR atau pre-rendering tetap direkomendasikan karena lebih cepat bagi pengguna dan crawler, serta tidak semua bot mampu menjalankan JavaScript. Pratinjau tautan di media sosial juga umumnya bergantung pada HTML awal.
Apa bedanya useAsyncData dan useFetch?#
useFetch adalah jalan pintas untuk memanggil sebuah URL, dengan kunci otomatis. useAsyncData lebih fleksibel karena menerima fungsi apa saja yang mengembalikan data, cocok untuk logika yang lebih rumit.
Kapan sebaiknya memakai SSG dibanding SSR?#
Pakai SSG saat konten jarang berubah dan kamu ingin hosting murah serta cepat, seperti blog atau dokumentasi. Pakai SSR saat data sering berubah atau bergantung pada request. Dengan routeRules, kamu bisa mencampur keduanya.
Bagaimana cara mengecek apakah halaman saya sudah SSR?#
Buka halaman, klik kanan, pilih View Page Source, lalu cari teks konten kamu. Jika teksnya ada di HTML mentah, halaman itu dirender di server.
Setelah Paham Alurnya, Semuanya Terasa Lebih Ringan#
Kita sudah menempuh perjalanan yang cukup panjang. Dimulai dari halaman yang tampak kosong di View Page Source, kita melihat bagaimana SSR memasak halaman lebih dulu di server, bagaimana hydration menghidupkannya di browser, dan bagaimana Nuxt mengurus sebagian besar kerumitan itu untukmu.
Bila harus diringkas dalam beberapa kalimat:
- SSR merender HTML di server, sehingga konten langsung terlihat dan fondasi SEO lebih kuat.
- Hydration menghidupkan halaman setelah JavaScript dimuat, dan kode yang sama berjalan di dua lingkungan.
- Ambil data dengan
useFetchatauuseAsyncData, bukan dionMounted, agar data ikut dirender di server. - Hati-hati dengan API browser, nilai acak, dan state global, karena itulah sumber hampir semua jebakan pemula.
- Pilih mode sesuai kebutuhan: SSR untuk situs dinamis yang butuh SEO, SSG untuk konten statis, SPA untuk area di balik login, dan
routeRulesbila ingin mencampurnya.
Bila kamu ingin langsung berlatih, ini urutan yang bisa kamu ikuti hari ini:
- Buat proyek baru dengan
npm create nuxt@latestdan jalankannpm run dev. - Buat satu halaman, lalu buktikan SSR lewat View Page Source.
- Buat endpoint di
server/api/dan ambil datanya denganuseFetch. - Isi judul dan deskripsi dengan
useSeoMeta. - Coba
routeRulesuntuk membuat satu halaman statis dan satu halaman SPA.
Semoga catatan ini membantu teman-teman yang baru mulai dengan Nuxt. Teknologi ini memang terasa berat di awal, tapi sekali paham alurnya, membangun web modern terasa jauh lebih menyenangkan. Mulailah dari proyek kecil, ulangi percobaan sampai pola "di mana kode ini berjalan" terasa wajar, dan biarkan pemahamanmu tumbuh dari sana.
Punya pengalaman unik soal SSR, atau menemukan error yang sulit dipecahkan? Tulis di kolom komentar, dan kita bahas bersama.
Sumber dan Bacaan Lanjutan#
Artikel ini disusun berdasarkan dokumentasi resmi berikut. Karena Nuxt berkembang cepat, buka versi terbaru dokumentasinya untuk memeriksa perubahan.
- Nuxt Docs, Rendering Modes (universal rendering, client-side rendering, hybrid rendering): https://nuxt.com/docs/guide/concepts/rendering
- Nuxt Docs, Data Fetching: https://nuxt.com/docs/getting-started/data-fetching
- Nuxt Docs, useAsyncData: https://nuxt.com/docs/api/composables/use-async-data
- Nuxt Docs, useFetch: https://nuxt.com/docs/api/composables/use-fetch
- Nuxt Docs, SEO and Meta: https://nuxt.com/docs/getting-started/seo-meta
- Nuxt Docs, useSeoMeta: https://nuxt.com/docs/api/composables/use-seo-meta
- Nuxt Docs, State Management (
useState): https://nuxt.com/docs/getting-started/state-management - Nuxt Docs, ClientOnly: https://nuxt.com/docs/api/components/client-only
- Nuxt Docs, Deployment: https://nuxt.com/docs/getting-started/deployment
- Vue.js, Server-Side Rendering (SSR): https://vuejs.org/guide/scaling-up/ssr
- Google Search Central, Understand JavaScript SEO basics: https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics
- web.dev, Rendering on the Web: https://web.dev/articles/rendering-on-the-web
- web.dev, Web Vitals: https://web.dev/articles/vitals
- Nitro, dokumentasi resmi: https://nitro.build
Catatan redaksi: contoh kode bersifat ilustrasi dan disederhanakan agar mudah dipahami. Sesuaikan dengan struktur dan versi proyekmu.