Tối ưu hóa Frontend Phần 1 - Nguyên lý cơ bản về hiệu suất
Hiệu suất là một trong những yếu tố quan trọng nhất ảnh hưởng đến trải nghiệm người dùng trên web. Bài viết này sẽ giới thiệu các nguyên lý cơ bản về hiệu suất frontend, từ các chỉ số quan trọng đến các kỹ thuật tối ưu hóa thiết yếu.
1. Hiểu về các chỉ số hiệu suất quan trọng
Để tối ưu hiệu suất một cách hiệu quả, trước tiên chúng ta cần hiểu và đo lường các chỉ số hiệu suất quan trọng.
Các chỉ số Core Web Vitals:
- Largest Contentful Paint (LCP): Đo thời gian tải và hiển thị phần tử lớn nhất trong viewport. Mục tiêu tốt là dưới 2.5 giây.
- First Input Delay (FID): Đo thời gian từ khi người dùng tương tác đầu tiên đến khi trình duyệt phản hồi. Mục tiêu tốt là dưới 100ms.
- Cumulative Layout Shift (CLS): Đo mức độ thay đổi bố cục không mong muốn. Mục tiêu tốt là dưới 0.1.
- Interaction to Next Paint (INP): Đo độ trễ tương tác, thay thế FID từ tháng 3/2024. Mục tiêu tốt là dưới 200ms.
Các chỉ số hiệu suất khác:
- Time to First Byte (TTFB): Thời gian từ khi yêu cầu đến khi nhận byte đầu tiên.
- First Contentful Paint (FCP): Thời gian hiển thị nội dung đầu tiên.
- Time to Interactive (TTI): Thời gian trang web trở nên hoàn toàn tương tác được.
- Total Blocking Time (TBT): Tổng thời gian chặn luồng chính.
// Đo lường Core Web Vitals bằng JavaScript
import {onCLS, onFID, onLCP, onINP} from 'web-vitals';
function sendToAnalytics({name, value, id}) {
const body = JSON.stringify({name, value, id});
// Sử dụng Beacon API nếu có thể
if (navigator.sendBeacon) {
navigator.sendBeacon('/analytics', body);
} else {
fetch('/analytics', {
body,
method: 'POST',
keepalive: true
});
}
}
// Đo và gửi các chỉ số
onCLS(sendToAnalytics);
onFID(sendToAnalytics);
onLCP(sendToAnalytics);
onINP(sendToAnalytics);
2. Tối ưu hóa Critical Rendering Path
Critical Rendering Path (CRP) là quá trình trình duyệt chuyển đổi HTML, CSS và JavaScript thành các pixel trên màn hình. Tối ưu hóa CRP giúp cải thiện đáng kể thời gian tải trang.
Các kỹ thuật tối ưu hóa CRP:
- Giảm thiểu kích thước tài nguyên: Nén và tối ưu HTML, CSS, JavaScript.
- Tối ưu thứ tự tải: Tải CSS trước, JavaScript sau.
- Giảm thiểu CSS chặn render: Sử dụng CSS inline cho nội dung quan trọng.
- Tải JavaScript không đồng bộ: Sử dụng thuộc tính
async
vàdefer
. - Giảm thiểu số lượng HTTP requests: Gộp các tệp, sử dụng CSS sprites.
<!-- Tối ưu thứ tự tải tài nguyên -->
<head>
<!-- CSS quan trọng inline -->
<style>
/* CSS cần thiết cho nội dung hiển thị đầu tiên */
.header, .hero { /* styles */ }
</style>
<!-- CSS không quan trọng tải không đồng bộ -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>
<!-- JavaScript không chặn render -->
<script src="critical.js" defer></script>
</head>
3. Tối ưu hóa hình ảnh và media
Hình ảnh và media thường chiếm phần lớn kích thước trang web. Tối ưu hóa chúng là cách hiệu quả để cải thiện hiệu suất tải.
Kỹ thuật tối ưu hóa hình ảnh:
- Chọn định dạng phù hợp: WebP cho hình ảnh thông thường, SVG cho đồ họa vector.
- Nén hình ảnh: Giảm kích thước file mà không làm giảm chất lượng đáng kể.
- Sử dụng hình ảnh đáp ứng: Cung cấp hình ảnh có kích thước phù hợp với thiết bị.
- Lazy loading: Chỉ tải hình ảnh khi cần thiết.
- Sử dụng CDN cho hình ảnh: Giảm độ trễ khi tải hình ảnh.
<!-- Hình ảnh đáp ứng với lazy loading -->
<img
src="small.jpg"
srcset="small.jpg 400w, medium.jpg 800w, large.jpg 1200w"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px"
loading="lazy"
alt="Mô tả hình ảnh"
/>
<!-- Sử dụng <picture> cho các định dạng khác nhau -->
<picture>
<source type="image/webp" srcset="image.webp">
<source type="image/jpeg" srcset="image.jpg">
<img src="image.jpg" alt="Mô tả hình ảnh" loading="lazy">
</picture>
4. Tối ưu hóa JavaScript
JavaScript có thể ảnh hưởng đáng kể đến hiệu suất trang web nếu không được tối ưu hóa đúng cách.
Kỹ thuật tối ưu hóa JavaScript:
- Giảm thiểu kích thước: Sử dụng minification và compression.
- Tránh chặn render: Sử dụng
async
,defer
hoặc dynamic import. - Tối ưu hóa thực thi: Tránh long tasks, sử dụng Web Workers cho tác vụ nặng.
- Tránh micro-optimizations không cần thiết: Tập trung vào các vấn đề hiệu suất lớn.
- Sử dụng memoization: Lưu trữ kết quả của các hàm tốn kém.
// Tải JavaScript động khi cần
function loadFeature() {
import('./feature.js')
.then((module) => {
module.initFeature();
})
.catch(err => {
console.error('Không thể tải tính năng:', err);
});
}
// Chỉ tải khi người dùng tương tác
document.querySelector('.feature-button').addEventListener('click', loadFeature);
// Sử dụng Web Worker cho tác vụ nặng
const worker = new Worker('heavy-computation.js');
worker.addEventListener('message', (event) => {
// Xử lý kết quả từ worker
updateUI(event.data);
});
// Gửi dữ liệu để xử lý
worker.postMessage({data: complexData});
5. Tối ưu hóa CSS
CSS không tối ưu có thể làm chậm quá trình render và tạo ra trải nghiệm người dùng kém.
Kỹ thuật tối ưu hóa CSS:
- Giảm thiểu CSS không sử dụng: Loại bỏ các quy tắc không cần thiết.
- Tối ưu hóa CSS selectors: Sử dụng selectors đơn giản và hiệu quả.
- Tránh các thuộc tính gây reflow: Ưu tiên sử dụng
transform
vàopacity
. - Sử dụng CSS containment: Cô lập các phần của trang để tối ưu render.
- Tối ưu hóa critical CSS: Inline CSS quan trọng và tải phần còn lại không đồng bộ.
/* Sử dụng transform thay vì thay đổi position */
.animation-good {
transform: translateX(100px);
}
/* Tránh sử dụng */
.animation-bad {
left: 100px;
}
/* Sử dụng CSS containment */
.component {
contain: content;
}
/* Sử dụng will-change cho animation */
.animated-element {
will-change: transform;
}
Kết luận
Hiểu và áp dụng các nguyên lý cơ bản về hiệu suất frontend là bước đầu tiên để tạo ra các trang web nhanh, phản hồi tốt và mang lại trải nghiệm người dùng tuyệt vời. Bằng cách tối ưu hóa Critical Rendering Path, hình ảnh, JavaScript và CSS, bạn có thể cải thiện đáng kể hiệu suất trang web của mình.