Gói Next.js để quản lý thư viện của bên thứ ba

Năm 2021, nhóm Chrome Aurora đã ra mắt thành phần Tập lệnh để cải thiện hiệu suất tải của các tập lệnh bên thứ ba trong Next.js. Kể từ khi ra mắt, chúng tôi đã mở rộng các tính năng để giúp nhà phát triển tải tài nguyên của bên thứ ba một cách dễ dàng và nhanh chóng hơn.

Bài đăng trên blog này cung cấp thông tin tổng quan về các tính năng mới mà chúng tôi đã phát hành, đáng chú ý nhất là thư viện @next/third-party, cũng như phác thảo các sáng kiến trong tương lai trong lộ trình của chúng tôi.

Ý nghĩa về hiệu suất của tập lệnh của bên thứ ba

41% trong số tất cả các yêu cầu của bên thứ ba trong trang web Next.js là tập lệnh. Không giống như các loại nội dung khác, tập lệnh có thể mất một khoảng thời gian đáng kể để tải xuống và thực thi, điều này có thể chặn quá trình kết xuất và trì hoãn hoạt động tương tác của người dùng. Dữ liệu từ Báo cáo trải nghiệm người dùng trên Chrome (CrUX) cho thấy những trang web Next.js tải nhiều tập lệnh của bên thứ ba hơn có tỷ lệ chuyển Lượt tương tác với Nội dung hiển thị tiếp theo (INP)Thời gian hiển thị nội dung lớn nhất (LCP) sẽ thấp hơn.

Biểu đồ thanh cho thấy sự sụt giảm tỷ lệ phần trăm Next.js đạt được điểm INP và LCP tốt tương ứng với số lượng bên thứ ba được tải
Báo cáo CrUX vào tháng 12 năm 2023 (110.823 trang web)

Mối tương quan được ghi nhận trong biểu đồ này không ngụ ý quan hệ nhân quả. Tuy nhiên, các thử nghiệm địa phương cung cấp thêm bằng chứng cho thấy tập lệnh của bên thứ ba có tác động đáng kể đến hiệu suất của trang. Ví dụ: biểu đồ bên dưới so sánh các chỉ số của các phòng thí nghiệm khác nhau khi một vùng chứa Trình quản lý thẻ của Google (bao gồm 18 thẻ được chọn ngẫu nhiên) được thêm vào Taxonomy (một ứng dụng mẫu Next.js phổ biến).

Biểu đồ thanh cho thấy sự khác biệt về các chỉ số phòng thí nghiệm khác nhau khi một trang web được tải có và không có Trình quản lý thẻ của Google
WebPageTest (4G dành cho thiết bị di động – Virginia Hoa Kỳ)

Tài liệu về WebPageTest cung cấp thông tin chi tiết về cách đo lường các dấu thời gian này. Nhìn nhanh thì có thể thấy rằng tất cả các chỉ số phòng thí nghiệm này đều chịu ảnh hưởng của vùng chứa GTM. Ví dụ: Tổng thời gian chặn (TBT) – một proxy trong phòng thí nghiệm hữu ích ước chừng INP – đã tăng gần 20 lần.

Thành phần tập lệnh

Khi vận chuyển thành phần <Script> trong Next.js, chúng tôi đảm bảo sẽ giới thiệu thành phần này thông qua một API thân thiện với người dùng, gần giống với phần tử <script> truyền thống. Bằng cách sử dụng tập lệnh này, các nhà phát triển có thể cùng xác định một tập lệnh của bên thứ ba trong bất kỳ thành phần nào trong ứng dụng của họ, và Next.js sẽ đảm nhận việc sắp xếp theo trình tự tập lệnh sau khi các tài nguyên quan trọng được tải.

<!-- By default, script will load after page becomes interactive -->
<Script src="https://example.com/sample.js" />

<!-- Script is injected server-side and fetched before any page hydration occurs -->
<Script strategy=”beforeInteractive” src="https://example.com/sample.js" />

<!-- Script is fetched later during browser idle time -->
<Script strategy=”lazyOnload” src="https://example.com/sample.js" />

Hàng chục nghìn ứng dụng Next.js (bao gồm cả các trang web phổ biến như Patreon, TargetNotion) sử dụng thành phần <Script>. Mặc dù hiệu quả, một số nhà phát triển vẫn lo ngại về những điều sau:

  • Vị trí đặt thành phần <Script> trong ứng dụng Next.js mà vẫn tuân thủ các hướng dẫn cài đặt khác nhau của nhiều nhà cung cấp bên thứ ba (trải nghiệm của nhà phát triển).
  • Chiến lược tải nào là chiến lược tối ưu nhất để sử dụng cho các tập lệnh khác nhau của bên thứ ba (trải nghiệm người dùng).

Để giải quyết cả hai mối lo ngại này, chúng tôi đã ra mắt @next/third-parties – một thư viện chuyên biệt cung cấp một tập hợp các thành phần và tiện ích được tối ưu hoá dành riêng cho các bên thứ ba phổ biến.

Trải nghiệm của nhà phát triển: giúp việc quản lý thư viện của bên thứ ba trở nên dễ dàng hơn

Nhiều tập lệnh của bên thứ ba được sử dụng trong một tỷ lệ đáng kể các trang web Next.js, trong đó Trình quản lý thẻ của Google là loại tập lệnh phổ biến nhất, được 66% số trang web tương ứng sử dụng. @next/third-parties được xây dựng dựa trên thành phần <Script> bằng cách giới thiệu các trình bao bọc cấp cao hơn được thiết kế để đơn giản hoá việc sử dụng cho các trường hợp sử dụng phổ biến này.

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleTagManager gtmId="GTM-XYZ" />
    </html>
  );
}

Google Analytics — một tập lệnh được sử dụng rộng rãi của bên thứ ba (52% trang web Next.js) – cũng có một thành phần riêng.

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleAnalytics gaId="G-XYZ" />
    </html>
  );
}

@next/third-parties đơn giản hoá quá trình tải các tập lệnh thường dùng, nhưng cũng mở rộng khả năng phát triển tiện ích cho các danh mục khác của bên thứ ba, chẳng hạn như các tệp đã nhúng. Ví dụ: video nhúng của Google Maps và YouTube lần lượt được dùng ở 8%4% trên các trang web Next.js. Chúng tôi cũng đã chuyển các thành phần để giúp bạn dễ tải hơn.

import { GoogleMapsEmbed } from "@next/third-parties/google";
import { YouTubeEmbed } from "@next/third-parties/google";

export default function Page() {
  return (
    <>
      <GoogleMapsEmbed
        apiKey="XYZ"
        height={200}
        width="100%"
        mode="place"
        q="Brooklyn+Bridge,New+York,NY"
      />
      <YouTubeEmbed videoid="ogfYd705cRs" height={400} params="controls=0" />
    </>
  );
}

Trải nghiệm người dùng: giúp thư viện bên thứ ba tải nhanh hơn

Trong một thế giới hoàn hảo, mọi thư viện bên thứ ba được sử dụng rộng rãi sẽ được tối ưu hoá hoàn toàn, khiến mọi yếu tố trừu tượng giúp cải thiện hiệu suất trở nên không cần thiết. Tuy nhiên, cho đến khi điều đó trở thành hiện thực, chúng tôi có thể cố gắng cải thiện trải nghiệm người dùng khi tích hợp thông qua các khung phổ biến như Next.js. Chúng tôi có thể thử nghiệm nhiều kỹ thuật tải, đảm bảo các tập lệnh được sắp xếp theo trình tự phù hợp và sau cùng là chia sẻ ý kiến phản hồi với các nhà cung cấp bên thứ ba để khuyến khích các thay đổi về luồng ngược dòng (upstream).

Hãy xem video nhúng trên YouTube. Trong trường hợp một số phương thức triển khai thay thế có hiệu suất tốt hơn nhiều so với phương thức nhúng gốc. Hiện tại, thành phần <YouTubeEmbed> do @next/third-parties xuất sẽ sử dụng lite-youtube-embed, khi được minh hoạ trong bảng so sánh Next.js "Hello, World" ("Xin chào thế giới") sẽ tải nhanh hơn đáng kể.

Ảnh GIF cho thấy so sánh tải trang giữa thành phần Nhúng trên YouTube và iframe YouTube thông thường
WebPageTest (4G dành cho thiết bị di động – Virginia Hoa Kỳ)

Tương tự, đối với Google Maps, chúng tôi đưa loading="lazy" vào làm thuộc tính mặc định cho lượt nhúng để đảm bảo rằng bản đồ chỉ tải khi cách khung nhìn một khoảng cách nhất định. Đây có vẻ như là một thuộc tính hiển nhiên cần đưa vào – đặc biệt là khi tài liệu về Google Maps đưa nó vào đoạn mã mẫu – nhưng chỉ 45% trang web Next.js nhúng Google Maps đang sử dụng loading="lazy".

Chạy tập lệnh của bên thứ ba trong một trình chạy web

Một kỹ thuật nâng cao mà chúng ta đang khám phá trong @next/third-parties giúp bạn dễ dàng giảm tải các tập lệnh của bên thứ ba cho một trình thực thi web. Được các thư viện như Partytown phổ biến phổ biến, điều này có thể làm giảm đáng kể tác động của các tập lệnh bên thứ ba đối với hiệu suất trang bằng cách di chuyển hoàn toàn các tập lệnh đó ra khỏi luồng chính.

Ảnh GIF động sau đây cho thấy sự thay đổi trong các tác vụ dài và thời gian chặn luồng chính khi áp dụng các chiến lược <Script> khác nhau cho một vùng chứa GTM trong một trang web Next.js. Xin lưu ý rằng mặc dù việc chuyển đổi giữa các lựa chọn chiến lược chỉ làm trễ thời gian thực thi các tập lệnh này, nhưng việc chuyển các tập lệnh đó sang một trình chạy web sẽ hoàn toàn loại bỏ thời gian trên luồng chính.

Ảnh GIF cho thấy sự khác biệt về thời gian chặn luồng chính của các chiến lược Script khác nhau
WebPageTest (4G dành cho thiết bị di động – Virginia Hoa Kỳ)

Trong ví dụ cụ thể này, việc di chuyển hoạt động thực thi vùng chứa Trình quản lý thẻ của Google (GTM) và các tập lệnh thẻ liên kết với vùng chứa đó sang một trình chạy web đã giảm 92% TBT.

Lưu ý: Nếu không được quản lý cẩn thận, kỹ thuật này có thể tự động phá vỡ nhiều tập lệnh của bên thứ ba, gây khó khăn cho việc gỡ lỗi. Trong những tháng tới, chúng tôi sẽ xác thực xem có bất kỳ thành phần bên thứ ba nào do @next/third-parties cung cấp hoạt động đúng cách khi chạy trong một trình chạy web hay không. Nếu có, chúng tôi sẽ cố gắng cung cấp một cách thức dễ dàng và không bắt buộc để nhà phát triển có thể sử dụng kỹ thuật này.

Các bước tiếp theo

Trong quá trình phát triển gói này, rõ ràng là cần phải tập trung các đề xuất tải của bên thứ ba để các khung khác cũng có thể hưởng lợi từ chính các kỹ thuật cơ bản được sử dụng. Điều này dẫn đến việc chúng tôi xây dựng Bên thứ ba Capital, một thư viện sử dụng JSON để mô tả kỹ thuật tải của bên thứ ba, hiện đang đóng vai trò nền tảng cho @next/third-parties.

Bước tiếp theo, chúng tôi sẽ tiếp tục tập trung vào việc cải thiện các thành phần được cung cấp cho Next.js, cũng như mở rộng nỗ lực để đưa các tiện ích tương tự vào các khung phổ biến khác và nền tảng CMS. Hiện tại, chúng tôi hợp tác với các nhà bảo trì Nuxt và dự định phát hành các tiện ích tương tự của bên thứ ba, phù hợp với hệ sinh thái của họ trong thời gian sắp tới.

Nếu một trong những bên thứ ba mà bạn sử dụng trong ứng dụng Next.js được @next/third-parties hỗ trợ, hãy cài đặt gói và dùng thử! Chúng tôi rất mong nhận được ý kiến phản hồi của bạn trên GitHub.