Frontend cơ bản – Một trang web được render ra làm sao?

render-page-v

Render một trang web là quá trình hiển thị trang web bắt đầu từ lúc bạn nhận được dữ liệu từ server (sau khi bạn gõ một tên miền – chẳng hạn như lienxo.us – vào thanh trình duyệt), đến khi trang web (bao gồm hình ảnh, âm thanh, chữ viết) được hiển thị đầy đủ trên màn hình. Quá trình này thực tế khá phức tạp và trải qua nhiều xử lý khác nhau, việc nắm được cách thức render giúp ích rất nhiều cho việc optimize tốc độ load trang.
Chúng ta hãy bắt đầu với một cái nhìn tổng quan về các hoạt động xảy ra ở trình duyệt trong quá trình render:

  1. Từ dữ liệu HTML đã nhận từ server Browser tạo ra DOM (Document Object Model) .
  2. Styles được load và parsed (phân tích) để tạo ra CSSOM (CSS Object Model).
  3. Dựa trên DOM và CSSOM ở trên, browser dựng lên một rendering tree – là một tập các object sẽ được render (Webkit gọi nó là render object hay renderer, trong khi đó Gecko gọi nó là một frame). Render tree có cấu trúc mô phỏng theo DOM và loại trừ các thành phần không được hiển thị (chẳng hạn thẻ hay các thành phần có style display:none). Mỗi đoạn text được biểu diễn như là một renderer tách biệt trong rendering tree. Mỗi đối tượng render chứa một đối tượng DOM tương ứng (hoặc một đoạn text) cộng với styles đã tính toán. Nói cách khác, render tree mô tả một biểu diễn hình ảnh của một DOM.
  4. Với mỗi thành phần render tree, các toạ độ tương ứng cũng được tính toán và được gọi là “layout”.
  5. Cuối cùng, nội dung trang web được hiển thị lên màn hình, quá trình này gọi là “painting”.

Khi user thao tác với trang web, hoặc là có đoạn script nào đó thay đổi trang web thì các bước kể trên được lặp lại vì cấu trúc trang web đã bị thay đổi.

Repaint

Nếu như chỉ thay đổi style của các element mà không làm thay đổi đến vị trí các element trên trang web (chẳng hạn background-color, border-color, visibility), thì trình duyệt chỉ cần repaint các element đó với style mới (có thể gọi là restyle).

Reflow

Khi thay đổi nội dung hay cấu trúc của trang web thì sẽ xảy ra quá trình gọi là reflow (còn gọi là relayout). Những thay đổi trên có thể kể đến như:

  • Thao tác tới DOM (thêm, sửa, xoá element)
  • Thay đổi nội dung, bao gồm text trong form
  • Tính toán hoặc thay đổi các CSS property
  • Thêm hay xoá style sheet
  • Thay đổi thuộc tính class
  • Thay đổi cửa sổ trình duyệt (thay đổi kích thước cửa sổ, cuộn trang)
  • Kích hoạt đến pseduo-class (chẳng hạn class :hover)

Browser optimize quá trình render trang như thế nào

Browser sẽ cố gắng giới hạn việc repaint/reflow chỉ trong phạm vi chứa các element bị thay đổi. Ví dụ, thay đổi kích thước của 1 element với style absolute/fixed chỉ ảnh hưởng đến bản thân element đấy và các element con của nó, trong khi nếu element đó có style là static position thì thay đổi sẽ ảnh hưởng tất cả các element khác.

Một cách khác để optimize là khi chạy code JavaScript, browser sẽ cache lại những thay đổi và áp dụng chúng vào một node liên quan sau khi code chạy xong. Chẳng hạn đoạn code sau chỉ kích hoạt một reflow và repaint:

var $body = $('body');
$body.css('padding', '1px'); // reflow, repaint 
$body.css('color', 'red'); // repaint 
$body.css('margin', '2px'); // reflow, repaint 
// only 1 reflow and repaint will actually happen

Lời khuyên hữu ích cho việc optimize

  • Code HTML và CSS phải đúng chuẩn, mặc dù nếu có gặp 1 lỗi cú pháp thì trang web vẫn chạy như thường. Styles cần cho vào trong phần <head> còn các mã JavaScript cần cho vào trong thẻ <body>
  • Cố gắng đơn giản hoá các CSS selector, tối thiểu hoá số lượng nesting (các CSS selector lồng vào nhau). Xếp theo mức độ nhanh đến chậm thì CSS selector được liệt kê như sau:
    1. Identificator: #id
    2. Class: .class
    3. Tag: div
    4. Selector nối tiếp: a + i
    5. Selector cha: ul > li
    6. Selector tổng: *
    7. Attribute selector: input[type=”text”]
    8. Pseudoclasse, Pseudoelement: a:hover
div * {...} // bad 
.list li {...} // bad 
.list-item {...} // good 
#list .list-item {...} // good
  • Tối thiểu hoá thao tác tới DOM, dùng cache mọi chỗ có thể
  • Nếu dùng jQuery, hãy tuân theo jQuery selectors best practices.
  • Nếu cần thay đổi style của element, nên thay đổi class vì sẽ có performant tốt nhất.
  • Chỉ animate những element có style absolute/fixed
  • Disable :hover animation khi kéo trang (thêm “no-hover” vào <body>). Xem thêm tại đây.

Dammecode via frontendbabel

Leave a comment