Next.js (3) การตั้งค่า Metadata

Web Development 29 พฤษภาคม พ.ศ. 2567 261
Home / Articles / 803

สวัสดีครับในวันนี้ผมจะพามาตั้งค่า Metadata ใน Next.js กัน หลายๆ คนที่เริ่มพัฒนาเว็บด้วย Next.js ใหม่ ๆ อาจจะยังสงสัยว่า ใน Next.js เราจะสามารถตั้ง Title และ Meta เช่น Open Graph protocol (og:image และอื่น ๆ) ของเว็บไซต์แบบ Dynamics ซึ่งแตกต่างกันในแต่ละหน้าได้อย่างไร บางหน้าจำเป็นต้องดึงข้อมูลจากฐานข้อมูลมาก่อน

หนึ่งในวิธีที่เราจะสามารถกำหนด Meta แบบคงที่ (Static) ได้ ก็คือการไปที่ layout.tsx ของแต่ละ Directory ซึ่งไฟล์นี้จะเป็นหนึ่งไฟล์ที่ประมวลผลแบบ Server-Side ในลำดับแรก ๆ เนื่องจาก Meta จำเป็นจะต้องถูกกำหนดในฝั่ง Server-Side หากไม่ได้สร้างไฟล์ดังกล่าว ก็สามารถสร้างขึ้นมาใหม่ได้เลย

Metadata

ยกตัวอย่างเป็นเว็บไซต์ของผมส่วนที่เป็น default ก็คือจะแสดงในหน้าปัจจุบัน และจะมีผลต่อหน้าอื่น ๆ ที่อยู่ใน Directory ที่ลึกเข้าไปด้วย หน้าอื่นๆ ที่มีการกำหนด เพียงแค่ title จะถูกเอามาใส่ในรูปแบบใน template

/src/app/layout.tsx

import type { Metadata } from "next";
import "./globals.css";
import React from "react";

export const metadata: Metadata = {
  metadataBase: new URL('https://sunny420x.com'),
  title: {
    absolute: "",
    default: "Sunny420x.com | Computer Science Articles by Sunny Jirakit",
    template: "%s | Sunny420x",
  },
  description: "บทความคอมพิวเตอร์ การพัฒนาเว็บไซต์และโปรแกรม โดย ซันนี่ จิรกิตติ์",
  openGraph: {
      images: '/img/banner-new.png',
  }
};


export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html>
      {children}
    </html>
  )
}
    

เมื่อผมไปสร้าง layout.tsx ใน /src/app/articles โดยที่ export const metadata: Metadata มาเพียง title และ description แบบนี้

/src/app/articles/layout.tsx

import type { Metadata } from "next";
import "../globals.css";
import React from "react";

export const metadata: Metadata = {
  title: "Articles",
  description: "Computer Science Articles.",
};


export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html>
      {children}
    </html>
  )
}
    

จะพบว่า หัวข้อ title ของเว็บไซต์ ก็จะได้เป็น "Articles | Sunny420x" แต่ description จะยังเป็นอันเดิมตามที่กำหนดไว้ใน /src/app/layout.tsx เนื่องจากไม่ได้กำหนด default หรือ template ไว้เหมือนกับ title ทำให้ nextjs จะยึดตาม layout.tsx ที่อยู่สูงกว่า

metadataBase

จะเห็นได้ว่าผมมีการตั้งค่า metadataBase ด้วย เนื่องจาก เมื่อเรา Build Project ของเราด้วยคำสั่ง npm build แล้วสั่งให้ทำงานด้วย npm start ในส่วนของ path เช่น /img/banner-new.png จะกลายเป็น http://localhost:3000/img/banner-new.png แทน ซึ่งผมต้องการให้มันเป็น https://sunny420x.com/img/banner-new.png จึงได้ทำการกำหนด metadataBase เข้าไป

generateMetadata

ทีนี้ผมจะไปส่วนที่เป็น Dynamics กันบ้าง เว็บบทความที่อันจะต้องมีหัวข้อ ภาพประกอบ และคำอธิบาย ซึ่งเราจำเป็นจะต้องดึงข้อมูลออกมาจากฐานข้อมูล ใน Server-Side ก่อน โดยผมจะไปที่ /src/articles/[id]/layout.tsx และเพิ่ม export generateMetadata ดังนี้เข้าไป จะเป็นการแทนที่ layout.tsx ที่อยู่ Directory ที่สูงกว่าได้เลย

/src/app/layout.tsx

import React from "react";
import "../../globals.css";
import { Metadata, ResolvingMetadata } from "next";

export async function generateMetadata(
  { params }: any,
  parent: ResolvingMetadata
): Promise {
  const id = params.id
 
  // fetch data
  const articleData = await fetch(`https://backend.sunny420x.com/get-article-title/${id}`, { next: { revalidate: 0 } }).then((res) => res.json())
 
  return {
    metadataBase: new URL('https://sunny420x.com'),
    title: articleData.article[0].title + " | Sunny420x Article",
    description: articleData.article[0].content.replace(/(<([^>]+)>)/ig,''),
    openGraph: {
        images: articleData.article[0].img,
    },
  }
}

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html>
      {children}
    </html>
  )
}

อ้างอิง:
nexts.org/docs

Profile Picture.
  • Name (Pen name): Sunny Jirakit (Sunny420x)
  • Study: Bachelor Degree of Computer Science from Chiang Mai Rajabhat University
  • Personality: Architect (INTJ-T)
  • Experience: JavaScript,  Angular.js, React.js, Next.js  Express.js, Unity C#, Socket.io