Cách tăng tốc ứng dụng Next.js bằng chiến lược phân chia mã và tải thông minh.
Ngày xuất bản: 8 tháng 11 năm 2019
Tìm hiểu về các loại phân chia mã và cách sử dụng tính năng nhập động để tăng tốc ứng dụng Next.js.
Phân chia mã dựa trên tuyến và dựa trên thành phần
Theo mặc định, Next.js chia JavaScript của bạn thành các đoạn riêng biệt cho từng tuyến đường. Khi người dùng tải ứng dụng của bạn, Next.js chỉ gửi mã cần thiết cho tuyến đường ban đầu. Khi di chuyển trong ứng dụng, người dùng sẽ tìm nạp các đoạn mã được liên kết với các tuyến đường khác. Tính năng phân chia mã dựa trên tuyến đường giúp giảm thiểu lượng tập lệnh cần được phân tích cú pháp và biên dịch cùng một lúc, nhờ đó giảm thời gian tải trang.
Mặc dù phân chia mã dựa trên tuyến đường là một lựa chọn mặc định phù hợp, nhưng bạn có thể tối ưu hoá thêm quy trình tải bằng cách phân chia mã ở cấp thành phần. Nếu có các thành phần lớn trong ứng dụng, bạn nên chia chúng thành các khối riêng biệt. Bằng cách đó, mọi thành phần lớn không quan trọng hoặc chỉ hiển thị khi có một số lượt tương tác nhất định của người dùng (chẳng hạn như nhấp vào nút) đều có thể được tải từng phần.
Next.js hỗ trợ import() động, cho phép bạn nhập các mô-đun JavaScript (bao gồm cả các thành phần React) một cách linh động và tải từng mục nhập dưới dạng một đoạn riêng biệt. Điều này giúp bạn phân chia mã ở cấp thành phần và cho phép bạn kiểm soát việc tải tài nguyên để người dùng chỉ tải mã cần thiết cho phần trang web mà họ đang xem. Trong Next.js, theo mặc định, các thành phần này được kết xuất phía máy chủ (SSR).
Nhập động trong thực tế
Bài đăng này bao gồm một số phiên bản của một ứng dụng mẫu bao gồm một trang đơn giản có một nút. Khi nhấp vào nút này, bạn sẽ thấy một chú cún đáng yêu. Khi chuyển qua từng phiên bản của ứng dụng, bạn sẽ thấy cách nhập động khác với nhập tĩnh và cách làm việc với chúng.
Trong phiên bản đầu tiên của ứng dụng, chú cún sống trong components/Puppy.js. Để hiển thị chú cún trên trang, ứng dụng sẽ nhập thành phần Puppy trong index.js bằng câu lệnh nhập tĩnh:
import Puppy from "../components/Puppy";
Để xem cách Next.js gói ứng dụng, hãy kiểm tra dấu vết mạng trong Công cụ cho nhà phát triển:
Để xem trước trang web, hãy nhấn vào Xem ứng dụng, rồi nhấn vào Toàn màn hình
.
Nhấn tổ hợp phím `Control+Shift+J` (hoặc `Command+Option+J` trên máy Mac) để mở Công cụ cho nhà phát triển.
Nhấp vào thẻ Mạng.
Chọn hộp đánh dấu Tắt bộ nhớ đệm.
Tải lại trang.
Khi bạn tải trang, tất cả mã cần thiết, bao gồm cả thành phần Puppy.js, sẽ được gói trong index.js:
Khi bạn nhấn nút Nhấp vào tôi, chỉ yêu cầu về tệp JPEG của chú cún mới được thêm vào thẻ Mạng:
Nhược điểm của phương pháp này là ngay cả khi người dùng không nhấp vào nút để xem chú cún, họ vẫn phải tải thành phần Puppy vì thành phần này có trong index.js. Trong ví dụ nhỏ này, điều đó không phải là vấn đề lớn, nhưng trong các ứng dụng thực tế, việc chỉ tải các thành phần lớn khi cần thiết thường là một điểm cải tiến lớn.
Bây giờ, hãy xem phiên bản thứ hai của ứng dụng, trong đó hoạt động nhập tĩnh được thay thế bằng hoạt động nhập động. Next.js bao gồm next/dynamic, cho phép bạn sử dụng tính năng nhập động cho mọi thành phần trong Next:
import Puppy from "../components/Puppy";
import dynamic from "next/dynamic";
// ...
const Puppy = dynamic(import("../components/Puppy"));
Làm theo các bước trong ví dụ đầu tiên để kiểm tra dấu vết mạng.
Khi bạn tải ứng dụng lần đầu tiên, chỉ có index.js được tải xuống. Lần này, kích thước nhỏ hơn 0,5 KB (giảm từ 37,9 KB xuống 37,4 KB) vì không bao gồm mã cho thành phần Puppy:
Giờ đây, thành phần Puppy nằm trong một đoạn riêng biệt, 1.js, chỉ được tải khi bạn nhấn nút:
Trong các ứng dụng thực tế, các thành phần thường lớn hơn nhiều và việc tải chúng một cách trì hoãn có thể cắt giảm tải trọng JavaScript ban đầu của bạn hàng trăm kilobyte.
Nhập động bằng chỉ báo tải tuỳ chỉnh
Khi tải tài nguyên một cách trì hoãn, bạn nên cung cấp một chỉ báo tải trong trường hợp có bất kỳ sự chậm trễ nào. Trong Next.js, bạn có thể thực hiện việc đó bằng cách cung cấp một đối số bổ sung cho hàm dynamic():
const Puppy = dynamic(() => import("../components/Puppy"), {
loading: () => <p>Loading...</p>
});
Để xem chỉ báo tải đang hoạt động, hãy mô phỏng kết nối mạng chậm trong Công cụ cho nhà phát triển:
Để xem trước trang web, hãy nhấn vào Xem ứng dụng, rồi nhấn vào Toàn màn hình
.
Nhấn tổ hợp phím `Control+Shift+J` (hoặc `Command+Option+J` trên máy Mac) để mở Công cụ cho nhà phát triển.
Nhấp vào thẻ Mạng.
Chọn hộp đánh dấu Tắt bộ nhớ đệm.
Trong danh sách thả xuống Throttling (Điều tiết), hãy chọn Fast 3G (3G nhanh).
Nhấn nút Nhấp vào tôi.
Giờ đây, khi bạn nhấp vào nút này, sẽ mất một lúc để tải thành phần và ứng dụng sẽ hiển thị thông báo "Đang tải…" trong thời gian chờ.
Nhập động mà không có SSR
Nếu chỉ cần kết xuất một thành phần ở phía máy khách (ví dụ: một tiện ích trò chuyện), bạn có thể thực hiện việc đó bằng cách đặt lựa chọn ssr thành false:
const Puppy = dynamic(() => import("../components/Puppy"), {
ssr: false,
});
Kết luận
Với khả năng hỗ trợ nhập động, Next.js cung cấp cho bạn tính năng phân tách mã ở cấp thành phần, có thể giảm thiểu tải trọng JavaScript và cải thiện thời gian tải ứng dụng. Theo mặc định, tất cả các thành phần đều được kết xuất phía máy chủ và bạn có thể tắt lựa chọn này bất cứ khi nào cần.