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

การดึงข้อมูลล่วงหน้า (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 มากเกินไป ลองเอาไปใช้ดูนะครับ

14 ข้อคิด เพื่อการเป็น Developer ที่ดีขึ้น จาก “Lee Robinson”

ข้อคิด เพื่อการเป็น Developer ที่ดีขึ้น จาก “Lee Robinson” ผู้ช่วยให้ Next.js มีผู้ใช้ทั่วโลก 1.3 ล้านคน และช่วยให้ Vercel กลายเป็น Unicorn

.

1. ความเร็วสำคัญกว่ากลยุทธ์ที่ดีที่สุด

การลงมือส่งมอบงานอย่างรวดเร็ว (“Shipping fast”) ดีกว่าการมัวแต่หากลยุทธ์ที่สมบูรณ์แบบ

ความเร็ว (Speed) คือจุดแข็งที่สร้างความได้เปรียบ

.

2. สร้างนิสัยรักการส่งมอบงาน

ต้องมี “bias toward shipping” คือเน้นการลงมือและนำของจริงออกมาใช้หรือให้คนใช้

ทีมขนาดเล็ก (Small teams) ส่งมอบงานได้เร็วกว่า

ทีมที่ใช้ AI เต็มรูปแบบ (“AI-native”) จะขยับตัวเร็วกว่า 10 เท่าเมื่อเทียบกับทีมที่ไม่ปรับตัว

.

3. การใช้งานจริงสำคัญกว่าการเปิดตัว

Landings > Launches: การที่คนมาใช้งานจริงสำคัญกว่าการเปิดตัวโปรเจกต์เฉย ๆ

ฟังลูกค้า สร้าง ส่งมอบ แจ้งลูกค้า แล้วทำซ้ำไปเรื่อย ๆ

.

4. ศักยภาพไร้ขีดจำกัด

ไม่มีเพดานอาชีพ (You have no career ceiling)

ความมุ่งมั่นและความอุตสาหะ (Grit) สำคัญกว่าพรสวรรค์ (Talent)

ไม่มีสิ่งใดมาแทนที่การลงมือทำซ้ำ ๆ (Putting in the hours)

พัฒนาให้ดีขึ้นวันละ 1% (“Get 1% better every day”)

.

5. การแสวงหาความจริงอย่างเข้มงวด

“Ruthlessly truth seeking”: ต้องหาความจริง แม้บางครั้งความจริงจะเจ็บปวด

พร้อมเปลี่ยนใจเมื่อรู้ว่าตัวเองผิด (You can just change your mind if wrong)

มีความเห็นที่ชัดเจนแต่ไม่ยึดติดเกินไป (Strong opinions, loosely held)

.

6. การเรียนรู้จากประสบการณ์และผู้อื่น

เพิ่มชั่วโมงแห่งการเปิดรับ (Maximize your exposure hours)

ข้อมูลจากประสบการณ์ (Anecdata) สำคัญกว่าข้อมูลเชิงสถิติ (Data) ในบางบริบท

แสวงหาความจริงจากหลายมุมมอง (Seek the collective truth)

.

7. การสื่อสารคือหัวใจของงาน

งานของเราคือ “การสื่อสาร” (Communication is the job)

การเขียนที่ชัดเจนแปลว่าคิดอย่างชัดเจน (Clear writing is clear thinking)

ทุกคนควรพัฒนาทักษะการเขียนให้ดีขึ้น

ผู้นำต้องสร้างความชัดเจนโดยเฉพาะเวลาที่ทีมสับสน

เป็นคนจดโน้ตในที่ประชุม แม้จะจดไว้ใช้เองก็ยังดี

.

8. การจัดการความคาดหวังและความสัมพันธ์ในทีม

ความคาดหวังที่ไม่ตรงกันนำไปสู่ความผิดหวัง

เวลาจะส่งข้อความใน Slack ให้คาดเดาคำถาม/ข้อโต้แย้งล่วงหน้าแล้วตอบไว้เลย

.

9. การศึกษาและการตลาดสำหรับนักพัฒนา

การศึกษา คือรูปแบบการตลาดที่ดีที่สุดสำหรับ Developer

จงจริงใจและยอมรับข้อผิดพลาดของตัวเอง

ไม่ควรใช้คำว่า “webinar” อีกต่อไป

.

10. ความช่วยเหลือและการเป็นผู้นำ

การช่วยเหลือเล็กน้อยอย่างต่อเนื่อง สะสมกลายเป็นอิทธิพลมหาศาล

ความเป็นผู้นำคือการรับผิดชอบต่อผลลัพธ์ ไม่ใช่แค่บทบาทในโครงสร้างองค์กร

อิทธิพลสำคัญกว่าตำแหน่ง

ผู้นำต้องลงมือทำเองและรู้จักมอบหมาย

เขียน playbook ของตัวเองจากการศึกษาแนวทางของคนอื่น แล้วประยุกต์ให้เหมาะกับตัวเอง

.

11. Passion, Work & Life

งานสามารถเป็นงานอดิเรกได้ แต่ก็ควรมีขอบเขต

“Passion + Boundaries” สำคัญกว่าความสมดุลชีวิต-งานแบบในอุดมคติ

งานที่ดีที่สุดมักเกิดจากความอยากรู้อยากเห็นของตัวเอง

.

12. การแสดงออกด้วยการลงมือทำ

สาธิตให้ดู (Demo) ดีกว่าเขียนบันทึก (Memo)

ในที่ประชุม บางทีคุณควรทำ prototype จริงได้เลย

ส่งมอบเฉพาะสิ่งที่ตัวเองรู้สึกตื่นเต้น

.

13. การจ้างงานและการสร้างทีม

การจ้างคนคือสิ่งที่แยกผู้นำดีออกจากผู้นำที่ยอดเยี่ยม

เวลาจ้างงาน ต้องตอบในใจว่า “ใช่เลย!” (Hell yes) หรือ “ไม่ใช่” (No) เท่านั้น

ศักยภาพการเติบโตสำคัญกว่าความสามารถปัจจุบัน

ควรจ้างคนที่คุณจะได้เรียนรู้ด้วย

ควรจ้างคนที่วันหนึ่งคุณอยากทำงานร่วมด้วยในอนาคต

คำถามสัมภาษณ์ที่ชอบ: “งานไหนที่คุณภูมิใจที่สุด?”

.

14. การนำทีมและวัฒนธรรม

พยายามมองเจตนาดีของคนอื่นเสมอ

เป็นผู้นำด้วยความเห็นอกเห็นใจ (Empathy)

อาจมีบางวันที่คนในทีมเจอวันที่แย่

คำวิจารณ์คือ feedback ที่ดี ถ้าฟังแบบไม่ใช้อารมณ์

.

ผมคิดว่ามีประโยชน์ลองเอาไปปรับใช้ดูนะครับ

เคยเจอ “TypeError: Cannot read property ‘x’ of undefined” หรือเปล่า

เปลี่ยนจากใช้ && แบบเดิมเป็น ?. (Optional Chaining) ดีกว่าไหม ทำให้โค้ดสะอาดและบำรุงรักษาง่ายกว่า

.

ปัญหาที่เจอบ่อย เวลาเข้าถึง property หลายชั้นใน Object ของ JavaScript มักเจอ TypeError: Cannot read property ‘x’ of undefined เราต้องเขียนโค้ดป้องกันซ้ำ ๆ เช่น

if (user && user.profile && user.profile.avatar) { … }

.

วิธีนี้ใช้ได้ผลปกติ แต่ลองมาใช้ Optional Chaining (?.) จะดีกว่าไหม

การใช้ user?.profile?.avatar จะหยุดทำงานทันทีหากค่าก่อนหน้าเป็น null หรือ undefined และคืนค่า undefined แทนการโยน Error วิธีนี้จะทำให้โค้ดสั้น อ่านง่าย และดูแลรักษาง่ายขึ้นครับ

ตัวอย่างการใช้งานจริง ดูในรูปนะครับ

.

นอกจากนี้ยังสามารถใช้งานร่วมกับ Nullish Coalescing (??) ได้ด้วย เช่น

const avatar = user?.profile?.avatar ?? ‘default.png’;

ให้ค่าเริ่มต้นเมื่อผลเป็น null | undefined

.

ข้อจำกัดและข้อควรระวัง

ถ้าค่าก่อนหน้าเป็น false, 0 หรือ ” มันจะยังไม่หยุดมันจะทำต่อ! การใช้มากเกินไปอาจซ่อนบั๊กหรือข้อบ่งชี้ว่าการออกแบบข้อมูลนั้นควรถูกปรับใหม่ และเราต้องใส่ ?. ให้ครบทุกระดับ เช่น user?.profile?.avatar ไม่ใช่ user?.profile.avatar แบบนี้

.

สรุป การใช้ Optional Chaining จะช่วยลดบรรทัดโค้ด ป้องกัน Error อ่านง่าย ชัดเจน เพิ่มความเสถียรของแอป โดยเฉพาะเมื่อข้อมูลไม่แน่นอนหรือมีโหลดแบบไดนามิก

.

การรองรับเบราว์เซอร์

ใช้งานได้ใน Chrome 80+, Firefox 74+, Safari 13.1+, Edge 80+

หากต้องรองรับ IE ให้ใช้ Babel ปลั๊กอิน เช่น @babel/plugin-proposal-optional-chaining

.

ใครมีโค้ดเก่าที่ใช้ && ยาวๆ ลองรีแฟกเตอร์ให้เป็น ?. ดูนะครับ โค้ดน่าจะสะอาดขึ้น อ่านง่าย และบำรุงรักษาง่ายกว่าเดิม

บันทึกการเขียนเว็บไซต์ใหม่ในรอบ 10 ปี ย้ายมาใช้ Next.js

1. โจทย์ คือ อยากได้เว็บใหม่ที่ผู้ใช้ต้องสามารถตรวจสอบคอร์สเรียนได้(คอร์สหลังๆ ผมส่งให้ทางเมล) และต้องทำให้เสร็จภายใน 2 สัปดาห์ เพราะผมติดสอน และต้องเปิดคอร์สใหม่ และต้องย้ายอีเมลของ user จากระบบเดิมกว่า 10,000 อีเมล มาฐานข้อมูลใหม่ และยังมีระบบ API เดิมที่ยังย้ายไม่ได้แต่ต้องใช้ต่อเนื่องด้วย คือย้ายบางส่วนก่อน บางส่วนจะทยอยย้าย

2. เว็บเดิมเขียนด้วย PHP (ใช้ Yii Framework 1.x) ใช้มามากกว่า 10 ปี เดิมใช้ฐานข้อมูล MySQL เวอร์ชัน 5.x เพิ่งอัปเกรดเป็น 8.x เมื่อต้นปี 2025 นี้

3. ส่วนเวอร์ชันของ PHP เว็บเดิม เวอร์ชัน 5.x เพิ่งอัปเกรดมาเป็น 7.4 เมื่อต้นปี 2025 แต่ก็ end of life ไปแล้ว ตอนแรกจะอัปเกรดไป 8.x แต่ก็ไม่ได้ เพราะระบบ API ฟรีที่ใช้สอน ยังเป็น Laravel เวอร์ชันเก่ามาก (5.x)

4. ตัดสินใจเขียนใหม่ดีกว่า โดยเลือกฟีเจอร์ที่จำเป็นก่อน เลือกใช้ Next.js 15.x ล่าสุด เขียนแบบ full-stack และเนื่องจากต้องรองรับ SEO ด้วย ก็ต้องเขียนโค้ดในส่วนของฟังก์ชัน generateMetadata จาก Database และทำ openGraph เพื่อรองรับ Social Media Sharing เช่น facebook ด้วย

5. ในส่วนหน้าตาของเว็บใหม่ ใช้ shadcn ui (Tailwind CSS 4.x) https://ui.shadcn.com/ เพื่อสร้าง React UI Component เพื่อความรวดเร็ว และไม่ต้องตกแต่งอะไรมากนัก

6. ย้ายฐานข้อมูลบางส่วนจาก MySQL จากระบบเดิม (ติดตั้งเอง ไม่ใช้ Docker) มาเป็น Supabase (Postgres) https://supabase.com/ แทน ไม่ต้องติดตั้งเอง ตอนนี้ใช้เวอร์ชันฟรีอยู่

7. ส่วนระบบ Authentication ในเว็บ ใช้ของ Supabase Auth เช่นเดียวกัน ไม่ต้องออกแรงเยอะ แต่ต้องย้ายอีเมลกว่า 10,000 records จาก MySQL มายัง Supabase ใช้วิธีการสร้างตารางผู้ใช้ชั่วคราว (temp table) แล้วเขียน script import ไปยัง Supabase Auth อีกที (ตอนนี้คนที่เคยซื้อคอร์สกับผมไปแล้ว สามารถเข้าไป reset รหัสผ่านได้นะครับ)

8. ในหน้าเพจระบบ Authentication ใช้ https://supabase.com/ui ซึ่งบอกว่าสบายมาก เอามาปรับแต่งนิดหน่อยก็ได้หน้าเพจ Sign In, Sign Up, Forgot Password, Update Profile ที่เขียนไว้ใช้กับ Next.js ได้เลย ไม่ต้องเขียนเอง แค่ปรับแก้เล็กน้อย

9. Icon ที่เป็น brand ดังๆ ที่อยู่ในหน้าแรกใช้ของ https://simpleicons.org

10. ระบบส่งเมลใช้ของ https://resend.com/ ตอนนี้ก็ยังใช้เวอร์ชันฟรีอยู่ ใช้ฟรี 100 เมลต่อวัน และ 3,000 เมลต่อเดือน ส่วน React Component หน้าตาของเมลที่ส่งหาทุกคน ใช้ของ https://react.email/

11. ในส่วนของ Hosting ใช้ของ https://vercel.com/ และก็ฟรีอยู่เช่นเดียวกัน มี https ฟรี เอา domain เก่ามาใช้ได้เลย ผมเก็บโค้ดไว้ที่ GitLab ก็ให้ Vercel ทำ CI/CD ดึง production branch มา Deploy Production ให้เลยครับ (นั่งจิบกาแฟรอ)

สรุป ณ​ ตอนนี้เว็บใหม่ที่ทุกคนเห็นยังใช้เงิน 0 บาท และมีฟีเจอร์หลักๆ ที่ต้องการแล้ว และตอนนี้กำลังทยอยอัปเดตข้อมูลคอร์สต่างๆ ให้ผู้เรียนได้มองเห็นที่หน้า Dashboard อยู่ครับ

ใครสนใจเยี่ยมชมได้ที่นี่ครับ https://www.codingthailand.com/

หรือมีอะไรสอบถามก็ถามมาได้ครับ

ทำไมการจัดการ Error ใน JavaScript ถึงเป็นเรื่องท้าทาย?

– Error Handling เป็นเรื่องใหญ่ เพราะในซอฟต์แวร์จริง ทุกอย่างมีโอกาสผิดพลาด เช่น network ล่ม, ข้อมูลไม่ครบ ฯลฯ

.

– การจัดการ error ที่ดีจะช่วยให้แอปไม่ crash เฉย ๆ แต่แจ้ง error ที่เข้าใจง่ายกับผู้ใช้ และ log ข้อมูลที่เป็นประโยชน์กับ dev

.

– พื้นฐานของ Error Handling ใน JavaScript

เครื่องมือหลักคือ try…catch, throw และ Error object

.

– Error ที่ไม่ถูก catch จะ “bubble” (ลอยขึ้นบน) ไปถึง global scope แล้วทำให้แอปหยุดหรือแสดง warning

.

– ถ้าเป็น async (Promise/async-await) ก็ใช้ .catch() หรือใส่ try…catch รอบ await

.

– ข้อควรระวังและจุดอ่อนของ JavaScript

JS สามารถ throw อะไรก็ได้ (string, number, object…) ไม่จำเป็นต้องเป็น Error ทำให้ใน catch อาจจะเจออะไรก็ได้ ต้องตรวจสอบเอง

.

– TypeScript ก็ช่วยไม่ได้มาก เพราะไม่สามารถรู้ได้ว่า error ที่ throw จะเป็นชนิดอะไร ต้องใช้ unknown หรือ any

.

– หลาย ๆ ไลบรารี (เช่น Supabase) เปลี่ยนจาก throw มาเป็น return object ที่มี error property แทน ซึ่งควบคุมได้ง่ายกว่า

.

– โค้ด Utility ง่าย ๆ ที่ใช้ได้จริง (ดีและ practical สำหรับโปรเจกต์ JavaScript/TypeScript ทั่วไป)

parseError: รับ error (unknown) แล้ว return เป็นข้อความ string ที่อ่านเข้าใจง่ายเสมอ ตัวอย่างโค้ด

export const parseError = (error: unknown) => {

if (typeof error === ‘string’) {

return error;

}

if (error instanceof Error) {

return error.message;

}

return ‘An error occurred’;

};

handleError: เรียก parseError แล้วเอาไปโชว์ toast/error UI (หรือจะ log ก็ได้) ตัวอย่างโค้ด

import { toast } from ‘sonner’;

import { parseError } from ‘./parse’;

export const handleError = (title: string, error: unknown) => {

const description = parseError(error);

toast.error(title, { description });

};

ตัวอย่าง การใช้กับ try / catch

import { handleError } from ‘@/lib/error/handle’;

try {

throw new Error(‘Something went wrong’);

} catch (err) {

handleError(‘Something went wrong’, err);

}

.

ตัวอย่างการใช้กับ promise chains

import { handleError } from ‘@/lib/error/handle’;

fetch(‘https://api.example.com/data‘)

.then((response) => response.json())

.then(console.log)

.catch(handleError);

.

– ความคิดเห็นจาก dev สายต่าง ๆ

1. Just Use Try/Catch

หลายคนบอกว่า try/catch ธรรมดาก็พอแล้ว

ส่วนมากนิยมจับ error แค่ในจุดบน ๆ ของแอป เช่น React Error Boundary หรือ Express middleware แล้วให้ error bubble ขึ้นมา

2. neverthrow

ไลบรารีที่เอา pattern แบบ Rust (Result/Ok/Err) มาใช้ใน TypeScript

ทุก function จะ return ว่าผ่าน/ไม่ผ่านแบบชัดเจน ต้อง handle error case ทุกครั้ง

ปลอดภัย, type-safe, explicit แต่โค้ดจะ verbose ขึ้น และมี dependency

3. Effect

เป็น functional effect system ที่จัดการ error, async, dependency ฯลฯ แบบ Haskell/Scala

Error type ถูก track ใน type system – ไม่ handle ครบ, โค้ดไม่ compile

เหมาะกับโค้ดฐานใหญ่ ๆ, ต้องการความ robust, แต่ “หนัก” มาก ไม่เหมาะเอามาใส่เล่น ๆ

ทำไมถกกันไม่จบ?

JavaScript ยืดหยุ่นสูง throw อะไรก็ได้ ไม่ force dev ให้ระบุ error ชนิดไหน

TypeScript ก็ไม่ได้ช่วยด้านนี้มากนัก เพราะทีมงานคิดว่าไม่เหมาะจะใส่ checked exception/throws keyword ในภาษา

สุดท้าย ไม่มีวิธีไหน “ถูก” หรือ “ผิด” เสียทีเดียว

.

ข้อแนะนำสรุปสำหรับ dev

1. เริ่มจากพื้นฐาน ใช้ try/catch ให้ถูกที่ อย่าปล่อยให้ error เงียบ

2. ตั้งกติกาทีม เช่น ห้าม throw string, ต้องใช้ utility เดียวกัน, ต้อง log error เสมอ ฯลฯ

3. ใช้ utility function (อย่าง parseError/handleError) หรือพิจารณา lib เสริมเช่น neverthrow/Effect ถ้าตรงกับ use case

4. สำคัญที่สุดคืออย่าปล่อย error เงียบ จะใช้วิธีไหนก็ได้ ขอแค่มีแนวทางและใช้สม่ำเสมอ

.

การจัดการ error ไม่มีวิธีที่ “ดีที่สุด” แต่สิ่งที่แย่ที่สุดคือไม่จัดการอะไรเลย

มีอะไรใหม่ใน Angular v20

1. Signals, effect, linkedSignal, toSignal เป็นมีสถานะเป็น stable แล้ว!

2. Zoneless mode เข้าสู่สถานะ developer preview (ไม่ต้องใช้ zone.js อีกต่อไป)

3. แนะนำใช้ control flow แบบใหม่ @if, @for, @switch แทน *ngIf, *ngFor, *ngSwitch แบบเดิมเพราะจะเอาออกแล้วใน v22 ครับ

คำสั่งในการอัปเกรดอัตโนมัติ

ng generate @angular/core:control-flow

4. รองรับ hot module replacement (HMR) ใน templates โดย เปิดใช้งานแบบ default

5. เพิ่ม type checking และ editor support สำหรับ host bindings

6. รองรับ operator ใหม่ใน template คือ ** (คือ ยกกำลัง) และ in เพื่อตรวจสอบ property ใน object ว่ามีไหม

7. รองรับ untagged template literals เช่น `layout col-${colWidth}`

8. resource และ httpResource สำหรับ state management แบบ reactive ด้วย Signal เป็นสถานะเป็น experimental แล้ว

9. ทดลองรองรับ Vitest แทน Karma แบบเดิม

10. เปลี่ยน Style Guide แบบใหม่ เช่น ไม่บังคับให้ใช้ suffix เช่น Component, Directive แล้ว

11. รองรับ GenAI มากขึ้น สร้างไฟล์ llms.txt ให้ LLMs ใช้เพื่อ generate โค้ด Angular ที่ถูกต้อง

12. เปิดให้ชุมชนโหวตตัวมาสคอต Angular ตัวแรก ใครสนใจลองไปโหวตได้ครับ

สรุป Angular v20 ถือเป็นการปิดงานใหญ่ในรอบหลายปี เช่น Signals, SSR, Zoneless และเริ่มต้นยุคใหม่ของ Angular แบบจริงจังแล้วครับ

สรุป 8 Best Practices สำหรับการออกแบบ “Function Calling” หรือ “Tool Calling” เพื่อใช้กับ LLM

คนที่เรียนหลักสูตร AI API กับผมไปแล้วคงได้เขียนโค้ดในหัวข้อของ function calling กันมาบ้าง วันนี้เลยเอา best practices เกี่ยวกับการออกแบบ Function Calling หรือ Tool Calling มาให้อ่านกันครับ

.

1. Function Description

ให้ระบุคำอธิบายของฟังก์ชันและพารามิเตอร์ให้ “ชัดเจนและเฉพาะเจาะจง” มากที่สุด เพราะ LLM จะอาศัยคำอธิบายเหล่านี้ในการเลือกฟังก์ชันที่ถูกต้องและป้อน argument ที่เหมาะสม (สำคัญมาก)

ลองใช้ค่า temperature ต่ำ (เช่น 0) เพื่อให้โมเดลเลือกฟังก์ชันได้อย่างแน่นอนและสม่ำเสมอ

.

2. Naming

การตั้งชื่อ ใช้ชื่อฟังก์ชันที่บ่งบอกถึงหน้าที่ชัดเจน หลีกเลี่ยงการใช้ space (เว้นวรรค), จุด (.) หรือขีด (-) ในชื่อ

.

3. Strong Typing

ควรกำหนดชนิดข้อมูลของพารามิเตอร์ให้เจาะจง เช่น integer, string, enum เป็นต้น (จะใช้ TypeScript ก็ได้) ถ้าพารามิเตอร์มีค่าให้เลือกจำกัด ให้ใช้ enum จะช่วยลดข้อผิดพลาดได้

.

4. Tool Selection

การเลือกเครื่องมือ แม้ว่า LLM model จะสามารถใช้เครื่องมือได้จำนวนมาก แต่ถ้ามีเครื่องมือ (tools) เยอะจนเกินไปก็อาจเสี่ยงให้เลือกผิดหรือเลือกอย่างไม่เหมาะสมได้ เพื่อให้ได้ผลลัพธ์ที่ดี ควรเลือกใช้แค่ tools ที่เกี่ยวข้องกับงานนั้นจริง ๆ

แนะนำให้มี active tools ไม่เกิน 10-20 รายการ

.

5. Prompt Engineering

– ควรระบุบริบทกับโมเดล (model role) เช่น “คุณคือผู้ช่วยพยากรณ์อากาศที่ให้ข้อมูลอย่างละเอียด”

– ให้คำแนะนำว่าให้ใช้ฟังก์ชันเมื่อไหร่ อย่างไร เช่น “ห้ามเดาเวลา ให้ใช้วันที่ในอนาคตเสมอหากดูพยากรณ์อากาศ”

– กระตุ้นให้โมเดลถามกลับเพื่อขอข้อมูลเพิ่มเติมถ้าจำเป็น

.

5. Validation

ถ้าฟังก์ชันนั้นสำคัญหรือมีผลกระทบมาก (เช่น สั่งซื้อของ) ควรให้ผู้ใช้ยืนยันก่อนจะ execute ฟังก์ชันจริง

.

6. Error Handling

ฟังก์ชันควรมีการจัดการข้อผิดพลาดที่ดี ถ้ามี input ที่ไม่ถูกต้อง หรือ API ล้มเหลว ควรคืนข้อความ error ที่มีข้อมูลเพียงพอ เพื่อให้โมเดลนำไปตอบ user ต่อได้อย่างเหมาะสม

.

7. Security

คำนึงถึงความปลอดภัยเวลาเรียก API ภายนอก ใช้ authentication และ authorization ที่เหมาะสม อย่าให้ข้อมูลสำคัญ/ข้อมูลส่วนตัวถูกเปิดเผยใน function call

.

8. Token Limits

คำอธิบายฟังก์ชันและพารามิเตอร์จะนับรวมเป็น input token ของโมเดล ถ้าเจอปัญหา token limit (เช่น prompt ยาวเกิน) ให้ลดจำนวนฟังก์ชันหรือเขียนคำอธิบายให้กระชับลง

ถ้า task ซับซ้อนมาก ให้แยกฟังก์ชันออกเป็นกลุ่มเล็ก ๆ ที่โฟกัสเฉพาะงานย่อย

.

สำหรับคนที่ใช้งาน API ของ LLM เจ้าต่างๆ และใช้ฟีเจอร์ Function calling อย่าลืมเอาหลักการออกแบบไปใช้ในโปรเจคตัวเองได้นะครับ

สรุป 7 ข้อควรรู้ ใน Node.js 24 ใหม่ ไม่แค่การอัปเดตเล็กๆ แต่มีการเปลี่ยนแปลงและเพิ่มฟีเจอร์ใหม่หลายอย่าง

1. อัปเกรด เป็น V8 Engine เป็นเวอร์ชัน 13.6 มีฟีเจอร์สำคัญ ดังนี้

– RegExp.escape: ช่วยให้การ escape regular expression ง่ายและปลอดภัยขึ้น ไม่ต้องเขียนฟังก์ชันเองอีกต่อไป

– Float16Array: Typed array สำหรับจัดการตัวเลขแบบ 16-bit float มีประโยชน์สำหรับงานที่ต้องการประสิทธิภาพ เช่น กราฟิก หรือ ML

– Atomics.pause: หยุด thread ใน Atomics ได้ มีประโยชน์สำหรับงานที่เกี่ยวกับ concurrency ระดับต่ำใน Workers

– WebAssembly Memory64: รองรับหน่วยความจำ 64 บิตใน WebAssembly ทำให้ประมวลผลงานหนักได้มากขึ้น

– await using: ใช้จัดการ resource เช่น ไฟล์ หรือ socket ได้อัตโนมัติเมื่อไม่ใช้งานแล้ว (ดู Explicit Resource Management)

– Error.isError: ช่วยตรวจสอบว่าวัตถุนั้นเป็น Error object จริง ๆ หรือไม่ ใช้งานง่ายขึ้นและปลอดภัยขึ้น

.

2. Permission Model แบบทดลอง (Experimental)

Permission Model ที่เปิดตัวครั้งแรกใน Node.js 20 ตอนนี้เปลี่ยน flag CLI จาก –experimental-permission เป็น –permission แล้ว เป็นสัญญาณว่าฟีเจอร์นี้เริ่มเสถียรมากขึ้น ช่วยเพิ่มความปลอดภัย โดยสามารถจำกัดสิ่งที่ Node.js สามารถเข้าถึงได้ เช่น ไฟล์หรือเครือข่าย เหมาะสำหรับแอป CLI หรือระบบ sandbox (คล้าย Deno)

.

3. URLPattern ใช้งานได้เป็น global แล้ว

API สำหรับจับ URL pattern เช่น routing ตอนนี้สามารถใช้ได้โดยไม่ต้อง import แล้ว (เหมือนกับ URL)

const pattern = new URLPattern({ pathname: ‘/users/:id’ });

เหมาะกับงาน routing หรือจับ URL โดยไม่ต้องใช้ regex เขียนง่าย อ่านง่าย ใช้งานสะดวก

.

4. Built-in Test Runner ดีขึ้น ก่อน Node.js 24 เราต้อง await subtest เอง ไม่งั้นมันอาจยังไม่ทำงานก่อน test จบ

await t.test(‘subtest’, () => { … });

หลัง Node.js 24: ไม่ต้อง await ก็ได้ Subtest จะรันให้ครบก่อนออกจากโปรแกรม

t.test(‘subtest’, () => { … });

เขียนเทสต์ง่ายขึ้น ลดข้อผิดพลาดที่เกิดจากลืม await โดยเฉพาะถ้าเราเพิ่งย้ายจาก framework test อื่น

.

5. HTTP Client มาพร้อมกับ Undici 7.0.0 เวอร์ชันใหม่ มาพร้อมกับการปรับปรุงประสิทธิภาพและรองรับมาตรฐาน HTTP ได้ดีขึ้น เร็วขึ้น ใช้งาน fetch ได้ลื่นไหล และเหมาะกับแอปที่เน้น HTTP request

.

6. npm v11

Node.js 24 มาพร้อม npm v11 ซึ่งมีสิ่งใหม่ดังนี้:

– ติดตั้งแพ็กเกจได้เร็วขึ้น ตรวจสอบความปลอดภัยดีขึ้น CI pipeline เสถียรขึ้น

– รองรับ node ^20.17.0 || >=22.9.0

– npm init เพิ่ม prompt สำหรับชนิดของแพ็กเกจ

– ลบคำสั่ง npm hook และ –ignore-scripts ใช้กับทุก lifecycle script รวม prepare

– ไม่ fallback ไป audit endpoint เก่าแล้ว

.

7. ยกเลิกฟีเจอร์เก่า จะมีฟีเจอร์บางอย่างถูกเลิกใช้ เช่น:

url.parse() → ควรใช้ WHATWG URL API แทน

SlowBuffer, tls.createSecurePair และอื่น ๆ

constants เก่าใน fs อย่าง fs.F_OK กำลังจะหายไป

.

สรุป

Node.js 24 ไม่ใช่แค่การอัปเดตเล็ก ๆ แต่มันเป็นก้าวที่สำคัญในเรื่องประสิทธิภาพ ความปลอดภัย และประสบการณ์ของนักพัฒนา

.

และอย่าลืมว่า Node.js 24 จะกลายเป็น LTS (Long-Term Support) ในเดือนตุลาคม 2025 นี้! ผมว่านี่เป็นเวลาที่ดีในการเริ่มทดสอบและวางแผนย้ายมาใช้กันแล้วนะครับ

เบราว์เซอร์จะเปลี่ยนสไตล์เริ่มต้นของ <h1>

เบราว์เซอร์จะเปลี่ยนสไตล์เริ่มต้นของ <h1> โดยจะไม่ลดขนาดตัวอักษรอัตโนมัติแล้ว และอาจถูก Lighthouse เตือนเรื่อง Best Practices

1. อย่าพึ่งพาสไตล์เริ่มต้นของเบราว์เซอร์ในการจัดลำดับหัวข้อ

เนื่องจากเบราว์เซอร์กำลังยกเลิกการปรับขนาดอัตโนมัติของ <h1> ตามระดับการซ้อนของ sectioning elements เช่น <section>, <article>, <nav>, และ <aside> ควรกำหนดลำดับหัวข้ออย่างชัดเจนโดยใช้ <h2> สำหรับหัวข้อระดับสอง, <h3> สำหรับระดับสาม เป็นต้น

.

2. กำหนด font-size และ margin สำหรับ <h1> ด้วยตนเอง

เพื่อหลีกเลี่ยงปัญหาการแสดงผลที่ไม่สอดคล้องกัน ควรกำหนดขนาดตัวอักษรและระยะห่างของ <h1> อย่างชัดเจน เช่น:

h1 {

font-size: 2em;

margin-block: 0.67em;

}

.

3. พิจารณาอัปเดต CSS reset

หากใช้ CSS reset หรือ normalize.css ควรตรวจสอบและอัปเดตให้รองรับการเปลี่ยนแปลงนี้ เพื่อให้แน่ใจว่าสไตล์พื้นฐานของคุณสอดคล้องกับพฤติกรรมใหม่ของเบราว์เซอร์

.

4. ตรวจสอบเว็บไซต์ด้วย Lighthouse และ DevTools

ใช้เครื่องมือเช่น Lighthouse และ DevTools ของเบราว์เซอร์เพื่อตรวจสอบว่าไม่มีการใช้งาน <h1> ที่ไม่มีการกำหนด font-size ซึ่งอาจถูกเตือนว่าเป็นการใช้งานที่ล้าสมัย

สรุป 5 ขั้นตอน Best Practices ช่วยป้องกัน app lag ใน React Native และ Expo

สรุป 5 ขั้นตอน Best Practices ช่วยป้องกัน app lag ใน React Native และ Expo

.

1. ใช้ TypeScript เพื่อป้องกัน bug หลีกเลี่ยงการใช้ any ให้มากที่สุด ถ้าต้องการข้ามการตรวจ type ให้ใช้ // @ts-expect-error แทน // @ts-ignore

.

2. หลีกเลี่ยง var และใช้ const / let ให้มากที่สุด ใช้ ESM แทน CommonJS เพื่อให้ Expo CLI ทำ tree-shaking ได้ แต่ถ้า require ใช้กับ assets ได้ เพราะไม่จำเป็นต้องทำ tree-shake

.

3. เปิดใช้งาน ESLint plugin ของ React เสมอ ใน Expo สามารถใช้คำสั่ง npx expo lint เพื่อเปิดใช้งาน และ config ESlint ให้อัตโนมัติ

.

4. ใช้ React Compiler มันจะวิเคราะห์ component แล้ว memoize ให้อัตโนมัติ สำหรับ expo ยังอยู่ในเวอร์ชัน beta แต่เปิดใช้ได้

.

5. ใช้ React 19 (Expo 53) เพื่อใช้ประโยชน์จากฟีเจอร์ใหม่ เช่น API use() ใช้แทน useContext() ได้ และสามารถเขียนแบบเงื่อนไข (conditional) ช่วยลดการใช้ hooks ทำให้ยืดหยุ่นมากขึ้น

อ่านเพิ่มเติมได้ที่นี่
https://expo.dev/blog/best-practices-for-reducing-lag-in-expo-apps