Tìm hiểu chi tiết về trình duyệt web hiện đại (phần 2)

Mariko Kosaka

Điều gì xảy ra trong quá trình điều hướng

Đây là phần 2 của loạt bài gồm 4 phần trên blog, tìm hiểu về cách hoạt động bên trong của Chrome. Trong bài đăng trước, chúng ta đã xem xét cách các quy trình và luồng xử lý các phần khác nhau của trình duyệt. Trong bài đăng này, chúng ta sẽ tìm hiểu sâu hơn về cách mỗi quy trình và luồng giao tiếp để hiển thị một trang web.

Hãy xem xét một trường hợp sử dụng đơn giản của việc duyệt web: bạn nhập một URL vào trình duyệt, sau đó trình duyệt sẽ tìm nạp dữ liệu từ Internet và hiển thị một trang. Trong bài đăng này, chúng ta sẽ tập trung vào phần mà người dùng yêu cầu một trang web và trình duyệt chuẩn bị hiển thị một trang – còn gọi là điều hướng.

Quá trình này bắt đầu bằng một quy trình trình duyệt

Quy trình của trình duyệt
Hình 1: Giao diện người dùng của trình duyệt ở trên cùng, sơ đồ quy trình của trình duyệt với luồng giao diện người dùng, mạng và bộ nhớ ở bên dưới

Như chúng ta đã đề cập trong phần 1: CPU, GPU, Bộ nhớ và cấu trúc đa quy trình, mọi thứ bên ngoài thẻ đều do quy trình trình duyệt xử lý. Quá trình trình duyệt có các luồng như luồng giao diện người dùng vẽ các nút và trường nhập của trình duyệt, luồng mạng xử lý ngăn xếp mạng để nhận dữ liệu từ Internet, luồng bộ nhớ kiểm soát quyền truy cập vào các tệp và nhiều luồng khác. Khi bạn nhập URL vào thanh địa chỉ, dữ liệu đầu vào của bạn sẽ được xử lý bằng luồng giao diện người dùng của quy trình trình duyệt.

Một thành phần điều hướng đơn giản

Bước 1: Xử lý dữ liệu đầu vào

Khi người dùng bắt đầu nhập vào thanh địa chỉ, điều đầu tiên mà luồng giao diện người dùng hỏi là "Đây có phải là cụm từ tìm kiếm hay URL không?". Trong Chrome, thanh địa chỉ cũng là một trường nhập dữ liệu tìm kiếm, vì vậy, luồng giao diện người dùng cần phân tích cú pháp và quyết định xem sẽ chuyển bạn đến một công cụ tìm kiếm hay đến trang web mà bạn yêu cầu.

Xử lý hoạt động đầu vào của người dùng
Hình 1: Luồng giao diện người dùng hỏi liệu dữ liệu đầu vào là cụm từ tìm kiếm hay URL

Bước 2: Bắt đầu chỉ đường

Khi người dùng nhấn enter, luồng giao diện người dùng sẽ bắt đầu một lệnh gọi mạng để lấy nội dung trang web. Vòng quay tải sẽ hiển thị ở góc của một thẻ và luồng mạng sẽ đi qua các giao thức thích hợp như tra cứu DNS và thiết lập Kết nối TLS cho yêu cầu.

Bắt đầu điều hướng
Hình 2: luồng giao diện người dùng giao tiếp với luồng mạng để chuyển đến mysite.com

Tại thời điểm này, luồng mạng có thể nhận được tiêu đề chuyển hướng máy chủ như HTTP 301. Trong trường hợp đó, luồng mạng sẽ giao tiếp với luồng giao diện người dùng mà máy chủ đang yêu cầu chuyển hướng. Sau đó, một yêu cầu URL khác sẽ được bắt đầu.

Bước 3: Đọc câu trả lời

Phản hồi HTTP
Hình 3: tiêu đề phản hồi chứa Content-Type và tải trọng là dữ liệu thực tế

Khi phần nội dung phản hồi (trọng tải) bắt đầu đến, luồng mạng sẽ xem xét vài byte đầu tiên của luồng nếu cần. Tiêu đề Content-Type của phản hồi sẽ cho biết đó là loại dữ liệu nào, nhưng vì tiêu đề này có thể bị thiếu hoặc không chính xác, nên tìm nạp loại MIME sẽ được thực hiện tại đây. Đây là một "việc khó khăn" như đã nhận xét trong mã nguồn. Bạn có thể đọc nhận xét để xem các trình duyệt khác nhau xử lý các cặp loại nội dung/trọng tải như thế nào.

Nếu phản hồi là tệp HTML, thì bước tiếp theo sẽ là truyền dữ liệu đến quy trình trình kết xuất, nhưng nếu đó là tệp zip hoặc một số tệp khác, thì tức là đó là yêu cầu tải xuống, vì vậy, chúng cần truyền dữ liệu đến trình quản lý tải xuống.

Nghe trộm loại MIME
Hình 4: Luồng mạng hỏi liệu dữ liệu phản hồi có phải là HTML từ một trang web an toàn hay không

Đây cũng là nơi diễn ra quy trình kiểm tra SafeBrowsing. Nếu miền và dữ liệu phản hồi có vẻ khớp với một trang web độc hại đã biết, thì luồng mạng sẽ cảnh báo để hiển thị một trang cảnh báo. Ngoài ra, quy trình kiểm tra Cross Origin Read Blocking (CORB) sẽ diễn ra để đảm bảo dữ liệu nhạy cảm trên nhiều trang web không được đưa vào quy trình kết xuất.

Bước 4: Tìm quy trình kết xuất

Sau khi tất cả các bước kiểm tra hoàn tất và luồng Mạng tự tin rằng trình duyệt sẽ chuyển đến trang web được yêu cầu, luồng Mạng sẽ thông báo cho luồng giao diện người dùng rằng dữ liệu đã sẵn sàng. Sau đó, luồng giao diện người dùng sẽ tìm một quy trình kết xuất để tiếp tục kết xuất trang web.

Tìm quy trình kết xuất
Hình 5: Luồng mạng yêu cầu luồng giao diện người dùng tìm Quy trình kết xuất

Vì yêu cầu mạng có thể mất vài trăm mili giây để nhận được phản hồi, nên một phương thức tối ưu hoá sẽ được áp dụng để đẩy nhanh quá trình này. Khi luồng giao diện người dùng đang gửi yêu cầu URL đến luồng mạng ở bước 2, luồng này đã biết trang web mà họ đang điều hướng đến. Luồng giao diện người dùng cố gắng chủ động tìm hoặc bắt đầu một quy trình kết xuất song song với yêu cầu mạng. Bằng cách này, nếu mọi thứ diễn ra như dự kiến, thì quá trình kết xuất sẽ ở trạng thái chờ khi luồng mạng nhận được dữ liệu. Quá trình chờ này có thể không được sử dụng nếu thao tác điều hướng chuyển hướng trên nhiều trang web, trong trường hợp đó, bạn có thể cần một quy trình khác.

Bước 5: Cam kết điều hướng

Giờ đây, dữ liệu và quy trình kết xuất đã sẵn sàng, IPC sẽ được gửi từ quy trình trình duyệt đến quy trình kết xuất để thực hiện thao tác điều hướng. Lớp này cũng truyền luồng dữ liệu để quá trình kết xuất có thể tiếp tục nhận dữ liệu HTML. Sau khi quy trình trình duyệt nghe được thông báo xác nhận rằng quá trình xác nhận đã xảy ra trong quy trình kết xuất, quá trình điều hướng sẽ hoàn tất và giai đoạn tải tài liệu sẽ bắt đầu.

Tại thời điểm này, thanh địa chỉ sẽ được cập nhật và chỉ báo bảo mật cũng như giao diện người dùng cài đặt trang web sẽ phản ánh thông tin trang web của trang mới. Nhật ký phiên hoạt động cho thẻ sẽ được cập nhật để các nút quay lại/tiến sẽ chuyển đến trang web vừa được truy cập. Để hỗ trợ khôi phục thẻ/phiên khi bạn đóng thẻ hoặc cửa sổ, nhật ký phiên sẽ được lưu trữ trên ổ đĩa.

Cam kết điều hướng
Hình 6: IPC giữa trình duyệt và các quy trình kết xuất, yêu cầu kết xuất trang

Bước bổ sung: Đã tải xong ban đầu

Sau khi điều hướng được thực hiện, quá trình kết xuất sẽ tiếp tục tải tài nguyên và hiển thị trang. Chúng tôi sẽ trình bày chi tiết về những gì xảy ra ở giai đoạn này trong bài đăng tiếp theo. Sau khi quá trình kết xuất "hoàn tất" quá trình kết xuất, quá trình này sẽ gửi một IPC trở lại quy trình trình duyệt (đây là sau khi tất cả các sự kiện onload đã kích hoạt trên tất cả các khung trong trang và đã hoàn tất quá trình thực thi). Tại thời điểm này, luồng giao diện người dùng sẽ dừng vòng quay đang tải trên thẻ.

Tôi nói "kết thúc" vì JavaScript phía máy khách vẫn có thể tải thêm tài nguyên và hiển thị các thành phần hiển thị mới sau thời điểm này.

Trang hoàn tất quá trình tải
Hình 7: IPC từ trình kết xuất đến quy trình trình duyệt để thông báo rằng trang đã "tải"

Bạn đã hoàn tất phần điều hướng đơn giản! Nhưng điều gì sẽ xảy ra nếu người dùng đặt một URL khác vào thanh địa chỉ lần nữa? Quy trình của trình duyệt cũng trải qua các bước tương tự để chuyển đến trang web khác. Nhưng trước khi có thể làm như vậy, trình xử lý cần kiểm tra với trang web hiện đang hiển thị xem họ có quan tâm đến sự kiện beforeunload hay không.

beforeunload có thể tạo cảnh báo "Rời khỏi trang web này?" khi bạn cố gắng rời khỏi hoặc đóng thẻ. Mọi thứ bên trong một thẻ, bao gồm cả mã JavaScript, đều do quy trình kết xuất xử lý. Vì vậy, quy trình trình duyệt phải kiểm tra với quy trình kết xuất hiện tại khi có yêu cầu điều hướng mới.

trình xử lý sự kiện beforeunload
Hình 8: IPC từ quy trình trình duyệt đến quy trình trình kết xuất cho biết rằng quy trình này sắp chuyển đến một trang web khác

Nếu thao tác điều hướng được bắt đầu từ quy trình trình kết xuất (chẳng hạn như người dùng nhấp vào một đường liên kết hoặc JavaScript phía máy khách đã chạy window.location = "https://newsite.com"), thì trước tiên, quy trình trình kết xuất sẽ kiểm tra trình xử lý beforeunload. Sau đó, thao tác này sẽ trải qua quy trình tương tự như thao tác điều hướng do trình duyệt khởi tạo. Điểm khác biệt duy nhất là yêu cầu điều hướng được khởi động từ quy trình kết xuất hình ảnh sang quy trình trình duyệt.

Khi điều hướng mới được thực hiện đến một trang web khác với trang web hiện đang hiển thị, một quy trình kết xuất riêng biệt sẽ được gọi để xử lý điều hướng mới trong khi quy trình kết xuất hiện tại vẫn được giữ lại để xử lý các sự kiện như unload. Để biết thêm thông tin, hãy xem tổng quan về các trạng thái vòng đời của trang và cách bạn có thể liên kết với các sự kiện bằng API Vòng đời trang.

điều hướng và tải xuống mới
Hình 9: 2 IPC từ một quy trình trình duyệt đến một quy trình kết xuất mới yêu cầu hiển thị trang và yêu cầu quy trình kết xuất cũ tải xuống

Trong trường hợp của Trình chạy dịch vụ

Một thay đổi gần đây đối với quy trình điều hướng này là việc giới thiệu worker dịch vụ. Trình chạy dịch vụ là một cách để ghi proxy mạng trong mã ứng dụng của bạn; cho phép nhà phát triển web có nhiều quyền kiểm soát hơn đối với nội dung cần lưu vào bộ nhớ đệm cục bộ và thời điểm nhận dữ liệu mới từ mạng. Nếu bạn đặt trình chạy dịch vụ để tải trang từ bộ nhớ đệm, thì bạn không cần yêu cầu dữ liệu từ mạng.

Điều quan trọng cần nhớ là worker dịch vụ là mã JavaScript chạy trong quy trình trình kết xuất. Nhưng khi yêu cầu điều hướng đến, làm cách nào để quy trình của trình duyệt biết rằng trang web có worker dịch vụ?

Truy vấn phạm vi của trình chạy dịch vụ
Hình 10: luồng mạng trong quy trình duyệt web tra cứu phạm vi của worker dịch vụ

Khi một worker dịch vụ được đăng ký, phạm vi của worker dịch vụ sẽ được giữ lại làm tham chiếu (bạn có thể đọc thêm về phạm vi trong bài viết Vòng đời của worker dịch vụ). Khi một thao tác điều hướng xảy ra, luồng mạng sẽ kiểm tra miền theo phạm vi trình chạy dịch vụ đã đăng ký. Nếu một trình chạy dịch vụ được đăng ký cho URL đó, luồng giao diện người dùng sẽ tìm một quy trình kết xuất để thực thi mã trình chạy dịch vụ. Trình chạy dịch vụ có thể tải dữ liệu từ bộ nhớ đệm, giúp bạn không cần yêu cầu dữ liệu từ mạng hoặc có thể yêu cầu tài nguyên mới từ mạng.

điều hướng serviceworker
Hình 11: luồng giao diện người dùng trong một quy trình trình duyệt khởi động một quy trình kết xuất để xử lý trình thực thi dịch vụ; sau đó, luồng worker trong quy trình kết xuất sẽ yêu cầu dữ liệu từ mạng

Bạn có thể thấy rằng hành trình đi và về này giữa quy trình trình duyệt và quy trình trình kết xuất có thể dẫn đến độ trễ nếu cuối cùng trình chạy dịch vụ quyết định yêu cầu dữ liệu từ mạng. Tải trước điều hướng là một cơ chế giúp tăng tốc quá trình này bằng cách tải tài nguyên song song với quá trình khởi động worker dịch vụ. Phương thức này đánh dấu các yêu cầu này bằng một tiêu đề, cho phép máy chủ quyết định gửi nội dung khác cho các yêu cầu này; ví dụ: chỉ gửi dữ liệu đã cập nhật thay vì toàn bộ tài liệu.

Tải trước thành phần điều hướng
Hình 12: luồng giao diện người dùng trong một quy trình duyệt web khởi động quy trình kết xuất để xử lý worker dịch vụ trong khi khởi động yêu cầu mạng song song

Tổng kết

Trong bài đăng này, chúng ta đã xem xét những gì xảy ra trong quá trình điều hướng và cách mã ứng dụng web của bạn (chẳng hạn như tiêu đề phản hồi và JavaScript phía máy khách) tương tác với trình duyệt. Khi biết các bước mà trình duyệt thực hiện để lấy dữ liệu từ mạng, bạn sẽ dễ dàng hiểu lý do các API như tải trước điều hướng được phát triển. Trong bài đăng tiếp theo, chúng ta sẽ tìm hiểu cách trình duyệt đánh giá HTML/CSS/JavaScript để hiển thị trang.

Bạn có thích bài đăng này không? Nếu bạn có câu hỏi hoặc đề xuất cho bài đăng sau này, tôi rất mong nhận được ý kiến của bạn trong phần bình luận bên dưới hoặc trên Twitter theo tên người dùng @kosamari.

Tiếp theo: Cách hoạt động bên trong của Quy trình kết xuất