Tối ưu hoá việc mã hoá và kích thước chuyển của thành phần dựa trên văn bản

Bên cạnh việc loại bỏ các lượt tải tài nguyên không cần thiết, điều tốt nhất bạn có thể làm để cải thiện tốc độ tải trang là giảm thiểu kích thước tải xuống tổng thể bằng cách tối ưu hoá và nén các tài nguyên còn lại.

Kiến thức cơ bản về nén dữ liệu

Sau khi bạn thiết lập trang web để tránh tải xuống mọi tài nguyên không dùng đến, bước tiếp theo là nén mọi tài nguyên đủ điều kiện còn lại mà trình duyệt phải tải xuống. Tuỳ thuộc vào loại tài nguyên (văn bản, hình ảnh, phông chữ, v.v.), bạn có thể lựa chọn nhiều kỹ thuật khác nhau: công cụ chung có thể bật trên máy chủ web, tối ưu hoá xử lý trước cho các loại nội dung cụ thể và tối ưu hoá dành riêng cho tài nguyên yêu cầu dữ liệu đầu vào của nhà phát triển.

Để mang lại hiệu suất tốt nhất, bạn cần kết hợp tất cả các kỹ thuật sau:

  • Nén là quá trình mã hoá thông tin bằng cách sử dụng ít bit hơn.
  • Việc loại bỏ dữ liệu không cần thiết luôn mang lại kết quả tốt nhất.
  • Có nhiều kỹ thuật và thuật toán nén khác nhau.
  • Bạn sẽ cần nhiều kỹ thuật để đạt được độ nén tốt nhất.

Quá trình giảm kích thước dữ liệu là quá trình nén dữ liệu. Nhiều người đã đóng góp các thuật toán, kỹ thuật và tối ưu hoá để cải thiện tỷ lệ nén, tốc độ nén và bộ nhớ mà các thuật toán nén khác nhau yêu cầu.

Một cuộc thảo luận đầy đủ về nén dữ liệu nằm ngoài phạm vi của hướng dẫn này. Tuy nhiên, bạn cần hiểu rõ cách hoạt động của quá trình nén và các kỹ thuật mà bạn có thể sử dụng để giảm kích thước của nhiều thành phần mà trang của bạn yêu cầu.

Để minh hoạ các nguyên tắc cốt lõi của các kỹ thuật này, hãy xem xét quy trình tối ưu hoá một định dạng tin nhắn văn bản đơn giản được tạo ra chỉ cho ví dụ này:

# Below is a secret message, which consists of a set of headers in
# key-value format followed by a newline and the encrypted message.
format: secret-cipher
date: 08/25/16
AAAZZBBBBEEEMMM EEETTTAAA
  1. Tin nhắn có thể chứa các chú giải tuỳ ý (đôi khi được gọi là nhận xét) được biểu thị bằng tiền tố "#". Các chú thích không ảnh hưởng đến ý nghĩa hoặc hành vi của thông báo.
  2. Thông báo có thể chứa tiêu đề, là các cặp khoá-giá trị (được phân tách bằng ":" trong ví dụ trước) xuất hiện ở đầu thông báo.
  3. Thông báo mang tải trọng văn bản.

Bạn có thể làm gì để giảm kích thước của thông báo trước đó, bắt đầu từ 200 ký tự?

  1. Nhận xét này rất thú vị nhưng không ảnh hưởng đến ý nghĩa của tin nhắn. Loại bỏ thông tin này khi truyền tin nhắn.
  2. Có những kỹ thuật tốt để mã hoá tiêu đề một cách hiệu quả. Ví dụ: nếu biết rằng tất cả thông báo đều có "định dạng" và "ngày", bạn có thể chuyển đổi các thông báo đó thành mã nhận dạng số nguyên ngắn và chỉ gửi các thông báo đó. Tuy nhiên, điều đó có thể không đúng, vì vậy, tốt nhất bạn nên để nguyên trạng thái hiện tại.
  3. Trọng tải chỉ là văn bản. Mặc dù chúng ta không biết nội dung thực sự của tệp này là gì (rõ ràng là tệp này đang sử dụng "secret-cipher"), nhưng chỉ cần nhìn vào văn bản là bạn có thể thấy có rất nhiều nội dung thừa trong đó. Có lẽ thay vì gửi các chữ cái lặp lại, bạn có thể chỉ cần đếm số lượng chữ cái lặp lại và mã hoá chúng hiệu quả hơn. Ví dụ: "AAA" trở thành "3A", biểu thị một chuỗi gồm 3 chữ A.

Kết hợp các kỹ thuật này tạo ra kết quả sau:

format: secret-cipher
date: 08/25/16
3A2Z4B3E3M 3E3T3A

Thông báo mới có độ dài 56 ký tự, tức là bạn đã nén thông báo ban đầu xuống 72%. Đó là một mức giảm đáng kể!

Đây là ví dụ đơn giản về cách các thuật toán nén có thể hiệu quả trong việc giảm kích thước chuyển của tài nguyên dựa trên văn bản. Trong thực tế, các thuật toán nén phức tạp hơn nhiều so với ví dụ trước và trên web, các thuật toán nén có thể được dùng để giảm đáng kể thời gian tải xuống cho các tài nguyên. Bằng cách áp dụng tính năng nén cho các thành phần văn bản, một trang web có thể mất ít thời gian tải tài nguyên hơn để người dùng có thể thấy được tác động của các tài nguyên đó sớm hơn so với khi không nén.

Giảm thiểu: xử lý trước và tối ưu hoá theo ngữ cảnh

Kỹ thuật đầu tiên được thảo luận ở đây là rút gọn. Mặc dù rút gọn không hoàn toàn là một thuật toán nén, nhưng đây là một cách xoá các ký tự không cần thiết và thừa được dùng trong mã nguồn để giúp con người dễ đọc tài nguyên hơn. Tuy nhiên, khả năng đọc đó không cần thiết để duy trì chức năng của mã nguồn đó trên các trang web chính thức và có thể trì hoãn việc tải tài nguyên trên web.

Giảm thiểu là một kiểu tối ưu hoá dành riêng cho nội dung có thể giúp giảm đáng kể dung lượng tài nguyên được phân phối. Đây cũng là một cách tối ưu hoá nên áp dụng trong quá trình xây dựng và triển khai. Ví dụ: trình tạo gói là một loại phần mềm thường dùng có thể tự động rút gọn tài nguyên ngay trước khi triển khai mã phát hành chính thức mới cho một trang web.

Cách tốt nhất để nén dữ liệu thừa hoặc không cần thiết là loại bỏ dữ liệu đó. Tuy nhiên, bạn không thể chỉ xoá dữ liệu tuỳ ý. Tuy nhiên, trong một số ngữ cảnh mà chúng tôi có kiến thức cụ thể về định dạng dữ liệu và các thuộc tính của nội dung đó, có thể giảm đáng kể kích thước của tải trọng mà không ảnh hưởng đến ý nghĩa hoặc khả năng thực tế của tải trọng đó.

<html>
  <head>
    <style>
      /* awesome-container is only used on the landing page */
      .awesome-container {
        font-size: 120%;
      }

      .awesome-container {
        width: 50%;
      }
    </style>
  </head>
  <body>
    <!-- awesome container content: START -->
    <div>
      This is my awesome container, and it is <em>so</em> awesome.
    </div>
    <!-- awesome container content: END -->
    <script>
      awesomeAnalytics(); // Beacon conversion metrics
    </script>
  </body>
</html>

Hãy xem xét đoạn mã HTML trước đó và 3 loại nội dung có trong đoạn mã đó:

  1. Mã đánh dấu HTML.
  2. CSS để tuỳ chỉnh cách trình bày của trang.
  3. JavaScript để hỗ trợ các hoạt động tương tác và các tính năng nâng cao khác của trang.

Mỗi loại nội dung trong số này có các quy tắc khác nhau về nội dung hợp lệ, các quy tắc khác nhau về việc chỉ định nhận xét, v.v. Tuy nhiên, câu hỏi còn lại là "làm cách nào để giảm kích thước của trang này?"

  • Chú thích mã là người bạn tốt nhất của nhà phát triển, nhưng trình duyệt không cần đến chú thích! Việc loại bỏ các nhận xét CSS (/* ... */), HTML (<!-- ... -->) và JavaScript (// ...) sẽ làm giảm tổng kích thước truyền của trang và các tài nguyên phụ của trang đó.
  • Trình nén CSS "thông minh" có thể nhận thấy rằng chúng ta đang sử dụng cách xác định quy tắc cho .awesome-container không hiệu quả và thu gọn hai nội dung khai báo thành một mà không ảnh hưởng đến bất kỳ kiểu nào khác, giúp tiết kiệm nhiều byte hơn. Trong một tập hợp lớn các quy tắc CSS, việc xoá loại nội dung thừa này có thể tích luỹ thêm — nhưng có thể không phải là điều có thể áp dụng một cách mạnh mẽ, vì các bộ chọn thường cần được sao chép trong các ngữ cảnh khác nhau, chẳng hạn như trong truy vấn nội dung nghe nhìn.
  • Dấu cách và thẻ là những tiện ích dành cho nhà phát triển trong HTML, CSS và JavaScript. Một trình nén bổ sung có thể loại bỏ tất cả các thẻ và dấu cách. Không giống như các kỹ thuật loại bỏ trùng lặp khác, bạn có thể áp dụng loại hình tối ưu hoá này một cách khá mạnh mẽ, miễn là các dấu cách hoặc thẻ đó không cần thiết cho việc trình bày trang. Ví dụ: bạn nên giữ lại các dấu cách trong các dòng văn bản trong tài liệu HTML, vì các dấu cách này đảm bảo khả năng đọc của nội dung mà người dùng sẽ thực sự thấy.
<html><head><style>.awesome-container{font-size:120%;width:50%}</style></head><body><div>This is my awesome container, and it is <em>so</em> awesome.</div><script>awesomeAnalytics()</script></body></html>

Sau khi áp dụng các bước trước đó, trang sẽ tăng từ 516 xuống còn 204 ký tự, thể hiện mức tiết kiệm khoảng 60%. Tuy không dễ đọc nhưng bạn không cần phải đọc được mã này thì mới có thể sử dụng. Các phương pháp phát triển hiện đại cũng cho phép bạn tách biệt các phiên bản mã nguồn được định dạng và dễ đọc với mã được tối ưu hoá mà bạn gửi đến môi trường phát hành công khai. Khi kết hợp với bản đồ nguồn (cung cấp bản trình bày dễ đọc về mã sản xuất đã chuyển đổi, giúp bạn dễ dàng khắc phục sự cố trong quá trình sản xuất), bạn có thể vừa có trải nghiệm tốt cho nhà phát triển vừa tối ưu hoá hiệu suất để mang lại trải nghiệm tốt cho người dùng.

Ví dụ trước minh hoạ một điểm quan trọng: trình nén đa năng (ví dụ: trình nén được thiết kế để nén văn bản tuỳ ý) có thể nén trang khá tốt trong ví dụ trước, nhưng sẽ không bao giờ biết xoá các nhận xét, thu gọn các quy tắc CSS hoặc hàng chục hoạt động tối ưu hoá khác dành riêng cho nội dung. Đó là lý do tại sao việc xử lý trước, rút gọn và các hoạt động tối ưu hoá khác có tính đến ngữ cảnh là quan trọng.

Tương tự, các kỹ thuật được mô tả ở trên có thể được mở rộng không chỉ cho các thành phần dựa trên văn bản. Hình ảnh, video và các loại nội dung khác đều chứa các dạng siêu dữ liệu riêng và nhiều tải trọng khác nhau. Ví dụ: mỗi khi bạn chụp ảnh bằng máy ảnh, tệp của ảnh đó thường nhúng nhiều thông tin bổ sung: chế độ cài đặt máy ảnh, vị trí, v.v. Tuỳ thuộc vào ứng dụng của bạn, dữ liệu này có thể rất quan trọng (ví dụ: trang web chia sẻ ảnh) hoặc hoàn toàn vô dụng. Bạn nên cân nhắc xem có nên xoá hay không. Trong thực tế, siêu dữ liệu này có thể thêm tối đa vài chục kilobyte cho mỗi hình ảnh.

Tóm lại, bước đầu tiên để tối ưu hoá hiệu quả của các thành phần là tạo khoảng không quảng cáo cho nhiều loại nội dung và cân nhắc những loại hình tối ưu hoá dành riêng cho nội dung mà bạn có thể áp dụng để giảm kích thước của các thành phần đó. Sau đó, sau khi bạn đã tìm hiểu được những tính năng này, hãy tự động hoá các tính năng tối ưu hoá này bằng cách thêm các tính năng đó vào các bước tạo bản dựng và phát hành để đảm bảo rằng các tính năng tối ưu hoá được áp dụng nhất quán cho mọi bản phát hành mới cho bản phát hành chính thức.

Nén văn bản bằng thuật toán nén

Bước tiếp theo để giảm kích thước của thành phần dạng văn bản là áp dụng thuật toán nén cho các thành phần đó. Tính năng này tiến thêm một bước bằng cách tìm kiếm tích cực các mẫu lặp lại trong tải trọng dựa trên văn bản trước khi gửi các mẫu đó đến người dùng và giải nén các mẫu đó sau khi chúng đến trình duyệt của người dùng. Kết quả là giảm đáng kể các tài nguyên đó và thời gian tải xuống nhanh hơn sau đó.

  • gzip và Brotli là các thuật toán nén thường dùng, hoạt động hiệu quả nhất trên các thành phần dựa trên văn bản: CSS, JavaScript, HTML.
  • Tất cả trình duyệt hiện đại đều hỗ trợ tính năng nén gzip và Brotli, đồng thời sẽ quảng cáo tính năng hỗ trợ cả hai trong tiêu đề yêu cầu HTTP Accept-Encoding.
  • Bạn phải định cấu hình máy chủ để bật tính năng nén. Theo mặc định, phần mềm máy chủ web thường sẽ cho phép các mô-đun nén tài nguyên dựa trên văn bản.
  • Bạn có thể điều chỉnh cả gzip và Brotli để cải thiện tỷ lệ nén bằng cách điều chỉnh mức độ nén. Đối với gzip, chế độ cài đặt nén có phạm vi từ 1 đến 9, trong đó 9 là chế độ tốt nhất. Đối với Brotli, phạm vi này là từ 0 đến 11, trong đó 11 là tốt nhất. Tuy nhiên, chế độ cài đặt nén cao hơn sẽ cần nhiều thời gian hơn. Đối với các tài nguyên được nén động (tức là tại thời điểm yêu cầu) thì chế độ cài đặt ở giữa phạm vi có xu hướng đưa ra sự đánh đổi tốt nhất giữa tỷ lệ nén và tốc độ. Tuy nhiên, bạn có thể nén tĩnh, đó là khi phản hồi được nén trước thời hạn và do đó, có thể sử dụng các chế độ cài đặt nén linh hoạt nhất hiện có cho mỗi thuật toán nén.
  • Mạng phân phối nội dung (CDN) thường cung cấp tính năng nén tự động các tài nguyên đủ điều kiện. CDN cũng có thể quản lý việc nén động và tĩnh cho bạn, giúp bạn giảm bớt một khía cạnh nén cần phải lo lắng.

gzipBrotli là các trình nén phổ biến có thể áp dụng cho bất kỳ luồng số byte nào. Về cơ bản, các trình này ghi nhớ một số nội dung đã kiểm tra trước đó của một tệp, sau đó tìm và thay thế các mảnh dữ liệu trùng lặp một cách hiệu quả.

Trong thực tế, cả gzip và Brotli đều hoạt động hiệu quả nhất trên nội dung dựa trên văn bản, thường đạt tỷ lệ nén lên tới 70-90% đối với các tệp lớn hơn. Tuy nhiên, việc chạy các thành phần thuật toán này đã được nén bằng các thuật toán thay thế (chẳng hạn như hầu hết các định dạng hình ảnh sử dụng kỹ thuật nén không tổn hao hoặc có tổn hao) sẽ mang lại hiệu quả cải thiện rất ít hoặc không cải thiện gì.

Mọi trình duyệt hiện đại đều quảng cáo hỗ trợ gzip và Brotli trong tiêu đề của yêu cầu HTTP Accept-Encoding. Tuy nhiên, nhà cung cấp dịch vụ lưu trữ có trách nhiệm đảm bảo rằng máy chủ web được định cấu hình đúng cách để phân phát tài nguyên nén khi ứng dụng yêu cầu.

Tệp Thuật toán Kích thước không nén Kích thước nén Tỷ số nén
angular-1.8.3.js Brotli 1.346 KiB 256 KiB 81%
angular-1.8.3.js gzip 1.346 KiB 329 KiB 76%
angular-1.8.3.min.js Brotli 173 KiB 53 KiB 69%
angular-1.8.3.min.js gzip 173 KiB 60 KiB 65%
jquery-3.7.1.js Brotli 302 KiB 69 KiB 77%
jquery-3.7.1.js gzip 302 KiB 83 KiB 73%
jquery-3.7.1.min.js Brotli 85 KiB 27 KiB 68%
jquery-3.7.1.min.js gzip 85 KiB 30 KiB 65%
lodash-4.17.21.js Brotli 531 KiB 73 KiB Tăng 86%
lodash-4.17.21.js gzip 531 KiB 94 KiB Tăng 82%
lodash-4.17.21.min.js Brotli 71 KiB 23 KiB 68%
lodash-4.17.21.min.js gzip 71 KiB 25 KiB 65%

Bảng trước cho thấy mức tiết kiệm mà cả phương thức nén Brotli và gzip có thể cung cấp cho một số thư viện JavaScript nổi tiếng. Mức tiết kiệm dao động từ 65% đến 86% tuỳ thuộc vào tệp và thuật toán. Để tham khảo, mức độ nén tối đa được áp dụng cho từng tệp cho cả Brotli và gzip. Bất cứ khi nào có thể, hãy ưu tiên dùng Brotli thay vì gzip.

Bật tính năng nén là một trong những cách đơn giản và hiệu quả nhất để triển khai tính năng tối ưu hoá. Nếu trang web của bạn không tận dụng được tính năng này, bạn đang bỏ lỡ một cơ hội lớn để cải thiện hiệu suất cho người dùng. May mắn thay, nhiều máy chủ web cung cấp cấu hình mặc định cho phép tối ưu hoá quan trọng này, đặc biệt là CDN rất hiệu quả trong việc triển khai cấu hình này theo cách cân bằng tốc độ và tỷ lệ nén.

Một cách nhanh chóng để xem quá trình nén là mở Công cụ của Chrome cho nhà phát triển, mở bảng điều khiển Mạng, tải một trang mà bạn chọn và quan sát phần dưới cùng của bảng điều khiển mạng.

Thông tin đọc của DevTools về kích thước thực tế so với kích thước chuyển.
Biểu thị kích thước chuyển (tức là được nén) của tất cả tài nguyên trang so với kích thước thực tế của các tài nguyên đó như minh hoạ trong bảng điều khiển mạng của Công cụ của Chrome cho nhà phát triển.

Giống như hình ảnh trước, bạn sẽ thấy bảng chi tiết về:

  • Số yêu cầu, là số lượng tài nguyên được tải cho trang.
  • Kích thước chuyển của tất cả các yêu cầu. Chỉ số này phản ánh mức độ hiệu quả của quá trình nén áp dụng cho bất kỳ tài nguyên nào của trang.
  • Kích thước tài nguyên của tất cả các yêu cầu. Chỉ số này cho biết kích thước của tài nguyên cho trang sau khi giải nén.

Ảnh hưởng đến Các chỉ số quan trọng về trang web

Các mức cải thiện về hiệu suất sẽ không được đo lường trừ phi có các chỉ số phản ánh những điểm cải thiện đó. Sáng kiến Chỉ số quan trọng chính của trang web là để tạo và nâng cao mức độ nhận biết về các chỉ số phản ánh trải nghiệm thực tế của người dùng. Điều này trái ngược với các chỉ số (chẳng hạn như thời gian tải trang đơn giản) không thể hiện rõ chất lượng trải nghiệm người dùng.

Khi bạn áp dụng các biện pháp tối ưu hoá được nêu trong hướng dẫn này cho các tài nguyên trên trang web, mức độ ảnh hưởng đến Chỉ số quan trọng chính của trang web có thể khác nhau, tuỳ thuộc vào tài nguyên được tối ưu hoá và (các) chỉ số liên quan. Tuy nhiên, sau đây là một số trường hợp mà việc áp dụng các biện pháp tối ưu hoá này có thể cải thiện Chỉ số quan trọng chính của trang web:

  • Các tài nguyên HTML được rút gọn và nén có thể cải thiện quá trình tải HTML đó, khả năng khám phá các tài nguyên phụ của HTML đó, do đó cải thiện quá trình tải các tài nguyên đó. Điều này có thể có lợi cho Thời gian hiển thị nội dung lớn nhất (LCP) của trang. Mặc dù bạn có thể sử dụng các gợi ý tài nguyên như rel="preload" để ảnh hưởng đến khả năng khám phá tài nguyên, nhưng việc sử dụng quá nhiều gợi ý có thể gây ra sự cố về tranh chấp băng thông. Bằng cách đảm bảo phản hồi HTML cho một yêu cầu điều hướng được nén, các tài nguyên trong đó có thể được trình quét tải trước khám phá sớm nhất có thể.
  • Một số ứng viên LCP cũng có thể được tải sớm hơn bằng cách sử dụng tính năng nén. Ví dụ: hình ảnh SVG là các đề xuất LCP có thể giảm thời lượng tải tài nguyên thông qua tính năng nén dựa trên văn bản. Điều này khác với việc tối ưu hoá mà bạn thực hiện cho các loại hình ảnh khác – vốn được nén thông qua các phương thức nén khác – chẳng hạn như cách hình ảnh JPEG sử dụng phương thức nén có tổn hao.
  • Ngoài ra, nút văn bản cũng có thể là đề xuất LCP. Cách các kỹ thuật được mô tả trong hướng dẫn này phụ thuộc vào việc bạn có đang sử dụng phông chữ web cho văn bản trên trang web của mình hay không. Nếu bạn đang sử dụng phông chữ web, thì các phương pháp hay nhất để tối ưu hoá phông chữ web sẽ được áp dụng. Tuy nhiên, nếu bạn không sử dụng phông chữ web mà thay vào đó là phông chữ hệ thống hiển thị mà không gây ra bất kỳ thời lượng tải tài nguyên nào, thì việc rút gọn và nén CSS sẽ làm giảm thời lượng này, nghĩa là quá trình kết xuất các nút văn bản LCP tiềm năng có thể diễn ra sớm hơn.

Kết luận

Cách bạn tối ưu hoá quá trình mã hoá và chuyển tài sản dựa trên văn bản là một khái niệm hiệu suất cơ sở, nhưng đây là một khái niệm có tác động lớn. Hãy đảm bảo rằng bạn đang làm mọi thứ có thể để đảm bảo rằng các tài nguyên đủ điều kiện để rút gọn và nén sẽ được hưởng lợi từ những hoạt động tối ưu hoá đó.

Quan trọng hơn, hãy đảm bảo rằng các quy trình này đang được tự động hoá. Để rút gọn, hãy sử dụng trình đóng gói để áp dụng tính năng rút gọn cho các tài nguyên đủ điều kiện. Đảm bảo rằng cấu hình máy chủ web của bạn hỗ trợ tính năng nén, nhưng hơn thế nữa, hãy sử dụng tính năng nén hiệu quả nhất hiện có. Để việc này trở nên đơn giản nhất có thể, hãy sử dụng CDN để tự động nén cho bạn, vì CDN không chỉ có thể nén tài nguyên cho bạn mà còn có thể nén rất nhanh.

Bằng cách củng cố các khái niệm hiệu suất cơ sở này vào cấu trúc của trang web, bạn có thể đảm bảo rằng các nỗ lực tối ưu hoá hiệu suất của mình đang đi đúng hướng và các hoạt động tối ưu hoá tiếp theo có thể dựa trên nền tảng vững chắc của các phương pháp cơ sở hiệu quả.