Next.js: Fullstack dalam Satu Proyek · 8/9
Penanganan error, not-found, dan metadata
Gagal dengan elegan, dan dasar-dasar SEO yang selalu ditanyakan ke developer CMS.
Baca 25 menit
Setelah pelajaran ini kamu bisa
- Menangkap error dengan `error.tsx` di tingkat yang tepat
- Memakai `notFound()` dan `not-found.tsx`
- Menjelaskan kenapa pesan error disembunyikan di production
- Mengatur metadata, termasuk judul per halaman
Error yang tidak tertangkap di Server Component akan berujung halaman kosong. error.tsx adalah boundary yang menangkapnya lalu me-render sesuatu yang berguna.
// app/[lang]/dashboard/error.tsx
"use client"; // error boundaries must be Client Components
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<div role="alert">
<h2>Something went wrong loading your dashboard</h2>
{/* In production, error.message is replaced with a generic string. */}
<p>{error.digest ? "Reference: " + error.digest : null}</p>
<button onClick={reset}>Try again</button>
</div>
);
}reset() mencoba me-render ulang segment-nya tanpa memuat ulang seluruh halaman. digest adalah hash yang bisa kamu cocokkan dengan log server-mu.Boundary bersarang
Sebuah error naik ke error.tsx terdekat di atasnya. Tempat kamu menaruh file itu menentukan seberapa banyak bagian halaman yang tetap selamat.
Perjalanan error ke atas, dan apa akibat penempatan setiap boundary bagi penggunanya.
Hasil
Tekan Jalankan untuk melihat hasilnya.
Ini jalan di browser kamu, di dalam sandbox. Apa pun yang kamu tulis di sini tidak bisa merusak situs.
notFound()
import { notFound } from "next/navigation";
export default async function LessonPage({ params }) {
const { module, lesson } = await params;
const ref = getLesson(module, lesson);
// Not an error - a legitimate 404. Renders not-found.tsx with a 404 status.
if (!ref) notFound();
return <article>...</article>;
}notFound() melempar, seperti redirect(), jadi tidak ada yang jalan setelahnya.Metadata
// Static, when it never depends on the data:
export const metadata: Metadata = {
title: "Dashboard",
description: "Your learning progress",
};
// Dynamic, when it does:
export async function generateMetadata({ params }): Promise<Metadata> {
const { module, lesson } = await params;
const ref = getLesson(module, lesson);
if (!ref) return {}; // a 404 needs no title
return { title: ref.lesson.title.en, description: ref.lesson.summary.en };
}
// In the root layout, a template applies a suffix to every child title:
export const metadata: Metadata = {
title: { default: "Fullstack Learning Path", template: "%s · Fullstack Learning Path" },
};template adalah alasan setiap halaman pelajaran di proyek ini menampilkan judulnya sendiri diikuti nama situsnya, tanpa mengulang akhirannya di mana pun.- Judul unik per halaman. Itulah yang muncul di hasil pencarian dan tab browser.
- Deskripsi yang terbaca seperti sebuah kalimat. Mesin pencari sering menampilkannya apa adanya.
- `openGraph` untuk pratinjau tautan. Inilah yang tampil saat seseorang menempelkan tautanmu di WhatsApp atau Slack.
- `<html lang>` yang benar. Ia memberi tahu screen reader bahasa apa yang harus dilafalkan.
Tugas praktik
Di proyek ini, buka /en/modules/react/nope dan pastikan kamu mendapat 404 — lalu jalankan curl -o /dev/null -w "%{http_code}\n" http://localhost:3000/en/modules/react/nope untuk membuktikan status-nya benar-benar 404 dan bukan 200. Lalu cek judul halaman di halaman pelajaran sungguhan dan temukan template di app/[lang]/layout.tsx yang menghasilkannya.
Hasil yang diharapkan
404, dan judul berbentuk "Judul pelajaran · Jalur Belajar Fullstack".