Skip to content
CodingThailand's Blog
CodingThailand's Blog

by โค้ชเอก

  • Home
  • About Me
  • CodingThailand.com
CodingThailand's Blog

by โค้ชเอก

การใช้งาน Prefetching ใน Next.js

17/07/202517/07/2025

การดึงข้อมูลล่วงหน้า (Prefetching) ช่วยให้การนำทางระหว่างเส้นทาง (routes) ต่าง ๆ ภายในแอปพลิเคชันให้ความรู้สึกเหมือนเป็นแบบทันที

.

Next.js จะพยายามดึงข้อมูลล่วงหน้าอย่างชาญฉลาดโดยอัตโนมัติ โดยอิงจากลิงก์ที่ใช้ในโค้ดแอปพลิเคชันของเรา

.

การทำงานของ Prefetching คืออะไร?

เมื่อมีการนำทางระหว่างเส้นทาง (routes) เบราว์เซอร์จะร้องขอ asset ที่จำเป็นสำหรับหน้า เช่น ไฟล์ HTML และ JavaScript การ prefetching คือกระบวนการร้องขอ resource เหล่านี้ล่วงหน้า ก่อน ที่จะมีการนำทางไปยัง route ใหม่

.

Next.js จะแบ่งแอปพลิเคชันออกเป็น JavaScript chunks ขนาดเล็กตามเส้นทาง แทนที่จะโหลดโค้ดทั้งหมดตั้งแต่ต้นเหมือน SPA แบบเดิม ๆ จะโหลดเฉพาะโค้ดที่จำเป็นสำหรับ route ปัจจุบันเท่านั้น ซึ่งจะช่วยลดเวลาโหลดเริ่มต้น ในขณะที่ส่วนอื่นของแอปจะถูกโหลดแบบเบื้องหลัง เมื่อผู้ใช้คลิกลิงก์ resource สำหรับเส้นทางใหม่ก็ถูกโหลดไว้ในแคชของเบราว์เซอร์แล้ว

.

ดังนั้น เมื่อมีการนำทางไปยังหน้าใหม่ จะไม่มีการ reload หน้าแบบเต็มหรือเห็น loading spinner ของเบราว์เซอร์ Next.js จะทำการเปลี่ยนหน้าแบบ client-side ซึ่งให้ประสบการณ์การใช้งานที่รวดเร็วเหมือนเป็นแอปพลิเคชันแบบ SPA

.

ในระหว่างการนำทางครั้งแรก เบราว์เซอร์จะโหลด HTML, JavaScript และ React Server Components (RSC) Payload สำหรับการนำทางถัดไป เบราว์เซอร์จะโหลดเฉพาะ RSC Payload ของ Server Components และ JS bundle ของ Client Components

.

การทำงานของ prefetching ที่ใช้งานที่บ่อยๆ ได้แก่

.

1. การ prefetch อัตโนมัติ (Automatic prefetch)

ตัวอย่าง:

import Link from ‘next/link’

export default function NavLink() {

return <Link href=”/about”>About</Link>

}

.

Context: หากไม่มี loading.js จะ prefetch ทั้งหน้า

Prefetched payload: ทั้งหน้า

Client Cache TTL: จนกว่าแอปจะ reload ใหม่

หากมี loading.js จะ prefetch เฉพาะ layout จนถึง loading boundary แรก (ค่า TTL 30 วินาที – สามารถปรับแต่งได้)

.

หมายเหตุ:

Automatic prefetching จะทำงานเฉพาะในโหมด production เท่านั้น สามารถปิดด้วย prefetch={false} หรือใช้ wrapper

.

2. การ prefetch แบบกำหนดเอง (Manual prefetch)

สามารถเรียกใช้ router.prefetch() เพื่อสร้างเส้นทางที่อยู่นอก viewport หรือเพื่อตอบสนองต่อ event ต่าง ๆ เช่น การวิเคราะห์ข้อมูล, การ hover, การ scroll เป็นต้น

ตัวอย่าง:

‘use client’

import { useRouter } from ‘next/navigation’

const router = useRouter()

router.prefetch(‘/pricing’)

.

3. Prefetch เมื่อ hover (Hover-triggered prefetch)

การขยาย Link ด้วยตัวเองหมายถึงเราต้องรับผิดชอบในเรื่อง prefetching, การ invalidation ของ cache และการเข้าถึงสำหรับผู้ใช้ (Accessibility) ควรใช้เฉพาะกรณีที่ default ยังไม่เพียงพอ

ตัวอย่างเมื่อเราต้องการ prefetch เมื่อ hover (แทนที่จะ prefetch เมื่อเข้า viewport ตามปกติ):

‘use client’

import Link from ‘next/link’

import { useState } from ‘react’

export function HoverPrefetchLink({

href,

children,

}: {

href: string

children: React.ReactNode

}) {

const [active, setActive] = useState(false)

return (

<Link

href={href}

prefetch={active ? null : false}

onMouseEnter={() => setActive(true)}

>

{children}

</Link>

)

}

prefetch={null} จะคืนค่า default prefetching (แบบ static) เมื่อตรวจพบ user intent (เมื่อ hover)

.

4. การขยายหรือปรับแต่ง Link (Extending or ejecting link)

เราสามารถขยาย <Link> เพื่อกำหนดกลยุทธ์ prefetching ของเราเอง เช่น ใช้ไลบรารีอย่าง ForesightJS เพื่อ prefetch link โดยทำนายทิศทางของเมาส์

หรือใช้ useRouter เพื่อสร้างพฤติกรรมบางอย่างของ <Link> เอง (แต่เราจะต้องรับผิดชอบเรื่อง prefetch และ cache ด้วยตัวเอง):

‘use client’

import { useRouter } from ‘next/navigation’

import { useEffect } from ‘react’

function ManualPrefetchLink({

href,

children,

}: {

href: string

children: React.ReactNode

}) {

const router = useRouter()

useEffect(() => {

let cancelled = false

const poll = () => {

if (!cancelled) router.prefetch(href, { onInvalidate: poll })

}

poll()

return () => {

cancelled = true

}

}, [href, router])

return (

<a

href={href}

onClick={(event) => {

event.preventDefault()

router.push(href)

}}

>

{children}

</a>

)

}

.

onInvalidate จะถูกเรียกเมื่อ Next.js พบว่า cached data เริ่มหมดอายุ เราสามารถ refresh prefetch ได้

หมายเหตุ: การใช้ <a> tag จะทำให้เกิดการนำทางหน้าใหม่เต็มรูปแบบ เว้นแต่เราจะใช้ event.preventDefault() และ router.push() แทน

.

5. การปิด prefetch (Disabled prefetch)

เราสามารถปิด prefetch สำหรับบาง route ได้ เพื่อควบคุมการใช้ resource ให้เหมาะสม

ตัวอย่าง:

‘use client’

import Link, { LinkProps } from ‘next/link’

function NoPrefetchLink({

prefetch,

…rest

}: LinkProps & { children: React.ReactNode }) {

return <Link {…rest} prefetch={false} />

}

.

กรณีนี้เหมาะกับการใช้ลิงก์ใน footer หรือส่วนที่ไม่จำเป็นต้อง prefetch

.

การแก้ไขปัญหา (Troubleshooting)

Side-effect ที่ไม่พึงประสงค์ระหว่าง prefetch

ถ้า layout หรือหน้าเพจของเรามี side-effect (เช่น track analytics) สิ่งเหล่านี้อาจจะถูก trigger ตั้งแต่ตอน prefetch ไม่ใช่ตอนผู้ใช้เข้าจริง

แนวทางแก้ไข:

ควรย้าย side-effect ไปไว้ใน useEffect hook หรือ Server Action ที่ trigger จาก Client Component

ก่อนแก้ไข:

import { trackPageView } from ‘@/lib/analytics’

export default function Layout({ children }: { children: React.ReactNode }) {

// เรียกใช้งานตั้งแต่ตอน prefetch

trackPageView()

return <div>{children}</div>

}

.

หลังแก้ไข:

app/ui/analytics-tracker.tsx

‘use client’

import { useEffect } from ‘react’

import { trackPageView } from ‘@/lib/analytics’

export function AnalyticsTracker() {

useEffect(() => {

trackPageView()

}, [])

return null

}

app/dashboard/layout.tsx

import { AnalyticsTracker } from ‘@/app/ui/analytics-tracker’

export default function Layout({ children }: { children: React.ReactNode }) {

return (

<div>

<AnalyticsTracker />

{children}

</div>

)

}

.

การป้องกัน prefetch ที่มากเกินไป

Next.js จะ prefetch ลิงก์ใน viewport อัตโนมัติเมื่อใช้ <Link> component หากมีลิงก์จำนวนมาก (เช่น infinite scroll table) อาจต้องการปิด prefetch เพื่อลด resource

ตัวอย่าง:

<Link prefetch={false} href={`/blog/${post.id}`}>

{post.title}

</Link>

ในกรณีนี้ route แบบ static จะถูกโหลดเมื่อคลิกเท่านั้น และ dynamic routes จะรอการ render จาก server ก่อนนำทาง

หากต้องการลดการใช้ resource โดยไม่ปิด prefetch ทั้งหมด สามารถใช้แนวทาง prefetch เมื่อ hover (target เฉพาะลิงก์ที่ user มีแนวโน้มจะคลิก):

‘use client’

import Link from ‘next/link’

import { useState } from ‘react’

export function HoverPrefetchLink({

href,

children,

}: {

href: string

children: React.ReactNode

}) {

const [active, setActive] = useState(false)

return (

<Link

href={href}

prefetch={active ? null : false}

onMouseEnter={() => setActive(true)}

>

{children}

</Link>

)

}

.

สรุป Next.js ให้ความยืดหยุ่นในการจัดการ prefetch เพื่อสร้างประสบการณ์ผู้ใช้ที่เร็วและลื่นไหล พร้อมทั้งมีทางเลือกในการปรับแต่งและป้องกันปัญหาที่อาจเกิดจากการ prefetch มากเกินไป ลองเอาไปใช้ดูนะครับ

Views: 11

Next.js

Post navigation

Previous post

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Posts ล่าสุด

  • การใช้งาน Prefetching ใน Next.js
  • 14 ข้อคิด เพื่อการเป็น Developer ที่ดีขึ้น จาก “Lee Robinson”
  • เคยเจอ “TypeError: Cannot read property ‘x’ of undefined” หรือเปล่า
  • บันทึกการเขียนเว็บไซต์ใหม่ในรอบ 10 ปี ย้ายมาใช้ Next.js
  • ทำไมการจัดการ Error ใน JavaScript ถึงเป็นเรื่องท้าทาย?

Recent Comments

    หมวดหมู่

    • .NET
    • AI
    • Android
    • Angular
    • Angular 2
    • Coding
    • CSS
    • Database
    • Editor
    • Flutter
    • Git
    • HTML5
    • Ionic 2
    • Ionic 4
    • Ionic Framwork
    • JavaScript
    • Laravel
    • Laravel 5
    • Next.js
    • Node.js
    • PHP
    • PHP 7
    • Plugins
    • React
    • React Native
    • Template
    • Tools
    • TypeScript
    • UI
    • Uncategorized
    • Vue.js
    • XAMPP
    • Yii
    • คอร์สเรียน
    • แรงบันดาลใจ

    Archives

    • July 2025
    • April 2025
    • November 2024
    • October 2024
    • April 2020
    • February 2020
    • August 2019
    • September 2018
    • August 2018
    • February 2018
    • November 2017
    • October 2017
    • August 2017
    • July 2017
    • April 2017
    • October 2016
    • August 2016
    • May 2016

    Tags

    .NET android Angular Angular 2 Atom Coding Coding Standard CSS CSS 3 Datepicker Express.js extensions Git HTML HTML5 Ionic2 JavaScript Laravel5 laravel 5.5 MariaDB Material Design MySQL Node.js npm PHP PHP7 plugins PouchDB recaptcha Restful sail.js template typescript typscript XAMPP Yii2

    ผู้เยี่ยมชม

    • 0
    • 1,818,149
    • 547,558
    • 11
    ©2025 CodingThailand's Blog | WordPress Theme by SuperbThemes