Image และ Font
ไอเดียหลักในหนึ่งประโยค
หัวข้อที่มีชื่อว่า “ไอเดียหลักในหนึ่งประโยค”next/image resize, แปลงเป็น format ใหม่ และ lazy-load image ให้พร้อมจองพื้นที่ไว้ล่วงหน้า ส่วน next/font self-host font ตอน build — หน้าเว็บจึงโหลดเร็วและไม่ขยับ
next/image resize, แปลง format และ lazy-load
หัวข้อที่มีชื่อว่า “next/image resize, แปลง format และ lazy-load”Image คือตัวแทนแบบ drop-in ของ <img> ที่ optimize ให้ตอน request โดยสร้าง version ที่ resize ตามอุปกรณ์ ส่ง format ใหม่อย่าง WebP หรือ AVIF เมื่อ browser รองรับ และ lazy-load ทุกอย่างที่อยู่ใต้ fold ให้อัตโนมัติ
เมื่อคุณ import ไฟล์ในเครื่อง Next.js อ่านขนาดจริงตอน build ดังนั้น width กับ height จึงถูกเติมให้เอง
import Image from 'next/image'import hero from './hero.png'
export default function Page() { return <Image src={hero} alt="Product hero shot" />}width, height และ priority
หัวข้อที่มีชื่อว่า “width, height และ priority”image ที่ Next.js เดาขนาดไม่ได้ — เช่น remote URL — คุณ ต้อง ส่ง width กับ height ค่าสองตัวนี้จองกล่องขนาดเป๊ะไว้ก่อน pixel จะมาถึง ซึ่งคือสิ่งที่กัน Cumulative Layout Shift ใส่ priority ให้ image ตัวที่เป็น Largest Contentful Paint เพื่อให้ Next.js preload ภาพนั้นและข้าม lazy-load
// Remote image: width + height are required to reserve spaceimport Image from 'next/image'
export default function Avatar() { return ( <Image src="https://cdn.example.com/avatar.png" alt="User avatar" width={64} height={64} priority // preload the LCP image, skip lazy-loading /> )}เมื่อไม่รู้ขนาดจริง ๆ ใช้ fill ภายใน parent ที่ตั้ง position ไว้ แล้วปล่อยให้ CSS จัดการขนาดกล่องแทน
// Unknown dimensions: use fill inside a positioned parent<div style={{ position: 'relative', width: 400, height: 300 }}> <Image src={src} alt="" fill sizes="400px" style={{ objectFit: 'cover' }} /></div>remote image ต้องมี remotePatterns
หัวข้อที่มีชื่อว่า “remote image ต้องมี remotePatterns”การ optimize external URL ตามใจชอบเท่ากับเปิด open proxy Next.js จึงปฏิเสธจนกว่าคุณจะ allowlist host นั้น ประกาศ images.remotePatterns ใน next.config และระบุให้เจาะจงที่สุดเท่าที่ทำได้
import type { NextConfig } from 'next'
const nextConfig: NextConfig = { images: { remotePatterns: [ { protocol: 'https', hostname: 'cdn.example.com', pathname: '/**' }, ], },}
export default nextConfignext/font self-host ตอน build
หัวข้อที่มีชื่อว่า “next/font self-host ตอน build”next/font ดาวน์โหลดไฟล์ font ตอน build แล้วเสิร์ฟจาก origin ของคุณเอง ไม่มี request ตอน runtime ไป Google และเพราะรู้ metric ของ font ล่วงหน้า จึงจองพื้นที่ได้ถูกต้องและได้ layout shift เป็นศูนย์
// app/layout.tsx — self-hosted, zero layout shift, no request to Googleimport { Inter } from 'next/font/google'import localFont from 'next/font/local'
const inter = Inter({ subsets: ['latin'], display: 'swap' })const brand = localFont({ src: './brand.woff2' })
export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en" className={inter.className}> <body className={brand.className}>{children}</body> </html> )}flowchart LR Src[Source asset] --> Build[Build step] Build --> Opt["Resized, WebP/AVIF, self-hosted font"] Opt --> Reserve["width + height reserve space"] Reserve --> Page["No layout shift, fast LCP"]