blog.dopana

Back

Tốc độ website ảnh hưởng trực tiếp đến user experience và SEO. 53% user rời trang nếu load lâu hơn 3 giây.

Core Web Vitals — Google Nói Gì?#

MetricTốtCần cải thiệnKém
LCP (Largest Contentful Paint)≤ 2.5s≤ 4s> 4s
INP (Interaction to Next Paint)≤ 200ms≤ 500ms> 500ms
CLS (Cumulative Layout Shift)≤ 0.1≤ 0.25> 0.25

1. Images — Nặng Nhất Trang#

Lazy Loading#

<img src="image.jpg" loading="lazy" alt="..." />
html

Chỉ tải ảnh khi user chuẩn bị scroll đến — tiết kiệm bandwidth, giảm initial load time.

WebP / AVIF#

<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="...">
</picture>
html

WebP nhỏ hơn JPEG 25-35%, AVIF nhỏ hơn 50%.

Responsive Images#

<img
  src="image-800.jpg"
  srcset="image-400.jpg 400w, image-800.jpg 800w, image-1200.jpg 1200w"
  sizes="(max-width: 600px) 400px, 800px"
  alt="..."
/>
html

Trình duyệt tự chọn ảnh phù hợp với viewport.

2. JavaScript — Kẻ Thù Của Performance#

Code Splitting#

// ❌ Tệ — import tất cả
import { Chart } from 'chart.js';

// ✅ Tốt — dynamic import
const Chart = await import('chart.js');

// React.lazy
const Dashboard = lazy(() => import('./Dashboard'));
typescript

Tree Shaking#

// ❌ Import cả thư viện
import { debounce } from 'lodash';

// ✅ Import đúng hàm
import debounce from 'lodash/debounce';
typescript

Async / Defer#

<!-- ❌ Block rendering -->
<script src="app.js"></script>

<!-- ✅ Tải song song, chạy sau khi parse HTML -->
<script defer src="app.js"></script>

<!-- ✅ Tải song song, chạy ngay khi tải xong -->
<script async src="analytics.js"></script>
html

3. CSS — Tối Ưu Render#

Critical CSS#

Inline CSS cần thiết cho above-the-fold, defer phần còn lại:

<head>
  <style>
    /* Critical CSS — inline trực tiếp */
    header { ... }
    .hero { ... }
  </style>
  <link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
</head>
html

Loại Bỏ CSS Không Dùng#

npx purgecss --css styles.css --content "src/**/*.html" --output dist/
bash

4. Font — Tránh FOIT (Flash of Invisible Text)#

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

<!-- font-display: swap — hiển thị text ngay với fallback font -->
<style>
  @font-face {
    font-family: 'Inter';
    src: url('/fonts/inter.woff2') format('woff2');
    font-display: swap;
  }
</style>
html

Không dùng quá 2 font families và subset font để giảm kích thước:

# glyphhanger — subset font
glyphhanger https://example.com --subset=*.ttf --formats=woff2
bash

5. Caching — Đừng Để Browser Phải Tải Lại#

HTTP Cache Headers#

// Static assets — cache lâu
app.use('/assets', express.static('dist', {
  maxAge: '1y',
  immutable: true,
}));

// HTML — không cache hoặc cache ngắn
app.get('/', (req, res) => {
  res.set('Cache-Control', 'no-cache');
  res.sendFile('index.html');
});
typescript

Service Worker#

6. Network — Giảm Số Request#

HTTP/2 Multiplexing#

HTTP/2 cho phép gửi nhiều file song song qua một connection. Không cần concatenate JS/CSS thành một file như thời HTTP/1.1.

Preload / Prefetch / Preconnect#

<!-- Preload — tải sớm resource quan trọng -->
<link rel="preload" href="/fonts/inter.woff2" as="font" crossorigin>

<!-- Prefetch — tải trước trang user có thể visit -->
<link rel="prefetch" href="/blog/microservices">

<!-- Preconnect — kết nối trước đến origin -->
<link rel="preconnect" href="https://api.example.com">
html

7. Bundle Size — Theo Dõi#

# Phân tích bundle
npx vite-bundle-visualizer
# hoặc
npx source-map-explorer dist/assets/*.js
bash

Đặt threshold trong CI:

{
  "scripts": {
    "size": "bundlesize",
    "bundlesize": [
      { "path": "dist/assets/*.js", "maxSize": "100 kB" }
    ]
  }
}
json

8. Lighthouse Score — Tự Động Kiểm Tra#

# Lighthouse CI
npx lhci autorun

# Hoặc web vitals trong code
import { onLCP, onINP, onCLS } from 'web-vitals';

onLCP(console.log);
onINP(console.log);
onCLS(console.log);
bash

Checklist Tối Ưu#

  • Images: WebP/AVIF, lazy loading, responsive
  • JS: code splitting, tree shaking, defer
  • CSS: critical CSS inline, purge unused
  • Font: display swap, subset, preconnect
  • Caching: Cache-Control, service worker
  • Preload critical resources
  • HTTP/2 enabled
  • Lighthouse score > 90
  • Core Web Vitals all “Good”

Kết Luận#

Performance là tính năng. Không phải thứ “làm sau” — nó ảnh hưởng đến revenue, user retention, SEO. Bắt đầu từ images (thường là thủ phạm nặng nhất), sau đó đến JS và font. Đo lường trước và sau để thấy sự khác biệt.

Tài liệu tham khảo#