Kết xuất trên web

Chúng ta nên triển khai logic và kết xuất ở đâu trong các ứng dụng của mình? Chúng ta có nên sử dụng tính năng Hiển thị phía máy chủ không? Còn việc bổ sung nước thì sao? Hãy cùng khám phá một số câu trả lời!

Là nhà phát triển, chúng tôi thường phải đối mặt với những quyết định ảnh hưởng đến toàn bộ kiến trúc của ứng dụng. Một trong những quyết định cốt lõi mà nhà phát triển web phải đưa ra là nơi triển khai logic và kết xuất trong ứng dụng của họ. Việc này có thể khó khăn vì có nhiều cách để tạo trang web.

Chúng tôi hiểu rõ hơn về không gian này dựa trên công việc của chúng tôi trong quá trình Chrome trao đổi với các trang web lớn trong vài năm qua. Nói chung, các nhà phát triển nên cân nhắc sử dụng phương pháp kết xuất phía máy chủ hoặc kết xuất tĩnh thay vì phương pháp bù nước hoàn toàn.

Để hiểu rõ hơn về kiến trúc mà chúng tôi đang lựa chọn khi đưa ra quyết định này, chúng tôi cần hiểu rõ về từng phương pháp và thuật ngữ nhất quán để sử dụng khi nói về chúng. Sự khác biệt giữa những phương pháp này giúp minh hoạ sự đánh đổi của việc kết xuất trên web thông qua lăng kính hiệu suất.

Thuật ngữ

Kết xuất

  • Hiển thị phía máy chủ (SSR): kết xuất phía máy khách hoặc ứng dụng phổ quát thành HTML trên máy chủ.
  • Hiển thị phía máy khách (CSR): hiển thị ứng dụng trong trình duyệt thông qua JavaScript để sửa đổi DOM.
  • Rehydration: "khởi động" các chế độ xem JavaScript trên máy khách để chúng có thể sử dụng lại cây và dữ liệu DOM của HTML do máy chủ kết xuất.
  • Kết xuất trước: chạy ứng dụng phía máy khách tại thời điểm xây dựng để có được trạng thái ban đầu dưới dạng HTML tĩnh.

Hiệu suất

Kết xuất phía máy chủ

Tính năng hiển thị phía máy chủ tạo ra HTML đầy đủ cho một trang trên máy chủ để phản hồi quá trình điều hướng. Điều này giúp tránh phải nhận thêm các lượt khứ hồi để tìm nạp và tạo mẫu trên máy khách, vì quá trình này được xử lý trước khi trình duyệt nhận được phản hồi.

Quá trình kết xuất phía máy chủ thường tạo ra FCP nhanh. Việc chạy logic trang và hiển thị trên máy chủ giúp bạn có thể tránh phải gửi nhiều JavaScript đến máy khách. Điều này giúp giảm TBT của trang, điều này cũng có thể dẫn đến INP thấp hơn, vì luồng chính không bị chặn thường xuyên trong khi tải trang. Khi luồng chính bị chặn ít thường xuyên hơn, các hoạt động tương tác của người dùng sẽ có nhiều cơ hội chạy sớm hơn. Điều này hợp lý vì khi hiển thị phía máy chủ, bạn thực sự chỉ gửi văn bản và đường liên kết đến trình duyệt của người dùng. Phương pháp này có thể hoạt động hiệu quả cho nhiều điều kiện thiết bị và mạng, đồng thời mở ra các phương pháp tối ưu hoá thú vị cho trình duyệt như phân tích cú pháp tài liệu truyền trực tuyến.

Sơ đồ cho thấy việc hiển thị phía máy chủ và việc thực thi JS ảnh hưởng đến FCP và TTI.

Với tính năng hiển thị phía máy chủ, người dùng ít có khả năng phải chờ JavaScript bị ràng buộc bởi CPU chạy trước khi họ có thể sử dụng trang web của bạn. Ngay cả khi không thể tránh được JS bên thứ ba, việc sử dụng tính năng hiển thị phía máy chủ để giảm chi phí JavaScript của bên thứ nhất có thể giúp bạn có nhiều ngân sách hơn cho phần còn lại. Tuy nhiên, có một sự đánh đổi tiềm năng với phương pháp này: việc tạo các trang trên máy chủ sẽ mất thời gian và có thể dẫn đến TTFB cao hơn.

Việc kết xuất phía máy chủ có đủ cho ứng dụng của bạn hay không phần lớn phụ thuộc vào loại trải nghiệm bạn đang xây dựng. Đã có nhiều tranh cãi đã lan truyền từ lâu về việc ứng dụng chính xác của tính năng hiển thị phía máy chủ và tính năng hiển thị phía máy khách, nhưng điều quan trọng cần nhớ là bạn chỉ có thể chọn sử dụng tính năng hiển thị phía máy chủ cho một số trang chứ không phải trang khác. Một số trang web đã áp dụng thành công kỹ thuật kết xuất kết hợp. Máy chủ Netflix kết xuất các trang đích tương đối tĩnh, trong khi tìm nạp trước JS cho các trang có nhiều lượt tương tác, nhờ đó, các trang do ứng dụng hiển thị nặng hơn này có cơ hội tải nhanh hơn.

Nhiều khung, thư viện và cấu trúc hiện đại giúp bạn có thể kết xuất cùng một ứng dụng trên cả ứng dụng khách và máy chủ. Bạn có thể sử dụng các kỹ thuật này để kết xuất phía máy chủ. Tuy nhiên, điều quan trọng cần lưu ý là các cấu trúc mà quá trình kết xuất diễn ra trên cả máy chủ trên ứng dụng khách là lớp giải pháp riêng với đặc điểm hiệu suất và sự đánh đổi rất khác nhau. Người dùng React có thể sử dụng API DOM máy chủ hoặc các giải pháp được xây dựng dựa trên những API này như Next.js để hiển thị phía máy chủ. Người dùng Vue có thể xem hướng dẫn kết xuất phía máy chủ hoặc Nuxt của Vue. Angular có hàm Universal. Tuy nhiên, hầu hết các giải pháp phổ biến đều sử dụng một dạng hydrat hoá, vì vậy hãy lưu ý phương pháp được sử dụng trước khi chọn một công cụ.

Kết xuất tĩnh

Quá trình kết xuất tĩnh diễn ra tại thời điểm tạo bản dựng. Phương pháp này mang lại FCP nhanh, TBT và INP thấp hơn — giả sử số lượng JS phía máy khách bị hạn chế. Không giống như tính năng hiển thị phía máy chủ, phương thức này cũng cố gắng đạt được TTFB nhanh một cách nhất quán, vì HTML cho một trang không phải được tạo động trên máy chủ. Nói chung, kết xuất tĩnh có nghĩa là tạo trước một tệp HTML riêng cho mỗi URL. Với phản hồi HTML được tạo trước, tính năng kết xuất tĩnh có thể được triển khai cho nhiều CDN để tận dụng chức năng lưu vào bộ nhớ đệm ở cạnh.

Sơ đồ cho thấy phương thức kết xuất tĩnh và thực thi JS không bắt buộc ảnh hưởng đến FCP và TTI.

Các giải pháp hiển thị tĩnh có đủ mọi hình dạng và kích thước. Các công cụ như Gatsby được thiết kế để giúp các nhà phát triển cảm thấy như ứng dụng của họ đang được kết xuất động thay vì được tạo dưới dạng một bước xây dựng. Các công cụ tạo trang web tĩnh như 11ty, JekyllMetalsmith tận dụng tính chất tĩnh, mang đến phương pháp tiếp cận dựa trên mẫu hơn.

Một trong những nhược điểm của hiển thị tĩnh là phải tạo các tệp HTML riêng lẻ cho mọi URL có thể có. Điều này có thể khó khăn hoặc thậm chí không khả thi khi bạn không thể dự đoán những URL đó sẽ xuất hiện trước thời gian nào hoặc đối với các trang web có số lượng lớn các trang riêng biệt.

Người dùng React có thể đã quen thuộc với Gatsby, Next.js static Export hoặc Navi – tất cả các thành phần này giúp người dùng dễ dàng soạn thảo trang bằng cách sử dụng các thành phần. Tuy nhiên, bạn cần hiểu rõ sự khác biệt giữa hiển thị tĩnh và kết xuất trước: các trang kết xuất tĩnh có tính tương tác mà không cần thực thi nhiều JavaScript phía máy khách, trong khi việc kết xuất trước sẽ cải thiện FCP của một Ứng dụng trang đơn mà phải được khởi động trên máy khách để các trang thực sự tương tác được.

Nếu bạn không chắc chắn liệu giải pháp đã cho là hiển thị tĩnh hay kết xuất trước, hãy thử vô hiệu hóa JavaScript và tải trang mà bạn muốn kiểm tra. Đối với các trang hiển thị tĩnh, hầu hết các chức năng sẽ vẫn tồn tại khi không bật JavaScript. Đối với các trang được kết xuất trước, có thể vẫn còn một số chức năng cơ bản như đường liên kết, nhưng hầu hết trang sẽ không hoạt động.

Một cách kiểm tra hữu ích khác là sử dụng tính năng điều tiết mạng trong Công cụ của Chrome cho nhà phát triển và quan sát lượng JavaScript đã tải xuống trước khi một trang có tính tương tác. Quá trình kết xuất trước thường yêu cầu nhiều JavaScript hơn để trở thành tương tác và JavaScript có xu hướng phức tạp hơn so với phương pháp nâng cao tăng dần sử dụng theo phương pháp kết xuất tĩnh.

Kết xuất phía máy chủ so với kết xuất tĩnh

Tính năng hiển thị phía máy chủ không phải là giải pháp dễ dàng vì bản chất linh động của tính năng này có thể dẫn đến chi phí điện toán đáng kể. Nhiều giải pháp hiển thị phía máy chủ không đẩy sớm, có thể trì hoãn TTFB hoặc tăng gấp đôi dữ liệu được gửi (ví dụ: trạng thái cùng dòng được JavaScript sử dụng trên máy khách). Trong React, renderToString() có thể bị chậm vì có tính đồng bộ và đơn luồng. API DOM máy chủ React mới hơn hỗ trợ truyền trực tuyến, có thể nhận phần đầu của phản hồi HTML cho trình duyệt sớm hơn trong khi phần còn lại vẫn đang được tạo trên máy chủ.

Quá trình kết xuất phía máy chủ "đúng" có thể liên quan đến việc tìm hoặc xây dựng một giải pháp để lưu vào bộ nhớ đệm thành phần, quản lý mức sử dụng bộ nhớ, áp dụng các kỹ thuật bộ nhớ và nhiều vấn đề khác. Thông thường, bạn sẽ xử lý/tạo lại cùng một ứng dụng nhiều lần – một lần trên ứng dụng và một lần trên máy chủ. Việc kết xuất phía máy chủ có thể giúp nội dung xuất hiện sớm hơn không đột nhiên có nghĩa là bạn phải làm nhiều việc hơn. Nếu bạn có nhiều khối lượng công việc trên ứng dụng sau khi phản hồi HTML do máy chủ tạo đến ứng dụng, điều này vẫn có thể dẫn đến TBT và INP cao hơn cho trang web của bạn.

Chế độ hiển thị phía máy chủ tạo HTML theo yêu cầu cho từng URL, nhưng có thể chậm hơn so với việc chỉ phân phát nội dung kết xuất tĩnh. Nếu bạn có thể thực hiện thêm công việc, thì tính năng hiển thị phía máy chủ cộng với lưu HTML vào bộ nhớ đệm có thể làm giảm đáng kể thời gian kết xuất phía máy chủ. Ưu điểm của chế độ hiển thị phía máy chủ là khả năng lấy nhiều dữ liệu "trực tiếp" hơn và phản hồi một nhóm yêu cầu hoàn chỉnh hơn so với phương thức kết xuất tĩnh. Các trang yêu cầu cá nhân hóa là ví dụ cụ thể về loại yêu cầu không hoạt động tốt với kết xuất tĩnh.

Quá trình kết xuất phía máy chủ cũng có thể đưa ra những quyết định thú vị khi xây dựng PWA: nên sử dụng bộ nhớ đệm service worker toàn trang hay chỉ kết xuất từng phần nội dung qua máy chủ?

Kết xuất phía máy khách

Hiển thị phía máy khách nghĩa là hiển thị các trang trực tiếp trong trình duyệt bằng JavaScript. Mọi logic, việc tìm nạp dữ liệu, tạo mẫu và định tuyến đều được xử lý trên máy khách chứ không phải trên máy chủ. Kết quả hiệu quả là nhiều dữ liệu hơn được chuyển từ máy chủ đến thiết bị của người dùng, đi kèm với một bộ đánh đổi riêng.

Tính năng hiển thị phía máy khách có thể khó tải và duy trì nhanh chóng đối với thiết bị di động. Nếu thực hiện ít thao tác nhất, thì tính năng hiển thị phía máy khách có thể đạt hiệu suất hoàn toàn của chế độ hiển thị phía máy chủ, duy trì ngân sách JavaScript chặt chẽ và mang lại giá trị trong ít lượt trọn vòng nhất có thể. Bạn có thể phân phối dữ liệu và tập lệnh quan trọng sớm hơn bằng cách sử dụng <link rel=preload>, nhờ đó, trình phân tích cú pháp sẽ hoạt động sớm hơn cho bạn. Các mẫu như PRPL cũng nên được đánh giá để đảm bảo các thao tác điều hướng ban đầu và tiếp theo đều diễn ra ngay lập tức.

Sơ đồ cho thấy quá trình kết xuất phía máy khách ảnh hưởng đến FCP và TTI.

Nhược điểm chính của việc kết xuất phía máy khách là số lượng JavaScript cần thiết có xu hướng tăng lên khi ứng dụng phát triển. Điều này có thể ảnh hưởng tiêu cực đến INP của trang. Điều này trở nên đặc biệt khó khăn khi có thêm thư viện JavaScript mới, đoạn mã polyfill và mã của bên thứ ba. Các đoạn mã này cạnh tranh về khả năng xử lý và thường phải được xử lý trước khi có thể hiển thị nội dung của một trang.

Những trải nghiệm sử dụng tính năng hiển thị phía máy khách dựa vào các gói JavaScript lớn nên cân nhắc việc phân tách mã linh hoạt để giảm TBT và INP trong quá trình tải trang, đồng thời đảm bảo tải từng phần JavaScript —"chỉ phân phát những gì bạn cần, khi bạn cần". Đối với những trải nghiệm có ít hoặc không có tính tương tác, tính năng kết xuất phía máy chủ có thể là một giải pháp dễ mở rộng hơn cho những vấn đề này.

Đối với những người tạo các ứng dụng trang đơn, việc xác định các phần cốt lõi của giao diện người dùng được hầu hết các trang chia sẻ có nghĩa là bạn có thể áp dụng kỹ thuật lưu vào bộ nhớ đệm shell ứng dụng. Khi kết hợp với trình chạy dịch vụ, điều này có thể cải thiện đáng kể hiệu suất dự kiến trong các lượt truy cập lặp lại, vì HTML shell của ứng dụng và các phần phụ thuộc của nó có thể được tải rất nhanh từ CacheStorage.

Kết hợp quá trình kết xuất phía máy chủ và kết xuất phía máy khách thông qua quá trình tái nạp nước

Phương pháp này cố gắng cân bằng sự đánh đổi giữa hiển thị phía máy khách và hiển thị phía máy chủ bằng cách thực hiện cả hai. Các yêu cầu điều hướng như tải hoặc tải lại toàn bộ trang được xử lý bởi máy chủ hiển thị ứng dụng thành HTML, sau đó JavaScript và dữ liệu được sử dụng để kết xuất sẽ được nhúng vào tài liệu kết quả. Sau khi thực hiện cẩn thận, quá trình này sẽ đạt được FCP nhanh như kết xuất phía máy chủ, sau đó "Tiếp tục" bằng cách kết xuất lại trên ứng dụng bằng kỹ thuật (re)hydration. Đây là một giải pháp hiệu quả nhưng có thể có những hạn chế đáng kể về hiệu suất.

Nhược điểm chính của quá trình kết xuất phía máy chủ khi tái nước là có thể tác động tiêu cực đáng kể đến TBT và INP, ngay cả khi cải thiện FCP. Các trang do phía máy chủ hiển thị có thể giả vờ được tải và tương tác, nhưng thực tế không thể phản hồi dữ liệu đầu vào cho đến khi tập lệnh phía máy khách cho các thành phần được thực thi và trình xử lý sự kiện được đính kèm. Quá trình này có thể mất vài giây hoặc thậm chí vài phút trên thiết bị di động.

Có lẽ bạn đã gặp phải điều này — trong một khoảng thời gian sau khi có vẻ như trang đã tải, việc nhấp hoặc nhấn không có tác dụng gì. Điều này nhanh chóng trở nên khó chịu vì người dùng vẫn thắc mắc tại sao không có gì xảy ra khi họ cố tương tác với trang.

Vấn đề về tái nước: 1 ứng dụng giá 2 ứng dụng

Các vấn đề về bù nước thường có thể nghiêm trọng hơn so với khả năng tương tác bị trì hoãn do JavaScript. Để JavaScript phía máy khách có thể "nhận" chính xác vị trí máy chủ dừng lại mà không cần phải yêu cầu lại tất cả dữ liệu mà máy chủ đã sử dụng để hiển thị HTML, các giải pháp hiển thị phía máy chủ hiện tại thường chuyển đổi tuần tự phản hồi từ các phần phụ thuộc dữ liệu của giao diện người dùng vào tài liệu dưới dạng thẻ tập lệnh. Tài liệu HTML thu được chứa mức độ sao chép cao:

Tài liệu HTML chứa giao diện người dùng được tuần tự hoá, dữ liệu cùng dòng và tập lệnh Bundle.js

Như bạn có thể thấy, máy chủ đang trả về nội dung mô tả về giao diện người dùng của ứng dụng để phản hồi một yêu cầu điều hướng, nhưng cũng trả về dữ liệu nguồn dùng để tạo giao diện người dùng đó và một bản sao đầy đủ của quá trình triển khai giao diện người dùng, sau đó khởi động trên máy khách. Chỉ sau khi bundle.js tải và thực thi xong, giao diện người dùng này mới có thể tương tác.

Chỉ số hiệu suất được thu thập từ các trang web thực sử dụng tính năng hiển thị và khôi phục phía máy chủ cho biết bạn không nên sử dụng tính năng này. Suy cho cùng, nguyên nhân nằm ở trải nghiệm người dùng: rất dễ để họ rơi vào một "thung lũng kỳ lạ", nơi khả năng tương tác không có sẵn mặc dù trang có vẻ đã sẵn sàng.

Sơ đồ cho thấy việc kết xuất ứng dụng có ảnh hưởng tiêu cực đến TTI.

Tuy nhiên, vẫn có khả năng kết xuất phía máy chủ bằng tính năng bù nước. Trong ngắn hạn, việc chỉ sử dụng tính năng kết xuất phía máy chủ cho nội dung có thể lưu vào bộ nhớ đệm cao có thể làm giảm TTFB, tạo ra kết quả tương tự như kết xuất trước. Việc bổ sung nước tăng dần, tăng dần hoặc một phần có thể là chìa khoá để giúp kỹ thuật này trở nên khả thi hơn trong tương lai.

Truyền trực tuyến phía máy chủ và khôi phục nước tăng dần

Tính năng hiển thị phía máy chủ đã có một số bước phát triển trong vài năm qua.

Truyền trực tuyến phía máy chủ cho phép bạn gửi HTML theo từng phần mà trình duyệt có thể hiển thị dần khi nhận được. Điều này có thể dẫn đến tốc độ hiển thị FCP nhanh vì mã đánh dấu sẽ đến tay người dùng nhanh hơn. Trong React, các luồng không đồng bộ trong [renderToPipeableStream()] (so với renderToString() đồng bộ) có nghĩa là backpressure được xử lý tốt.

Bạn cũng nên cân nhắc tính năng bù nước tích luỹ và những việc mà React đã ra mắt. Với phương pháp này, từng phần của một ứng dụng do máy chủ kết xuất sẽ được "khởi động" theo thời gian, thay vì phương pháp phổ biến hiện tại là khởi động toàn bộ ứng dụng cùng một lúc. Điều này có thể giúp giảm lượng JavaScript cần thiết để các trang có khả năng tương tác, do quá trình nâng cấp phía máy khách các phần có mức độ ưu tiên thấp của trang có thể bị trì hoãn để tránh chặn luồng chính, cho phép người dùng tương tác diễn ra sớm hơn sau khi người dùng bắt đầu.

Quá trình bù nước tích cực cũng có thể giúp tránh một trong những sai lầm phổ biến nhất về việc bù nước khi kết xuất phía máy chủ, trong đó cây DOM do máy chủ kết xuất bị huỷ và sau đó được tạo lại ngay lập tức – thường xuyên nhất là do dữ liệu yêu cầu kết xuất phía máy khách đồng bộ ban đầu chưa sẵn sàng, có thể là đang chờ giải pháp của Promise.

Bù nước một phần

Phương pháp bù nước một phần cho thấy rất khó thực hiện. Phương pháp này là phần mở rộng của ý tưởng bù nước tăng dần, trong đó từng phần (các thành phần/khung hiển thị/cây) cần được bổ sung nước dần sẽ được phân tích và những thành phần có ít tương tác hoặc không có khả năng phản ứng được xác định. Đối với mỗi phần hầu hết tĩnh này, mã JavaScript tương ứng được chuyển thành tham chiếu tĩnh và chức năng trang trí, giúp giảm dấu chân phía máy khách xuống gần bằng 0.

Phương pháp bổ sung nước một phần cũng có những vấn đề và yếu tố ảnh hưởng riêng. Điều này đặt ra một số thách thức thú vị cho việc lưu vào bộ nhớ đệm và điều hướng phía máy khách có nghĩa là chúng ta không thể giả định HTML do máy chủ kết xuất cho các phần trơ của ứng dụng sẽ hoạt động mà không cần tải trang đầy đủ.

Kết xuất ba hình

Nếu bạn có thể sử dụng trình chạy dịch vụ, thì bạn cũng có thể quan tâm đến phương thức kết xuất "trisomorphic". Đây là kỹ thuật mà bạn có thể sử dụng tính năng hiển thị phía máy chủ truyền trực tuyến cho các thao tác điều hướng ban đầu/không phải JS, sau đó yêu cầu trình chạy dịch vụ thực hiện việc kết xuất HTML cho các thao tác điều hướng sau khi cài đặt. Điều này có thể luôn cập nhật các thành phần và mẫu được lưu vào bộ nhớ đệm, đồng thời cho phép điều hướng theo kiểu SPA để kết xuất các chế độ xem mới trong cùng một phiên. Phương pháp này hiệu quả nhất khi bạn có thể chia sẻ cùng một mã định tuyến và tạo mẫu giữa máy chủ, trang ứng dụng khách và trình chạy dịch vụ.

Sơ đồ kết xuất Trisomorphic, cho thấy một trình duyệt và trình chạy dịch vụ đang giao tiếp với máy chủ.

Những điều cần cân nhắc về SEO

Khi chọn chiến lược hiển thị nội dung trên web, các nhóm thường tác động đến tác động của SEO. Tính năng hiển thị phía máy chủ thường được chọn để cung cấp trải nghiệm "tìm kiếm hoàn chỉnh" mà trình thu thập thông tin có thể diễn giải dễ dàng. Trình thu thập dữ liệu có thể hiểu được JavaScript, nhưng thường có các hạn chế bạn cần lưu ý về cách chúng hiển thị. Tính năng kết xuất phía máy khách có thể mang lại hiệu quả, nhưng thường là không nếu không có các bước kiểm thử bổ sung và thực hiện các thao tác khác. Gần đây hơn, tính năng kết xuất động cũng là một lựa chọn đáng cân nhắc nếu kiến trúc của bạn phụ thuộc nhiều vào JavaScript phía máy khách.

Khi nghi ngờ, công cụ kiểm tra tính thân thiện với thiết bị di động là vô giá để kiểm tra nhằm đảm bảo rằng phương pháp mà bạn chọn có đáp ứng những điều bạn mong đợi. Thẻ này cho thấy bản xem trước trực quan về cách trình thu thập dữ liệu của Google nhìn thấy một trang bất kỳ, nội dung HTML đã chuyển đổi tuần tự được tìm thấy (sau khi thực thi JavaScript) và mọi lỗi xảy ra trong quá trình hiển thị.

Ảnh chụp màn hình giao diện người dùng Kiểm tra tính thân thiện với thiết bị di động.

Kết thúc

Khi quyết định phương pháp kết xuất hình ảnh, hãy đo lường và hiểu điểm tắc nghẽn của bạn. Hãy cân nhắc xem kết xuất tĩnh hoặc kết xuất phía máy chủ có thể giúp bạn đạt được mục tiêu đó hay không. Bạn hoàn toàn có thể gửi HTML có JavaScript tối thiểu để có được trải nghiệm có tính tương tác. Dưới đây là một bản đồ hoạ thông tin tiện lợi cho thấy nhiều kiểu máy chủ-ứng dụng:

Bản đồ hoạ thông tin cho thấy nhiều lựa chọn được mô tả trong bài viết này.

Ghi công

Cảm ơn mọi người đã gửi bài đánh giá và nguồn cảm hứng:

Jeffrey Posnick, Houssein Djirdeh, Shubhie Panicker, Chris Harrelson và Sebastian Markbāge