Anh em làm frontend web thường xuyên làm việc với HTML CSS, khi các bạn viết xong code và thực hiện chạy nó trên browsers (trình duyệt), chúng sẽ được xử lý qua 1 chuỗi các bước để xây dựng và hiển thị trang web đó lên. Các bạn có bao giờ lăn tăn xem trình duyệt cụ thể là làm những gì đối với file .html của chúng ta không? Bài viết này sẽ giới thiệu với các bạn các bước xử lý của trình duyệt. Trước tiên thì chúng ta sẽ sử dụng file html sau (có chứa có css và script)
<!DOCTYPE html>
<html>
<head>
<title>The "Click the button" page</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<h1>
Click the button.
</h1>
<button type="button">Click me</button>
<script>
var button = document.querySelector("button");
button.style.fontWeight = "bold";
button.addEventListener("click", function () {
alert("Well done.");
});
</script>
</body>
</html>
Khi trình duyệt nhận được file HTML, nó sẽ thực hiện luồng các bước xử lý như sau:
- Sử dụng file HTML để tạo DOM (Document Object Model)
- Sử dụng CSS để tạo CSSOM (CSS Object Model)
- Chạy Script xử lý DOM và CSSOM kết hợp để tạo thành Render Tree
- Sử dụng Render Tree để Layout (xác định size và position của toàn bộ phần tử trên trang web)
- Paint tất cả các pixel (hiển thị lên màn hình)
Cụ thể chúng ta sẽ đi vào từng bước nhé:
Bước 1: HTML
Trình duyệt đọc file HTML từ trên xuống dưới và sử dụng nó để tạo ra các node từ file HTML. Như file HTML đầu bài, các node sẽ được sinh ra như hình trên, từ đó sẽ tạo thành cây DOM.
Lưu ý: từ việc tạo DOM trên thì chúng ta nên đặt style ở ngay trên đầu và script ở cuối file vì style luôn cần được load sớm, còn script thì ngược lại càng muộn càng tốt (vì phải có HTML với CSS thì script mới chạy).
Bước 2: CSS
// External stylesheet
<link rel="stylesheet" href="styles.css">
// Internal styles
<style>
h1 {
font-size: 18px;
}
</style>
// Inline styles
<button style="background-color: blue;">Click me</button>
CSSOM cũng được tạo ra 1 cách tương tự như DOM
Ở đây chúng ta thấy rằng Trình duyệt sẽ chỉ Render Tree được khi DOM và CSSOM được tạo hoàn chỉnh, vì thế CSSOM sẽ chặn quá trình render trang web và chúng ta có 1 khái niệm gọi là “Render Blocking” để chỉ những node liên quan đến style dùng để tạo CSSOM. Cũng vì thế mà chúng ta nên giảm kích thước style và load chúng càng sớm càng tốt, ngược lại những style dư thừa (hoặc chưa cần thiết) thì nên cắt bớt hoặc trì hoãn tải tối đa có thể.
Bước 3: JavaScript
Nếu trình duyệt tìm thấy những javascript node (external hoặc internal) như dưới đây
// An external script
http://app.js
// An internal script
<script>
alert("Oh, hello");
</script>
lúc đó việc parse file HTML và tạo DOM/CSSDOM node sẽ bị dừng lại để chờ xử lý. Từ đó chúng ta lại có thêm 1 thuật ngữ là “Parser blocking” để chỉ những đoạn JavaScript trên. Ví dụ ta có 1 đoạn script như sau:
var button = document.querySelector("button");
button.style.fontWeight = "bold";
button.addEventListener("click", function () {
alert("Well done.");
});
Nó sẽ ảnh hưởng đến DOM và CSSOM như sau:
Vì những script có thể cần đến HTML hoặc style để xử lý, do vậy chúng ta nên chạy script khi những phần tử đó đã sẵn sàng. Nếu có nhiều external script thì trình duyệt sẽ tải về và chạy lần lượt theo thứ tự trước sau.
Lưu ý: chúng ta có thể sử dụng attribute “async” để tải script về 1 cách không đồng bộ trên 1 thread khác và tiếp tục parse trang, khi nào việc tải về hoàn tất thì nó sẽ được chạy.
http://async-script.js
http://defer-script.js
async và defer đều là trì hoàn việc tải script về để không chặn việc load trang; điểm khác nhau là defer sẽ chỉ chạy khi HTML parse xong và chạy theo thứ tự, còn async thì có thể chạy ở bất kỳ thời điểm nào khi nó load xong. Các bạn có thể xem hình dưới để dễ hình dung:
Từ đó ta thấy async sẽ hữu ích với những script không tác động gì đến DOM/CSSOM, không ảnh hưởng gì đến UX, ví dụ như analytics hoặc tracking. Còn defer thì sẽ hữu ích với những script tác động đến Render Tree nhưng không liên quan gì đến việc hiển thị phần above the fold (phần trên nếp gấp) của trang web hoặc cần những script khác chạy trước nó.
Bước 4: Render Tree
Khi tất cả các node đã được đọc, DOM và CSSOM đã sẵn sàng thì trình duyệt sẽ ghép chúng lại và dựng Render Tree.
Bước 5: Layout
Ở bước này, trình duyệt sẽ xác định size và position của tất cả các phần tử trên trang web.
Bước 6: Paint
Bước cuối cùng là vẽ và hiển thị trang trên màn hình.
Nhìn thì nhiều bước thế thôi nhưng toàn bộ quá trình này thưởng chỉ diễn ra trong vài giây hoặc vài chục giây. Tối ưu tốc độ load trang là 1 việc không dễ cho các frontend developer. Hy vọng bài viết sẽ cho các bạn cái nhìn tổng quan về quá trình 1 website được tạo ra.
Cảm ơn các bạn đã đọc
Các link tham khảo
https://www.internetmarketingninjas.com/google-core-web-vitals/
https://andydavies.me/blog/2013/10/22/how-the-browser-pre-loader-makes-pages-load-faster/
https://hackernoon.com/optimising-the-front-end-for-the-browser-f2f51a29c572
From Anyway with Love!