Lompat ke konten
Kembali ke modul

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.

tsx
// 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.

Coba sendiri

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()

tsx
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>;
}
Ini persis yang dilakukan halaman pelajaran di proyek ini. notFound() melempar, seperti redirect(), jadi tidak ada yang jalan setelahnya.

Metadata

tsx
// 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".