ถ้าคุณเป็นเจ้าของเว็บไซต์ นักพัฒนา หรือทำงานด้าน SEO มาก่อน คุณคงคุ้นเคยกับคำว่า Core Web Vitals เป็นอย่างดี แต่คุณรู้หรือไม่ว่า ตั้งแต่เดือนมีนาคม 2024 Google ได้ทำการเปลี่ยนแปลงครั้งใหญ่ โดยปลดเมตริก FID (First Input Delay) ออกจากการเป็น Core Web Vitals และนำเอาเมตริกใหม่ที่ชื่อว่า INP (Interaction to Next Paint) เข้ามาแทนที่อย่างเป็นทางการ
การเปลี่ยนแปลงครั้งนี้ไม่ใช่แค่เรื่องเล็ก ๆ แต่เป็นการเปลี่ยนวิธีคิดเรื่องประสบการณ์ผู้ใช้ (UX) ในระดับโครงสร้าง เพราะ INP วัดความเร็วการตอบสนองของทุก Interaction ที่ผู้ใช้ทำกับเว็บไซต์ของคุณ ไม่ใช่แค่ครั้งแรกเหมือน FID อีกต่อไป ซึ่งหมายความว่า ถ้าเว็บไซต์ของคุณมีปัญหาเรื่อง JavaScript ที่หนัก โค้ดที่ block main thread หรือ third-party script ที่ไม่จำเป็น คุณจะเห็นผลกระทบต่ออันดับ SEO และ Conversion Rate อย่างชัดเจน
ในบทความนี้ ทีม Southern Whale จะพาคุณเจาะลึกทุกแง่มุมของ INP ตั้งแต่นิยาม การวัดผล สาเหตุ 10 ข้อที่ทำให้ INP สูง วิธีแก้ 10 ข้อพร้อม code snippet ตัวอย่างจริงของเว็บ WordPress ที่เราปรับปรุงจาก INP 600ms ลงมาที่ 180ms รวมถึงเครื่องมือ คำถามที่พบบ่อย และข้อผิดพลาดที่คนมักพลาด
INP คืออะไร? วัดอะไรบ้าง
INP ย่อมาจาก Interaction to Next Paint ซึ่งเป็นเมตริกที่วัดความหน่วง (latency) ระหว่างเวลาที่ผู้ใช้เริ่ม interaction กับเว็บไซต์ (เช่น คลิก แตะ หรือกดปุ่มคีย์บอร์ด) จนถึงเวลาที่เบราว์เซอร์สามารถวาด (paint) เฟรมถัดไปบนหน้าจอเพื่อแสดงผลการตอบสนองให้ผู้ใช้เห็น
พูดง่าย ๆ คือ INP วัดว่า “ผู้ใช้รู้สึกว่าเว็บของคุณตอบสนองเร็วแค่ไหน” หลังจากที่เขาทำอะไรลงไป ไม่ว่าจะคลิกปุ่ม submit ฟอร์ม คลิกเปิดเมนู หรือเลื่อนเลือกตัวเลือก dropdown
INP ประกอบด้วย 3 ส่วนย่อยที่รวมกันเป็นเวลาทั้งหมด:
INP = Input Delay + Processing Time + Presentation Delay
1. Input Delay (ความหน่วงรับสัญญาณ) คือเวลาตั้งแต่ผู้ใช้ทำ interaction จนถึงเวลาที่ event handler เริ่มทำงาน ความหน่วงนี้มักเกิดจาก main thread ถูก block ด้วย task อื่นที่กำลังทำงานอยู่ เช่น JavaScript ที่ parsing, render บล็อก หรือ task ค้างคิวอยู่ใน event loop
2. Processing Time (เวลาประมวลผล) คือเวลาที่ event handler ทำงานทั้งหมด ตั้งแต่เริ่มจนจบ รวมถึงการเรียก function ต่าง ๆ การ update state การ fetch API การคำนวณ และการเปลี่ยนแปลง DOM ส่วนนี้มักเป็นตัวหลักที่ทำให้ INP สูง โดยเฉพาะเว็บที่ใช้ React, Vue, Angular และมี state management ที่ซับซ้อน
3. Presentation Delay (ความหน่วงแสดงผล) คือเวลาที่เบราว์เซอร์ใช้ในการ recalculate style, layout, paint และ composite ก่อนที่จะแสดงเฟรมถัดไปบนหน้าจอ ความหน่วงนี้มักเกิดจาก layout thrashing, forced reflow, heavy CSS animation หรือ DOM ที่ใหญ่เกินไป
ที่สำคัญคือ INP ไม่ได้วัดแค่ interaction เดียว แต่จะเก็บข้อมูลทุก interaction ในระหว่างที่ผู้ใช้อยู่บนหน้านั้น แล้วเลือก interaction ที่หน่วงที่สุด (worst case) มาเป็นค่า INP ของหน้าเว็บนั้น ๆ ดังนั้นแม้ว่าหน้าจะ snappy 99% ของเวลา แต่ถ้ามี interaction หนึ่งที่หน่วงมาก ๆ ก็จะทำให้ INP คะแนนแย่ทันที
เกณฑ์ Good / Needs Improvement / Poor ของ INP
Google กำหนดเกณฑ์การประเมิน INP ออกเป็น 3 ระดับ โดยอิงจากข้อมูลการใช้งานจริงของผู้ใช้ (Real User Monitoring) ในระดับ 75th percentile ซึ่งหมายความว่า คุณต้องทำให้ 75% ของ interaction ทั้งหมดมีค่าอยู่ในเกณฑ์ที่กำหนด ตารางด้านล่างนี้แสดงเกณฑ์อย่างชัดเจน
| ระดับ | ค่า INP | สีในรายงาน | ความหมาย |
|---|---|---|---|
| Good (ดี) | ≤ 200ms | สีเขียว | ผู้ใช้รู้สึกว่าเว็บไซต์ตอบสนองเร็วมาก เกือบจะ instant |
| Needs Improvement (ต้องปรับปรุง) | 200ms - 500ms | สีส้ม | ผู้ใช้เริ่มรู้สึกว่ามีความหน่วงเล็กน้อย ควรปรับปรุง |
| Poor (แย่) | > 500ms | สีแดง | ผู้ใช้รู้สึกว่าเว็บไซต์ช้า กระตุก ไม่ตอบสนอง ทำให้ frustration สูง |
ทำไม Google ถึงเลือกเกณฑ์ 200ms ในการเป็น “Good”? เพราะจากงานวิจัยทาง UX และ Human-Computer Interaction พบว่า สมองมนุษย์รับรู้ว่า “เกือบจะ instant” ที่ระยะเวลาประมาณ 100ms และเริ่มรู้สึกว่า “มีความหน่วง” ที่ระยะเวลาเกิน 200-300ms ขึ้นไป Google จึงเลือก 200ms เป็นจุดที่ user experience ยังถือว่าดี โดยไม่เข้มงวดเกินไปจนเป็นไปไม่ได้ในทางปฏิบัติ
อีกประเด็นที่สำคัญคือ INP จะถูกใช้เป็นหนึ่งในสัญญาณการจัดอันดับใน Google Search ตั้งแต่ Q2 ปี 2024 เป็นต้นมา ซึ่งหมายความว่า ถ้า INP ของคุณอยู่ในระดับ Poor หรือ Needs Improvement คุณอาจสูญเสียอันดับให้กับคู่แข่งที่มี INP ในระดับ Good โดยเฉพาะในตลาดที่การแข่งขันสูง เช่น e-commerce การเงิน การท่องเที่ยว
ทำไม INP สำคัญกว่า FID
หลายคนอาจสงสัยว่า ในเมื่อ FID เป็นเมตริกที่ใช้กันมานานและเข้าใจง่าย ทำไม Google ถึงต้องเปลี่ยนมาใช้ INP ที่ดูซับซ้อนกว่า? คำตอบสั้น ๆ คือ FID วัดเฉพาะ interaction แรกเท่านั้น ซึ่งไม่สะท้อนประสบการณ์ผู้ใช้จริงตลอด session
ลองดูตารางเปรียบเทียบด้านล่างเพื่อทำความเข้าใจความแตกต่างให้ชัดเจนยิ่งขึ้น
| ประเด็น | FID (First Input Delay) | INP (Interaction to Next Paint) |
|---|---|---|
| วัด interaction | ครั้งแรกเท่านั้น | ทุกครั้งในหน้านั้น |
| วัดอะไร | Input delay เท่านั้น | Input delay + Processing + Presentation |
| ครอบคลุม | ส่วนเริ่มต้นของ session | ตลอด session ของผู้ใช้ |
| เกณฑ์ Good | < 100ms | < 200ms |
| สะท้อน UX จริง | บางส่วน | ครบถ้วน |
| ตรวจจับ JS หนัก | จับได้ส่วนน้อย | จับได้เต็มที่ |
| สถานะ | เลิกใช้ มี.ค. 2024 | Core Web Vitals ทางการ |
ปัญหาหลักของ FID คือมันวัดเฉพาะ “input delay” ของ interaction แรกเท่านั้น ซึ่งในความเป็นจริง interaction แรกมักจะเป็นการคลิกปุ่มเมนู เปิดหน้า login หรือคลิกลิงก์ทั่วไปที่ event handler ไม่ซับซ้อน ทำให้ FID มักได้คะแนนดี แต่หลังจากที่ผู้ใช้เริ่มใช้งานจริง เช่น submit ฟอร์ม คลิกปุ่ม “add to cart” หรือใช้ search filter ที่ trigger heavy JS เว็บจะเริ่มหน่วง ทำให้ผู้ใช้รู้สึกแย่ แต่ FID ไม่จับเหตุการณ์เหล่านี้ได้
INP แก้ปัญหานี้โดยการวัด interaction ทุกครั้ง และเลือก worst-case มาเป็นตัวแทน นอกจากนี้ INP ยังวัดทั้ง processing time และ presentation delay ด้วย ซึ่งสะท้อนว่าผู้ใช้รอเห็นการเปลี่ยนแปลงบนหน้าจอนานแค่ไหน ไม่ใช่แค่รอ JS เริ่มทำงาน
ในทาง SEO การที่ INP เป็นเมตริกที่เข้มงวดกว่าและครอบคลุมกว่า ส่งผลให้เว็บไซต์ที่เคยผ่าน FID อย่างสบาย ๆ อาจไม่ผ่าน INP จากสถิติของ HTTP Archive ในปี 2024 พบว่ามีเว็บไซต์ประมาณ 36% ที่อยู่ในระดับ Needs Improvement หรือ Poor ของ INP เทียบกับเพียง 10% ของ FID ซึ่งเป็นช่องว่างที่ใหญ่มาก
วิธีวัด INP: PageSpeed Insights, CrUX Dashboard, web-vitals.js
การวัด INP สามารถทำได้หลายวิธี ขึ้นอยู่กับวัตถุประสงค์และระดับความละเอียดที่คุณต้องการ ทีม Southern Whale แนะนำให้ใช้หลายวิธีร่วมกันเพื่อให้ได้ภาพรวมที่สมบูรณ์
1. PageSpeed Insights
วิธีที่ง่ายที่สุดคือเข้าไปที่ pagespeed.web.dev แล้วใส่ URL ของหน้าเว็บที่คุณต้องการวัด PageSpeed Insights จะแสดงทั้ง Lab data (จาก Lighthouse simulation) และ Field data (จาก Chrome User Experience Report หรือ CrUX) ของ INP ในส่วน Core Web Vitals พร้อมเกณฑ์การประเมิน
ข้อดีคือใช้งานง่าย ไม่ต้องติดตั้งอะไร และให้ insight เบื้องต้นรวมถึงข้อเสนอแนะในการปรับปรุง ข้อจำกัดคือ Field data จะแสดงเฉพาะหน้าที่มี traffic เพียงพอเท่านั้น และข้อมูลเป็นค่าเฉลี่ย 28 วันย้อนหลัง ไม่ใช่แบบ real-time
2. CrUX Dashboard บน Looker Studio
ถ้าคุณต้องการดูข้อมูลย้อนหลังในรูปกราฟ แนวโน้ม และเปรียบเทียบ device ต่าง ๆ ให้ใช้ CrUX Dashboard ที่สร้างบน Looker Studio (เดิมคือ Data Studio) เพียงคุณกรอก URL ของเว็บไซต์ระบบจะดึงข้อมูล CrUX มาแสดงเป็นกราฟอย่างสวยงาม
CrUX Dashboard เหมาะมากสำหรับการทำ report ให้ client หรือ stakeholder เพราะสามารถ visualize การเปลี่ยนแปลงของ INP ตลอด 12 เดือนได้
3. web-vitals.js — วัด INP บนเว็บของคุณเอง
ถ้าคุณต้องการวัด INP แบบ real-time บนเว็บของคุณเอง รวมถึงส่งข้อมูลไปยัง analytics เช่น Google Analytics, Cloudflare Analytics หรือ self-hosted tool ให้ใช้ library web-vitals ที่ทาง Chrome team พัฒนาขึ้นมา
ติดตั้งด้วย npm:
npm install web-vitals
แล้วใช้งานในโค้ดของคุณ:
import { onINP } from 'web-vitals';
onINP((metric) => {
console.log('INP:', metric.value, 'ms');
console.log('Rating:', metric.rating); // 'good', 'needs-improvement', 'poor'
console.log('Interaction target:', metric.entries[0]?.target);
// ส่งข้อมูลไปยัง analytics
gtag('event', 'web_vitals', {
metric_name: 'INP',
metric_value: Math.round(metric.value),
metric_rating: metric.rating,
metric_target: metric.entries[0]?.target?.tagName,
});
});
ข้อดีของวิธีนี้คือคุณจะได้ข้อมูลแบบ real-time จากผู้ใช้ทุกคน รวมถึงรายละเอียดว่า element ไหนที่เป็นต้นเหตุของ INP สูง ทำให้คุณสามารถระบุปัญหาและแก้ไขได้ตรงจุด
4. Chrome DevTools Performance Panel
สำหรับการ debug เชิงลึก เปิด Chrome DevTools ไปที่ Performance tab แล้วเริ่ม recording จากนั้นทำ interaction ที่ต้องการทดสอบ เมื่อหยุด recording จะเห็น timeline ของ task ทั้งหมด รวมถึง long task ที่ block main thread ซึ่งเป็นต้นเหตุของ INP สูง
10 สาเหตุที่ INP สูง
เพื่อให้คุณสามารถวินิจฉัยปัญหา INP ในเว็บของคุณได้ ทีม Southern Whale ได้รวบรวม 10 สาเหตุที่พบบ่อยที่สุด พร้อมคำอธิบายว่าแต่ละสาเหตุส่งผลต่อ INP อย่างไร
1. Long Task (งานยาวเกิน 50ms)
Long Task คือ JavaScript task ใด ๆ ก็ตามที่ใช้เวลาประมวลผลเกิน 50ms ซึ่งจะ block main thread และทำให้ event handler ของ interaction รออยู่ในคิว ส่งผลโดยตรงต่อ Input Delay ของ INP
2. Render Blocking Resources
CSS และ JavaScript ที่ block การ render ของหน้าเว็บ ทำให้เบราว์เซอร์ต้องรอ download และ parse ไฟล์เหล่านี้ก่อนที่จะแสดงผล หากผู้ใช้ทำ interaction ในช่วงนี้ INP จะสูงมาก
3. JS Bundle ที่ใหญ่เกินไป
เว็บไซต์สมัยใหม่ที่ใช้ React, Vue, Angular มักมี bundle size หลาย MB เมื่อ parse และ execute จะใช้เวลานาน โดยเฉพาะบนอุปกรณ์ low-end เช่น Android ระดับล่าง ทำให้ INP สูงต่อเนื่อง
4. Layout Thrashing
เกิดจากการที่ JavaScript อ่านและเขียนค่า layout-related property (เช่น offsetWidth, offsetHeight, scrollTop) สลับกันหลายครั้งใน loop เดียว ทำให้เบราว์เซอร์ต้อง recalculate layout ซ้ำ ๆ ส่งผลให้ Presentation Delay สูงขึ้น
5. Forced Reflow
คล้ายกับ Layout Thrashing แต่เกิดจากการที่โค้ดอ่านค่า geometry ของ element ทันทีหลังจากเปลี่ยน DOM ทำให้เบราว์เซอร์ต้องคำนวณ layout ใหม่ทันที (synchronous reflow) แทนที่จะรอ batch ในเฟรมถัดไป
6. Heavy CSS (Complex Selectors, Many Rules)
CSS ที่มี selector ซับซ้อน เช่น descendant selector ที่ยาว, universal selector หรือมี rule จำนวนมาก ทำให้ style recalculation ช้า เมื่อ DOM เปลี่ยนแปลง เวลาที่ใช้คำนวณ style จะเพิ่มขึ้นแบบ exponential
7. Third-Party Script ที่หนัก
Script จาก analytics, ad network, chat widget, social embed มักมีขนาดใหญ่และทำงานบน main thread เดียวกัน ทำให้ INP สูงโดยที่คุณควบคุมได้ยาก
8. Slow API Call ใน Event Handler
ถ้า event handler ของคุณเรียก API แบบ synchronous หรือมีการประมวลผลข้อมูลที่ได้ก่อนตอบสนอง ผู้ใช้จะต้องรอนานก่อนเห็นการเปลี่ยนแปลง ทำให้ Processing Time ของ INP สูง
9. Big DOM (มากกว่า 1500 elements)
DOM ที่มีจำนวน element มาก (มากกว่า 1500) ทำให้การ traverse และ update DOM ช้า โดยเฉพาะเมื่อใช้ querySelector หรือเปลี่ยนแปลงหลาย element พร้อมกัน
10. requestAnimationFrame Callback ที่หนัก
ถ้าใน rAF callback มีการคำนวณหนักหรือมีการ trigger forced reflow จะทำให้แต่ละเฟรม render ช้า ส่งผลให้ Presentation Delay สูงขึ้น โดยเฉพาะใน animation ที่ใช้ JavaScript
10 วิธีแก้ INP
หลังจากที่คุณทราบสาเหตุแล้ว มาดูวิธีแก้แต่ละข้ออย่างละเอียด พร้อม code snippet ที่คุณสามารถนำไปใช้ได้ทันที
1. Code Splitting แบ่ง Bundle ออกเป็นชิ้นเล็ก ๆ
แทนที่จะ load JavaScript ทั้งหมดในไฟล์เดียว ให้แบ่งโค้ดตาม route หรือ feature โดยใช้ dynamic import:
// แทนที่จะ import ทั้งหมดในไฟล์เดียว
// import HeavyComponent from './HeavyComponent';
// ให้ใช้ dynamic import เพื่อโหลดเฉพาะเมื่อจำเป็น
button.addEventListener('click', async () => {
const { HeavyComponent } = await import('./HeavyComponent');
HeavyComponent.render();
});
2. Defer JavaScript ที่ไม่จำเป็นใน Critical Path
ใส่ defer หรือ async attribute ให้กับ <script> ที่ไม่จำเป็นต้อง execute ทันที:
<!-- ไม่ดี: block parsing -->
<script src="analytics.js"></script>
<!-- ดี: ใช้ defer หรือ async -->
<script src="analytics.js" defer></script>
<script src="ads.js" async></script>
3. Web Worker สำหรับงานหนัก
ย้ายงานคำนวณหนัก เช่น parse JSON ขนาดใหญ่, image processing, encryption ไปทำใน Web Worker เพื่อไม่ให้ block main thread:
// main.js
const worker = new Worker('heavy-task.js');
worker.postMessage({ data: largeArray });
worker.onmessage = (e) => {
console.log('ผลลัพธ์:', e.data);
};
// heavy-task.js
self.onmessage = (e) => {
const result = processData(e.data); // งานหนัก
self.postMessage(result);
};
4. requestIdleCallback สำหรับงานที่ไม่เร่งด่วน
ใช้ requestIdleCallback เพื่อเลื่อนงานที่ไม่เร่งด่วนไปทำเมื่อ browser ว่าง:
function logAnalytics(data) {
if ('requestIdleCallback' in window) {
requestIdleCallback(() => {
sendToAnalytics(data);
}, { timeout: 2000 });
} else {
setTimeout(() => sendToAnalytics(data), 1);
}
}
5. ลดขนาด DOM
ทำ DOM ให้แบน ๆ และมีจำนวน element น้อย โดยใช้ virtual scrolling สำหรับ list ยาว ๆ และลบ element ที่ไม่จำเป็น
6. Optimize Event Listener
ใช้ event delegation แทนที่จะ attach listener ทุก element และใช้ passive: true สำหรับ scroll/touch:
// ไม่ดี: attach listener หลายอัน
document.querySelectorAll('.button').forEach(btn => {
btn.addEventListener('click', handler);
});
// ดี: event delegation
document.body.addEventListener('click', (e) => {
if (e.target.matches('.button')) {
handler(e);
}
});
// passive listener สำหรับ scroll
window.addEventListener('scroll', onScroll, { passive: true });
7. Debounce และ Throttle
ใช้ debounce สำหรับ input handler และ throttle สำหรับ scroll/resize:
function debounce(fn, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
// ใช้กับ search input
searchInput.addEventListener('input', debounce((e) => {
performSearch(e.target.value);
}, 300));
8. Hardware Acceleration ด้วย CSS
ใช้ transform และ opacity แทน top, left, width, height สำหรับ animation เพราะ properties เหล่านี้ใช้ GPU compositor ไม่ trigger layout/paint:
/* ไม่ดี: trigger layout */
.box {
left: 100px;
width: 200px;
transition: left 0.3s, width 0.3s;
}
/* ดี: ใช้ GPU */
.box {
transform: translateX(100px) scale(1.5);
transition: transform 0.3s;
will-change: transform;
}
9. Lazy Load Component และ Image
โหลด component และรูปภาพเฉพาะเมื่อ scroll ถึงตำแหน่งนั้น:
// Image lazy loading (native)
<img src="placeholder.jpg" data-src="real-image.jpg" loading="lazy" />
// Component lazy loading ด้วย Intersection Observer
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
}, { rootMargin: '50px' });
document.querySelectorAll('img[data-src]').forEach(img => {
observer.observe(img);
});
10. ลด Third-Party Script และใช้ Facade Pattern
แทนที่จะ load YouTube embed, social widget โดยตรง ให้ใช้ facade ที่แสดงรูป preview แล้วโหลด iframe จริงเมื่อคลิก:
const youtubeButton = document.querySelector('.youtube-facade');
youtubeButton.addEventListener('click', () => {
const videoId = youtubeButton.dataset.videoId;
const iframe = document.createElement('iframe');
iframe.src = `https://www.youtube.com/embed/${videoId}?autoplay=1`;
iframe.frameBorder = '0';
iframe.allow = 'autoplay; encrypted-media';
iframe.allowFullscreen = true;
youtubeButton.replaceWith(iframe);
});
ถ้าคุณใช้ WordPress การติดตั้ง plugin ที่เหมาะสม สามารถช่วยจัดการ third-party script และ defer JS ได้โดยไม่ต้องเขียนโค้ดเอง
ตัวอย่างจริง: WordPress site INP 600ms → 180ms
เพื่อให้คุณเห็นภาพชัดเจนว่าการ optimize INP สามารถส่งผลกระทบมากแค่ไหน เรามาดูเคสจริงของลูกค้า WordPress e-commerce ที่ทีม Southern Whale ได้ดูแล
เว็บไซต์นี้ขายสินค้าแฟชั่นออนไลน์ มี traffic ประมาณ 50,000 visit ต่อเดือน ก่อนการปรับปรุง INP อยู่ที่ 600ms (Poor) ทำให้ผู้ใช้บ่นว่าเว็บกระตุก โดยเฉพาะเมื่อกดปุ่ม “เพิ่มลงตะกร้า” และเมื่อใช้ filter ในหน้า category
เราทำการวิเคราะห์ด้วย Chrome DevTools และพบปัญหาหลักดังนี้:
| ปัญหา | INP ที่เกี่ยวข้อง | สาเหตุ |
|---|---|---|
| ปุ่ม Add to cart | 580ms | Heavy AJAX + DOM update ทั้งหน้า |
| Filter ในหน้า category | 720ms | Re-render product list 200 items |
| Mega menu hover | 320ms | JS animation + heavy CSS |
| Search auto-suggest | 450ms | API call ทุกการพิมพ์ ไม่มี debounce |
| Modal popup | 380ms | Load full content ทันทีเมื่อโหลดหน้า |
หลังจากระบุปัญหาได้ เราใช้กลยุทธ์การแก้ไขดังนี้:
| วิธีแก้ | เครื่องมือ/เทคนิค | ผลกระทบต่อ INP |
|---|---|---|
| ใช้ debounce กับ search | Custom JS 10 บรรทัด | -270ms |
| Replace mega menu animation ด้วย CSS only | CSS transform | -200ms |
| Code split admin/checkout bundle | Webpack splitChunks | -180ms |
| Lazy load modal content | Intersection Observer | -150ms |
| ย้าย analytics ไป Web Worker | Partytown | -120ms |
| Replace third-party chat widget | Facade + lazy load | -80ms |
ผลลัพธ์หลังจาก 3 สัปดาห์:
| Metric | ก่อนปรับปรุง | หลังปรับปรุง | เปลี่ยนแปลง |
|---|---|---|---|
| INP (p75) | 600ms | 180ms | -70% |
| LCP (p75) | 3.2s | 2.1s | -34% |
| CLS | 0.15 | 0.05 | -67% |
| Bounce Rate | 58% | 41% | -29% |
| Conversion Rate | 1.8% | 2.6% | +44% |
| อันดับ keyword หลัก | 7 | 3 | +4 |
ที่น่าสนใจคือ การปรับปรุง INP ไม่ได้ส่งผลแค่กับ Core Web Vitals เท่านั้น แต่ยังช่วยลด bounce rate และเพิ่ม conversion rate อย่างมีนัยสำคัญ เพราะผู้ใช้รู้สึกว่าเว็บเร็วและ responsive ทำให้อยู่นานขึ้นและซื้อสินค้ามากขึ้น
อ่านเพิ่มเติมเกี่ยวกับการ optimize เมตริก Core Web Vitals อื่น ๆ ได้ที่บทความ LCP Optimization 2026 และ CLS Cumulative Layout Shift 2026 ของเรา
Tools สำหรับวิเคราะห์และ Debug INP
ในการทำงาน optimize INP คุณต้องมีเครื่องมือที่เหมาะสมเพื่อช่วยให้คุณระบุปัญหาและวัดผลได้อย่างแม่นยำ ด้านล่างนี้คือเครื่องมือที่ทีม Southern Whale ใช้เป็นประจำในการดูแลลูกค้า
1. Chrome DevTools Performance Panel
เครื่องมือนี้เป็นพื้นฐานที่นักพัฒนาทุกคนต้องใช้เป็น เพราะให้ข้อมูลละเอียดที่สุดเกี่ยวกับ task ที่ทำงานบน main thread ขั้นตอนการใช้งาน:
- เปิด DevTools (F12) ไปที่ Performance tab
- เปิด CPU throttling เป็น 4x slowdown และ Network เป็น Slow 4G เพื่อจำลองอุปกรณ์ low-end
- กด Record (Ctrl+E) แล้วทำ interaction ที่ต้องการวัด
- กด Stop เพื่อดู timeline
ในส่วน Interactions ที่อยู่เหนือ Main thread จะแสดง interaction พร้อม INP value และ breakdown ของแต่ละช่วง (input delay, processing, presentation) คุณสามารถคลิกที่ task เพื่อดูว่า function ไหนใช้เวลานานที่สุด
2. Lighthouse
Lighthouse รวมอยู่ใน Chrome DevTools และ PageSpeed Insights แต่ให้ค่า Lab data เป็นหลัก ไม่ใช่ Field data ดังนั้นค่า INP ใน Lighthouse จะแตกต่างจากค่า INP จริงของผู้ใช้ Lighthouse เหมาะสำหรับการ test ในระหว่าง development และ CI/CD pipeline
3. Layoutshift.com / WebPageTest
WebPageTest เป็นเครื่องมือ profile เว็บที่ทรงพลังมาก สามารถ test จากหลาย location, device และ network speed ได้ ฟีเจอร์ที่มีประโยชน์มากสำหรับ INP คือ Filmstrip View ที่แสดงภาพหน้าจอทุก 100ms ทำให้เห็นว่าหลัง interaction เว็บใช้เวลานานแค่ไหนกว่าจะแสดงผล
4. Google Search Console — Core Web Vitals Report
หลังจาก deploy การปรับปรุง อย่าลืมเข้า Google Search Console ไปที่ Core Web Vitals Report เพื่อ track ผลในระยะยาว Report นี้แสดงข้อมูลจาก CrUX โดยแบ่งเป็น URL group และระดับ Good/Needs Improvement/Poor ทำให้คุณเห็นว่าหน้าไหนต้องปรับปรุงเร่งด่วน
5. Real User Monitoring (RUM) Tools
สำหรับเว็บที่ traffic สูงและต้องการ data ละเอียด แนะนำให้ใช้ RUM tool เช่น Cloudflare Web Analytics, SpeedCurve, Akamai mPulse หรือ self-hosted ด้วย web-vitals.js + Cloudflare Workers Analytics เพื่อ track INP แบบ real-time พร้อม breakdown ตาม device, browser, country และ page
ถ้าคุณต้องการตั้งค่า RUM กับ Cloudflare อ่านวิธีการได้ที่บทความ Cloudflare Complete Guide 2026
5 ข้อผิดพลาดที่คนทำบ่อยเกี่ยวกับ INP
จากประสบการณ์ของทีม Southern Whale ในการ optimize เว็บมาแล้วหลายร้อยเว็บ เราพบว่าคนมักทำผิดพลาด 5 ข้อต่อไปนี้ ซึ่งทำให้การ optimize INP ไม่ได้ผลเท่าที่ควร
1. ใช้ Lab Data แทน Field Data เพื่อตัดสินใจ
ข้อผิดพลาดที่พบบ่อยที่สุดคือการดูคะแนน Lighthouse แล้วคิดว่าเว็บเร็วแล้ว ทั้งที่ผู้ใช้จริงเจอ INP สูงมาก เพราะ Lighthouse ใช้ simulation ที่ไม่สะท้อนสภาพการใช้งานจริง ผู้ใช้จริงใช้อุปกรณ์หลากหลาย ความเร็วเน็ตต่างกัน และทำ interaction ที่ซับซ้อนกว่าใน Lighthouse test
แก้ไข: ใช้ Field data จาก CrUX, Search Console หรือ RUM tool เป็นหลักในการตัดสินใจ Lab data ใช้สำหรับ debug เฉพาะหน้า
2. Optimize Desktop เท่านั้น แต่ลืม Mobile
ผู้ใช้ส่วนใหญ่ในไทยใช้ mobile ซึ่งมี CPU ช้ากว่า desktop หลายเท่า INP บน mobile มักสูงกว่า desktop 2-3 เท่า แต่หลายทีม optimize เฉพาะ desktop เพราะ test สะดวกกว่า
แก้ไข: ใช้ CPU throttling 4x ใน DevTools, test บน Android low-end จริง หรือ remote debug บนอุปกรณ์จริง
3. ลืม Test หลัง Deploy Plugin/Theme ใหม่
WordPress site มักติดตั้ง plugin เพิ่มเรื่อย ๆ ทำให้ INP ค่อย ๆ แย่ลงโดยไม่รู้ตัว เช่น ติดตั้ง security plugin, SEO plugin, popup plugin ฯลฯ ที่แต่ละตัวเพิ่ม JS หลายร้อย KB
แก้ไข: ตั้ง alert ใน RUM tool ให้แจ้งเตือนเมื่อ INP แย่ลง และ test INP ทุกครั้งหลัง deploy plugin หรือ theme ใหม่
4. ใช้ React/Vue SSR แต่ Hydration หนัก
หลายคนคิดว่าการใช้ SSR (Server-Side Rendering) จะช่วยให้เว็บเร็ว แต่ลืมว่า hydration เป็นกระบวนการที่กิน main thread มาก ทำให้ INP สูงในช่วงแรกของ session
แก้ไข: ใช้ partial hydration, selective hydration หรือ island architecture (เช่น Astro, Qwik) เพื่อ hydrate เฉพาะส่วนที่จำเป็น
5. Defer ทุกอย่างจน UX แย่
บางคน defer ทุก script จน element ที่ผู้ใช้ต้องการใช้ทันที (เช่น navigation, search) ไม่ทำงาน ทำให้ INP สูงเมื่อผู้ใช้พยายาม interact กับ element เหล่านั้นในช่วงแรก
แก้ไข: แยกแยะ critical interaction และ non-critical script ให้ชัดเจน Critical interaction ต้องโหลด script ทันที ส่วน non-critical สามารถ defer หรือ lazy load ได้
คำถามที่พบบ่อย
Q1: INP ต่างจาก TBT (Total Blocking Time) อย่างไร?
TBT วัดเฉพาะระหว่างการโหลดหน้าเว็บ (FCP ถึง TTI) เป็นเมตริก Lab data ที่ใช้ใน Lighthouse ส่วน INP วัด interaction ทุกครั้งตลอด session ของผู้ใช้ และเป็น Field data จากผู้ใช้จริง ทั้งสองเมตริกเสริมกัน — TBT ช่วยทำนาย INP ก่อน deploy ส่วน INP บอกประสบการณ์จริงหลัง deploy
Q2: INP สำคัญกว่า LCP หรือ CLS ไหม?
ทั้งสามเมตริก (LCP, INP, CLS) เป็น Core Web Vitals ที่มีน้ำหนักเท่ากันใน Google Ranking ถ้าหน้าใดผ่านทั้งสามเมตริกในระดับ Good จะได้ ranking signal เชิงบวก แต่ถ้าไม่ผ่านเมตริกใดเมตริกหนึ่ง อาจสูญเสียโอกาสการจัดอันดับ ดังนั้นต้อง optimize ทุกเมตริกควบคู่กัน
Q3: ทำไม INP บน mobile สูงกว่า desktop?
เพราะ mobile มี CPU และ memory จำกัดกว่า desktop หลายเท่า โดยเฉพาะ Android low-end ที่ใช้ chipset อย่าง Mediatek Helio หรือ Snapdragon 4 series การ parse JavaScript ขนาด 500KB อาจใช้เวลาบน mobile มากกว่า desktop 5-10 เท่า ดังนั้นการ optimize ต้องคำนึงถึง mobile เป็นหลัก
Q4: ใช้ Server-Side Rendering (SSR) ช่วย INP ได้ไหม?
SSR ช่วย LCP ได้ดี แต่ไม่ช่วย INP โดยตรง เพราะ INP เกิดจาก JavaScript ที่ทำงานหลังจาก hydration เสร็จแล้ว ในบาง framework เช่น Next.js การใช้ SSR แล้ว hydrate ทั้งหน้าอาจทำให้ INP แย่ลงในช่วงต้นของ session แนะนำให้ใช้ partial hydration หรือ React Server Components แทน
Q5: ใช้ Cache ช่วย INP ได้ไหม?
Cache ช่วย LCP เพราะลดเวลาโหลด HTML/CSS/JS แต่ไม่ช่วย INP โดยตรง เพราะ INP เกิดจากการ execute JS หลังจากผู้ใช้ทำ interaction ซึ่งเป็นกระบวนการที่ไม่เกี่ยวกับการโหลด อย่างไรก็ตาม ถ้าใช้ CDN ที่มี edge worker เช่น Cloudflare Workers สามารถช่วย API call ใน event handler ให้เร็วขึ้นได้
Q6: ถ้าใช้ WordPress จะ optimize INP อย่างไรให้ง่ายที่สุด?
แนะนำให้เริ่มจาก: (1) ลบ plugin ที่ไม่จำเป็น โดยเฉพาะที่ inject JS ทุกหน้า (2) ติดตั้ง caching plugin เช่น WP Rocket หรือ LiteSpeed Cache แล้วเปิด Defer JS, Delay JS (3) ใช้ Cloudflare Workers หรือ Partytown ย้าย third-party script ไป Web Worker (4) ติดตั้ง plugin SEO ที่ดีและไม่หนัก เพื่อแทน plugin ที่หนักเกินจำเป็น
Q7: INP เกิน 500ms จะเสีย SEO เลยไหม?
INP เป็นหนึ่งในสัญญาณการจัดอันดับ ไม่ใช่ตัวตัดสินเด็ดขาด แต่ถ้า INP อยู่ในระดับ Poor (>500ms) คุณจะเสียโอกาสในการได้ ranking boost จาก Google Page Experience signal และในตลาดที่แข่งขันสูง ความได้เปรียบเล็ก ๆ น้อย ๆ ก็สามารถทำให้คุณตกอันดับได้ ดังนั้นควรพยายาม optimize ให้อยู่ในระดับ Good
Q8: ใช้ React/Vue ทำให้ INP แย่กว่า Vanilla JS ใช่หรือไม่?
ไม่จำเป็น ทุก framework สามารถมี INP ดีได้ถ้า optimize ดี ๆ React 18 มี concurrent features ที่ช่วย break long task ให้สั้นลง Vue 3 มี composition API ที่ช่วย code split ได้ดี ส่วน Vanilla JS ก็มีความเสี่ยงถ้าเขียนโดยไม่คำนึงถึง main thread blocking ดังนั้นไม่ใช่เรื่องของ framework แต่เป็นเรื่องของวิธีเขียนโค้ดและสถาปัตยกรรม
สรุป
INP (Interaction to Next Paint) เป็น Core Web Vitals ใหม่ที่เข้ามาแทนที่ FID ตั้งแต่เดือนมีนาคม 2024 และกลายเป็นหนึ่งในสัญญาณการจัดอันดับที่สำคัญของ Google Search ความแตกต่างหลักจาก FID คือ INP วัด interaction ทุกครั้งตลอด session ของผู้ใช้ ไม่ใช่แค่ครั้งแรก และครอบคลุมทั้ง Input Delay, Processing Time และ Presentation Delay ทำให้สะท้อน user experience จริงได้ดีกว่ามาก
เกณฑ์ของ INP คือ Good ≤ 200ms, Needs Improvement 200-500ms และ Poor > 500ms ซึ่งวัดที่ 75th percentile ของผู้ใช้จริง สาเหตุที่ INP สูงมี 10 ข้อหลัก ตั้งแต่ Long Task, Render Blocking, JS Bundle ใหญ่, Layout Thrashing ไปจนถึง Third-Party Script ที่หนัก
วิธีแก้ที่ได้ผลดีที่สุด ได้แก่ Code Splitting, Defer JS, Web Worker, requestIdleCallback, Optimize Event Listener, Debounce, Hardware Acceleration ด้วย CSS, Lazy Load Component และการใช้ Facade Pattern แทน Third-Party Script จากตัวอย่างจริงของลูกค้า WordPress e-commerce ที่ทีม Southern Whale ดูแล สามารถลด INP จาก 600ms เหลือ 180ms ภายใน 3 สัปดาห์ ส่งผลให้ Conversion Rate เพิ่ม 44% และอันดับ keyword หลักดีขึ้น 4 อันดับ
ถ้าคุณต้องการคำปรึกษาในการ optimize INP หรือ Core Web Vitals อื่น ๆ สำหรับเว็บไซต์ของคุณ สามารถ ติดต่อทีม Southern Whale ได้ตลอด เรามีบริการ Web Development และ Performance Optimization สำหรับทุกขนาดธุรกิจ พร้อมการ implement ที่ใช้ best practice ระดับโลก