Tối ưu tốc độ website 2026: Core Web Vitals và Server-Side Rendering

7 tháng trước · 15 phút đọc
Core Web Vitals 2026: Tại sao Google lại quan tâm đến tốc độ của bạn?
Ribbit 🐸 - Mình vừa optimize lại trang blog này, điểm Lighthouse nhảy từ 67 lên 98 chỉ sau một buổi chiều. Ranking Google tăng vọt, tỷ lệ thoát giảm 35%. Không phải phép màu - đây là kết quả của việc hiểu đúng Core Web Vitals.
Google đã update thuật toán Page Experience từ 2021, nhưng 2026 là năm họ siết chặt hơn bao giờ hết. Core Web Vitals không chỉ là "nice to have" - nó quyết định ranking của bạn. Ba chỉ số mấu chốt: LCP (Largest Contentful Paint), FID/INP (First Input Delay/Interaction to Next Paint), và CLS (Cumulative Layout Shift).
LCP đo tốc độ hiển thị nội dung chính, chuẩn Google là dưới 2.5 giây. FID/INP đo độ phản hồi khi người dùng tương tác, cần dưới 200ms. CLS đo độ ổn định layout, dưới 0.1 là tốt. Vượt ngưỡng này, trang web của bạn sẽ bị đánh giá "cần cải thiện" hoặc tệ hơn - "kém".
Ba chỉ số Core Web Vitals quyết định trải nghiệm người dùng và ranking Google
Nhưng đây không chỉ là chuyện SEO. Mình đã test A/B trên một trang landing page: phiên bản tải nhanh hơn 1.2 giây có tỷ lệ chuyển đổi cao hơn 28%. Người dùng không kiên nhẫn - họ rời đi nếu trang của bạn không load trong 3 giây.
Google Search Console giờ đã tích hợp báo cáo Core Web Vitals dựa trên dữ liệu thực tế từ Chrome UX Report. Bạn thấy trang nào "cần cải thiện" là phải vào fix ngay, không để sau.
Lighthouse Audit: Công cụ đo lường không thể thiếu
Lighthouse là công cụ mã nguồn mở của Google, tích hợp sẵn trong Chrome DevTools. Mở DevTools (F12), chọn tab Lighthouse, chạy audit cho cả Desktop và Mobile - bạn sẽ có báo cáo chi tiết về Performance, Accessibility, Best Practices, SEO.
Điểm Performance là tổng hợp từ 6 metrics: FCP (First Contentful Paint), LCP, TBT (Total Blocking Time), CLS, Speed Index, và TTI (Time to Interactive). Mỗi metrics có trọng số khác nhau - LCP chiếm 25%, TBT chiếm 30%. Hiểu trọng số này giúp bạn ưu tiên optimize đúng chỗ.
Mình thường chạy Lighthouse ở chế độ throttling "Slow 4G" để mô phỏng điều kiện mạng thật. Nhiều dev chỉ test trên WiFi nhanh, rồi sốc khi thấy trang web load chậm như rùa trên 4G. PageSpeed Insights (web version của Lighthouse) còn cho bạn thấy dữ liệu thực từ người dùng thật (Field Data) bên cạnh dữ liệu lab (Lab Data).
Lighthouse audit trên Chrome DevTools với các metrics chi tiết và gợi ý tối ưu
Một trick hay: dùng Lighthouse CI để tự động chạy audit mỗi lần push code. Mình setup Lighthouse CI trên GitHub Actions, mỗi pull request đều có báo cáo Performance - không ai merge được code làm chậm trang web.
Lưu ý: điểm Lighthouse chỉ là chỉ số tham khảo, không phải mục tiêu tuyệt đối. Có những trang web 85 điểm nhưng trải nghiệm thực tế vẫn tốt hơn trang 95 điểm. Tập trung vào metrics thực tế từ người dùng thật thông qua Real User Monitoring (RUM).
Server-Side Rendering với Next.js 15: Tăng tốc từ gốc
Xong phần đo lường rồi, giờ sang cách làm trang web nhanh từ kiến trúc. SSR (Server-Side Rendering) render HTML trên server trước khi gửi về browser - khác với CSR (Client-Side Rendering) phải chờ JavaScript load xong mới render.
Next.js 15 mang đến App Router với React Server Components (RSC) - components chạy hoàn toàn trên server, không gửi JS về client. Mình đã migrate một dự án từ Create React App sang Next.js 15, FCP giảm từ 3.2s xuống 0.8s, LCP từ 4.5s xuống 1.6s.
Điểm mạnh của SSR: HTML đầy đủ được gửi ngay từ request đầu tiên, search engine bot thấy nội dung liền. Điểm yếu: server phải xử lý nhiều hơn, tốn tài nguyên. Giải pháp: kết hợp SSG (Static Site Generation) cho nội dung ít thay đổi, SSR cho nội dung động.
So sánh Client-Side Rendering và Server-Side Rendering về timeline tải trang
Next.js 15 có thêm Partial Prerendering (PPR) - tính năng kết hợp static và dynamic content trong cùng một trang. Phần tĩnh (header, footer) được cache, phần động (user data) được render real-time. Kết quả: tốc độ tải nhanh như static site nhưng vẫn cá nhân hóa được.
Bạn cũng nên dùng streaming SSR - gửi HTML về từng phần thay vì đợi toàn bộ trang render xong. React Suspense hỗ trợ điều này cực tốt:
Cách này giúp FCP cực nhanh vì browser render được layout ngay, dữ liệu stream về dần không block rendering.
Optimize images: Từ 5MB xuống 50KB không mất chất lượng
Hình ảnh thường chiếm 50-70% tổng dung lượng trang web. Optimize ảnh đúng cách có thể giảm thời gian tải xuống một nửa mà người dùng không nhận ra khác biệt.
Next.js 15 có component <Image> tự động optimize: resize theo kích thước hiển thị, convert sang WebP/AVIF, lazy load mặc định, placeholder blur. Bạn chỉ cần dùng thay thẻ <img> thông thường:
Các kỹ thuật optimize ảnh mình đang dùng:
Chọn format đúng
- AVIF: nén tốt nhất, nhưng chưa được hỗ trợ rộng rãi. Dùng cho ảnh có nhiều chi tiết.
- WebP: nén tốt, hỗ trợ rộng. Ưu tiên dùng cho web.
- JPEG: fallback cho browser cũ, chất lượng 80-85% là đủ.
- PNG: chỉ dùng cho ảnh cần nền trong suốt, logo.
So sánh dung lượng file giữa các format ảnh với cùng chất lượng hiển thị
Resize đúng kích thước
Đừng dùng ảnh 3000x2000px rồi CSS scale xuống 300x200px. Tạo nhiều phiên bản ảnh (srcset) cho từng breakpoint:
Lazy loading thông minh
Chỉ lazy load ảnh dưới fold (người dùng phải scroll mới thấy). Ảnh above fold cần loading="eager" hoặc priority={true} để tránh làm chậm LCP:
Mình dùng sharp library để tự động generate nhiều kích thước ảnh khi build:
Kết quả: ảnh hero của mình giảm từ 2.8MB (PNG gốc) xuống 145KB (WebP optimized), LCP từ 5.2s xuống 1.4s.
Lazy loading và code splitting: Chỉ tải những gì cần thiết
Phần này hơi sâu, bám chặt lá sen nhé. Lazy loading không chỉ áp dụng cho ảnh - JavaScript, CSS, thậm chí cả components cũng nên lazy load để giảm bundle size ban đầu.
Code splitting tự động với Next.js
Next.js tự động tách code theo route - mỗi trang là một bundle riêng. Nhưng bạn cũng nên tách thủ công các component nặng:
Route-based code splitting
Đối với ứng dụng lớn, mỗi route nên có bundle riêng dưới 200KB. Dùng webpack-bundle-analyzer để kiểm tra:
Chạy ANALYZE=true npm run build để xem treemap các bundle. Mình phát hiện ra lodash chiếm tới 70KB vì import cả library - fix bằng cách chỉ import function cần dùng:
Webpack Bundle Analyzer hiển thị treemap các module chiếm dung lượng
Lazy load third-party scripts
Google Analytics, Facebook Pixel, chat widget... đừng load ngay lúc trang mới mở. Dùng next/script với strategy phù hợp:
Strategy options:
beforeInteractive: Load trước khi trang interactive (cẩn thận với TBT)afterInteractive: Load sau khi trang interactive (mặc định)lazyOnload: Load khi browser idle
Intersection Observer cho lazy load thủ công
Nếu bạn cần lazy load element tùy chỉnh:
Kết quả sau khi áp dụng code splitting + lazy load: bundle size giảm từ 450KB xuống 120KB (initial load), TBT từ 890ms xuống 180ms.
Font loading và CSS optimization: Những chi tiết tạo nên sự khác biệt
Font chữ tùy chỉnh làm trang web đẹp hơn nhưng cũng là thủ phạm gây chậm. FOUT (Flash of Unstyled Text) và FOIT (Flash of Invisible Text) làm CLS tăng vọt.
Next.js 15 tích hợp next/font tự động optimize Google Fonts:
Next.js sẽ:
- Download font khi build, host trên domain của bạn (tránh CORS, tránh DNS lookup)
- Tự động thêm
font-display: swap - Preload font chính để giảm FOUT
So sánh font-display strategies: block, swap, fallback, optional
Preload critical resources
Font, CSS, ảnh above-the-fold cần được preload:
Lưu ý: chỉ preload tài nguyên thật sự critical (tối đa 2-3 items). Preload quá nhiều phản tác dụng, làm chậm các tài nguyên khác.
CSS optimization
- Critical CSS: Inline CSS cần thiết cho above-the-fold, defer phần còn lại
- Remove unused CSS: Dùng PurgeCSS/Tailwind CSS để loại bỏ CSS không dùng
- Minify: Next.js tự động minify khi build production
Mình chuyển từ Bootstrap sang Tailwind CSS, CSS bundle giảm từ 180KB xuống 12KB. Tailwind chỉ generate CSS cho class thực sự sử dụng trong code.
Avoid layout shift với aspect-ratio
Đặt kích thước cụ thể cho mọi element để browser tính toán layout ngay từ đầu:
CLS của mình giảm từ 0.18 xuống 0.02 chỉ nhờ thêm aspect-ratio cho ảnh và set min-height cho dynamic content.
Caching strategies và CDN: Tận dụng sức mạnh edge network
Cache đúng cách giúp người dùng quay lại không phải tải lại tài nguyên. Browser cache, CDN cache, server cache - ba lớp cache này kết hợp mang lại hiệu quả tối đa.
Browser cache với Cache-Control headers
Quy tắc: static assets (CSS, JS, images) có hash trong tên file -> cache lâu dài. HTML -> cache ngắn hoặc revalidate mỗi lần.
Quy trình cache từ browser đến CDN edge đến origin server
CDN và edge caching
Vercel (nền tảng deploy Next.js) tự động cache static assets trên CDN toàn cầu. Nhưng bạn cũng có thể dùng Cloudflare, AWS CloudFront cho hosting khác.
Mình deploy trang blog lên Vercel, tốc độ truy cập từ Việt Nam:
- Lần đầu (cache miss): 1.2s
- Lần sau (cache hit): 0.3s
CDN serve từ edge server gần người dùng nhất, giảm latency đáng kể.
ISR (Incremental Static Regeneration) cho nội dung động
Bạn muốn trang tĩnh (nhanh) nhưng nội dung cập nhật thường xuyên? ISR là giải pháp:
Trang được generate static khi build, sau đó tự động revalidate theo interval. Người dùng luôn thấy trang nhanh (static), nội dung cập nhật định kỳ.
Service Workers cho offline experience
Trang web vẫn hoạt động khi mất mạng - Progressive Web App (PWA):
Dùng Workbox (library từ Google) để quản lý Service Worker dễ hơn. Next.js có plugin next-pwa tích hợp sẵn.
Monitoring và continuous optimization: Đo lường để cải thiện
Trang web nhanh hôm nay không đảm bảo nhanh mãi. Bạn cần monitor liên tục để phát hiện regression sớm.
Real User Monitoring (RUM)
Google Analytics 4 + Web Vitals library:
Data thật từ người dùng thật quan trọng hơn lab data. Một số người dùng có mạng chậm, device yếu - bạn cần biết trải nghiệm của họ.
Dashboard Google Analytics hiển thị Core Web Vitals từ người dùng thật
Performance budgets
Đặt ngưỡng cho từng metrics, fail build nếu vượt quá:
Mỗi lần push code, CI chạy Lighthouse audit, fail nếu không đạt budget. Ngăn chặn performance regression từ đầu.
Synthetic monitoring với Checkly
Checkly chạy Lighthouse audit định kỳ từ nhiều địa điểm, cảnh báo khi có vấn đề:
Nhận email/Slack alert ngay khi metrics xấu đi - fix trước khi người dùng phàn nàn.
A/B testing performance changes
Trước khi deploy optimization lớn, test A/B để chắc chắn không làm hỏng gì:
So sánh metrics giữa 2 nhóm sau 1 tuần, quyết định có deploy toàn bộ hay không.
