Bài viết được dịch từ https://blog.cloudflare.com

HTTP/2 sẽ thay đổi cách các web deverloper tối ưu hóa website của mình. Trong HTTP/1.1, cách phổ biến để tăng 5% tốc độ tải trang là giảm số kết nối TCP và các HTTP request với các kỹ thuật như spriting (gộp nhiều file ảnh vào một file ví dụ các ảnh icon), inlining (viết mã css, js,... trong file html), chia sẻ tên miền (domain sharding), và nối file (concatenation).

Cuộc sống trở lên dễ dàng hơn một chút trong HTTP/2. Nó giúp cho các website thông thường tăng 30% hiệu suất mà không cần một quá trình xây dựng và triển khai phức tạp. Trong bài viết này chúng ta sẽ thảo luận các cách mới (new best practice) để tối ưu hóa website trong HTTP/2.

Tối ưu hóa web trong HTTP/1.1

Hầu hết các kỹ thuật tối ưu hóa website trong HTTP/1.1 xoay quanh việc tối thiểu hóa số lượng các HTTP request tới server gốc. Một trình duyệt chỉ có thể mở một số lượng giới hạn các kết nối TCP đồng thời tới một máy chủ gốc, và tải các tài sản (asset) trên mỗi kết nối theo một quá trình tuần tự: một tài sản được đáp ứng trước khi cái tiếp theo có thể gửi. Điều này được gọi là head-of-line blocking.

Và kết qủa là các web developer nén nhiều tài sản nhất có thể vào một kết nối và tìm nhiều cách để các trình duyệt tránh head-of-line blocking. Trong HTTP/2, một vài cách như vậy có thể làm giảm tốc độ tải trang.

Tư duy tối ưu hóa web mới cho HTTP2

Tối ưu hóa cho HTTP/2 yêu cầu một tư duy khác. Thay vì lo lắng về việc giảm các HTTP request, các web developer nên tập trung vào việc điều chỉnh caching của trình duyệt. Quy tắc chung là các tài nguyên nhỏ, riêng rẽ vì chúng có thể cache độc lập và truyền song song.

Sự thay đổi này xảy ra nhờ các tính năng multiplexing và header compression của HTTP/2. Multiplexing cho phép nhiều request chia sẻ cùng một kết nối TCP, nhiều tài sản có thể tải song song mà không cần thành lập nhiều kết nối. Điều này loại bỏ vấn đề head-of-line blocking của HTTP/1.1. Header compression giảm dung lượng các HTTP request, so với mỗi request tương đương trong HTTP/1.1.

Hai tính năng khác của HTTP/2 cũng thay đổi cách tối ưu web là: stream prioritization và server push. Cho phép các trình duyệt chỉ định thứ tự các tài nguyên chúng muốn nhận và cho phép các máy chủ gửi thêm các tài nguyên mà trình duyệt chưa biết là nó cần chúng (chưa request). Để tận dụng tối đa những tính năng mới này, các web developer cần quên một vài cách tốt nhất (best practice) của HTTP/1.1, cái đã trở thành bản tính tự nhiên thứ 2 của họ.

Tham khảo các khóa học lập trình online, onlab, và thực tập lập trình tại TechMaster

Các cách tối ưu hóa tốt nhất cho HTTP/2

Dừng nối (concatenating) các file với nhau

Trong HTTP/1.1, các web developers thường kết hợp tất cả CSS của toàn bộ website vào một file duy nhất. Tương tự, với javascript, và các ảnh kết hợp vào một spritesheet. Với một file CSS, JavaScript và ảnh sẽ giảm số lượng các HTTP request, làm tăng hiệu suất cho HTTP/1.1

Tuy nhiên, nối file không còn là cách tốt nhất trong HTTP/2. Trong khi nối file vẫn cải thiện tỉ lệ nén, nó buộc phải đánh đổi với chi phí cache. Thậm chí nếu chỉ một dòng CSS thay đổi, trình duyệt buộc phải tải lại toàn bộ CSS.

Ngoài ra, không phải mọi trang trong website của bạn đều sử dụng tất cả các khai báo hoặc các hàm trong file CSS hoặc JavaScript đã được nối. Sau khi cache, đây không phải là vấn đề lớn, nhưng nó có nghĩa là những byte không cần thiết đã được truyền, xử lý và thực thi để render trang đầu tiên người dùng nghé thăm. Khi so sánh với một request trong HTTP/1.1 đây là một sự đánh đổi đáng giá, nhưng nó có thể làm chậm thời gian tải trang trong HTTP/2.

Thay vì việc nối file, các web develper nên tập trung nhiều hơn vào việc tối ưu hóa chính sách cache. Bằng cách tách các file thường xuyên thay đổi và các file hiếm khi thay đổi, có thể sử dụng CDN của bạn hoặc cache trình duyệt của người dùng cho các file ít thay đổi.

Dừng các tài sản (assets) inlining

Các tài sản inlining là một trường hợp đặc biệt của nối file. Đó là việc nhúng code CSS, JavaScript và hình ảnh trực tiếp trong file HTML. Ví dụ, nếu trang web của bạn trông như thế này:

<html>
  <head>
    <link rel="stylesheet" href="/style.css">
  </head>
  <body>
    <img src="logo.png">
    <script src="scripts.min.js"></script>
  </body>
</html>

Bạn có thể sử dụng một công cụ inlining và nhận được kết quả như sau:

<html>
  <head>
    <style>

      body {
        font-size: 18px;

        color: #999;
      }
    </style>
  </head>
  <body>
    <img src="data:image/png;base64,Rw0KGgoAAAANSUhEUgAAAEAABA...">
    <script>console.log('Hello, World!');</script>
  </body>
</html>

Cách này giảm số lượng các HTTP request thành một. Nhưng giống như nối file, bạn không nên làm như vậy trong HTTP/2.

Inlining có nghĩa là trình duyệt không thể cache các tài sản một cách riêng rẽ. Nếu các khai báo CSS được áp dụng cho toàn bộ website của bạn được nhúng vào mỗi file HTML, các khai báo này sẽ được gửi lại từ server mọi lúc. Kết quả là các byte dư thừa sẽ được gửi lại khi người dùng duyệt các trang.

Inlining cũng có ảnh hưởng tới stream prioritization. Bởi vì CSS, JavaScript và hình ảnh được nhúng trong file HTML, thứ tự ưu tiên của chúng cùng mức với nội dung HTML. Điều này có nghĩa là trình duyệt không thể yêu cầu các tài sản theo thứ tự mong muốn, và có khả năng làm chậm thời gian tải trang.

Thay vì inlining các tài sản, các web developer lên tận dụng chức năng server push của HTTP/2. Server push cho phép web server của bạn nói một số thứ giống như: "Giữ lấy, hình ảnh và file CSS này để render trang HTML bạn vừa yêu cầu". Điều này tương tự inlining một tài sản, nhưng nó không làm hỏng stream prioritizatioon, và nó cho phép tận dụng một CDN và cache trình duyệt của người dùng.

Dừng chia sẻ các tên miền (domain)

Chia sẻ tên miền là một kỹ thuật phổ biến để các trình duyệt có thể mở nhiều kết nối TCP hơn số lượng chúng hỗ trợ. Các trình duyệt giới hạn số lượng kết nối tới một máy chủ gốc, nhưng chia các tài sản website của bạn trên nhiều tên miền, có thể mở rộng tập hợp các kết nối TCP. Điều này tránh được head-of-line blocking, nhưng nó đi kèm với việc phải đánh đổi.

Nên tránh chia sẻ tên miền trong HTTP/2. Kết quả của mỗi chia sẻ là một truy vấn DNS, kết nối TCP và TLS handshake không cần thiết (giả định các máy chủ sử dụng các chứng chỉ TLS khác nhau). Với cách này, trong HTTP/1.1 bạn có thể download các tài sản song song. Nhưng, với HTTP/2: multiplexing cho phép các tài sản tải song song thông qua một kết nối. Và giống như inlining, chia sẻ tên miền phá vỡ HTTP/2 stream prioritization bởi vì các trình duyệt không thể ưu tiên truyền trên nhiều máy chủ.

Nếu bạn đang sử dụng chia sẻ tên miền và muốn tận dụng lợi thế của HTTP/2, bạn không cần phải refactoring toàn bộ cosebase của mình. Trong bài viết trộn chia sẻ tên miền và SPDY, các trình duyệt nhận ra khi nhiều máy chủ gốc sử dụng cùng chứng chỉ TLS. Trình duyệt sẽ tái sử dụng cùng kết nối SPDY hoặc HTTP/2 cho tất cả máy chủ. Điều này vẫn có kết quả là các truy vấn tới nhiều DNS, nhưng nó là giải pháp nếu bạn muốn có hiệu suất tốt nhất cho cả HTTP/1.1 và HTTP/2.

Một vài cách (best practice) vẫn sẽ được sử dụng

May mắn là không phải mọi cách tối ưu web đều thay đổi trong HTTP/2. Vẫn có nhiều cách trong HTTP/1.1 có thể sử dụng với HTTP/2. Phần còn lại của bài viết này sẽ thảo luận về các cách đó.

Giảm các tra cứu DNS

Trước khi một trình duyệt có thể yêu cầu các tài nguyên trên website của bạn, nó cần tìm địa chỉ IP máy chủ của bạn thông qua hệ thống tên miền (DNS). Cho đến khi DNS đáp trả, người sử dụng sẽ có một màn hình trắng. HTTP/2 được thiết kế để tối ưu hóa cách các trình duyệt web kết nối với các máy chủ. Nó không ảnh hưởng tới hiệu suất của hệ thống tên miền.

Khi các truy vấn DNS trở lên tốn kém, đặc biệt nếu bạn bắt đầu truy vấn tại tên máy chủ gốc, cần thận trọng để giảm thiểu số lượng các tra cứu DNS cái website của bạn sử dụng. DNS có thể nạp trước thông qua <link rel='dns-prefetch' href='...' /> trong thẻ <head>  của file HTML, nhưng nó không phải là một giải pháp cho tất cả các trường hợp.

Sử dụng một mạng phân phối nội dung (CDN)

Mất 130ms để ánh sáng đi một vòng quanh trái đất. Đó là độ trễ không thể tránh khỏi - nó chỉ là vật lý. Bản chất không hoàn hảo của các kết nối cáp quang và không dây, cũng như cấu trúc liên kết của mạng Internet toàn cầu làm nó mất gần 300-400ms để truyền một gói tin từ máy tính của bạn tới một máy chủ cách đó nửa vòng trái đất. Độ trễ mà người dùng có thể cảm nhận là 100ms, và bạn có thể đặt các tài sản website của bạn trên các máy chủ ở gần khu vực địa lý của mình thông qua các CDN.

Tận dụng cache của trình duyệt

Bạn có thể tận dụng các mạng phân phối nội dung thêm một bước nữa bằng cách caching các tài sản trong cache của trình duyệt. Điều này tránh mọi loại truyền dữ liệu thông qua mạng, bên cạnh đáp trả 304 Not Modified.

Giảm thiểu tối đa kích thước các HTTP request

Mặc dù các HTTP/2 request đã được ghép (multiplexed), nó vẫn cần thời gian để truyền qua cáp. Vì thế, vẫn có lợi khi giảm lượng dữ liệu bạn cần truyền. Điều này có nghĩa là giảm thiểu thước cookie, URL, chuỗi truy vấn và các tham chiếu URL nhiều nhất có thể.

Giảm thiểu tối đa kích thước các HTTP response

Tất nhiên, điều này đúng theo hướng ngược lại so với phần trên. Là một web deverloper, bạn muốn tạo ra các đáp trả từ máy chủ với kích thước nhỏ nhất có thể bằng cách minifying HTML, CSS, và các file JavaScript, tối ưu hóa hình ảnh, và nén các tài nguyên với gzip.

Loại bỏ các điều hướng không cần thiết

Các điều hướng 301 và 302 xảy ra khi bạn chuyển sang một nền tảng mới hoặc thiết kế lại website của mình, chúng nên được loại bỏ bất cứ khi nào có thể. Các điều hướng này tạo ra độ trễ không cần thiết. Bạn cần đặc biệt cẩn thận với các chuỗi điều hướng có hơn một lần chuyển hướng để tới được URL đích.

Các đáp trả điều hướng giống như 301 và 302 không phải là một ý tưởng hay, nhưng chúng không phải là điều tệ nhất. Chúng có thể được cache tại client, vì thế trình duyệt có thể nhận ra các URL là các điều hướng và tránh việc chuyển hướng lòng vòng không cần thiết. Thẻ Meta refreshes  (Ví dụ: <meta http-equiv="refresh"...) là một trường hợp khác, nó có chi phí đắt hơn bởi vì không thể cache, và có thể ảnh hưởng tới hiệu suất trong một số trình duyệt.

 Kết luận

Tóm lại tối ưu web trong HTTP/2 gồm: tránh nối file, các tài sản inlining, và chia sẻ tên miền. Điều này không chỉ tăng tốc website của bạn, mà cũng làm cho quá trình xây dựng và triển khai đơn giản hơn.

Tuy nhiên, bạn cần phải chú ý. Hầu hết các máy chủ, mạng chia sẻ nội dung (bao gồm CloudFlare), và các ứng dụng đã tồn tại chưa hỗ trợ server push. Các máy chủ và mạng chia sẻ nội dung sẽ sớm bắt kịp, nhưng để tận dụng lợi ích từ server push, bạn cần làm một vài thay đổi trong codebase của mình.

Cũng cần biết rằng hiệu năng của HTTP/2 phụ thuộc vào kiểu nội dung bạn phục vụ. Ví dụ, các website dựa trên nhiều tài sản bên ngoài sẽ cho thấy sự tăng hiệu suất lớn trong HTTP/2 so với các website chỉ có một vài request.