DEV Community

Việt Anh Trần Hữu
Việt Anh Trần Hữu

Posted on

Tối ưu Package Imports Nextjs

Hello mọi người lại là Slao đây !
Sau đây vấn đề chúng ta sẽ giải quyết là hiểu tại sao lại dẫn đến sự ảnh hưởng khi import Package một cách bừa bãi và cách giải quyết nó

Vấn đề về Barrel File

Nhiều thư viện (đặc biệt là các thư viện biểu tượng/thành phần) sử dụng "tệp Barrel", các tệp xuất lại nhiều mô-đun từ một điểm nhập duy nhất.

Ví dụ, nếu bạn nhập { AlertIcon } từ 'lucide-react', thì thực ra bạn đang nhập thông qua tệp Barrel có thể chứa hàng nghìn biểu tượng xuất khác. Mặc dù bạn chỉ muốn một biểu tượng, thời gian chạy JavaScript phải xử lý TẤT CẢ các lần xuất, có thể mất 200-800ms hoặc thậm chí vài giây.

Tại sao đây là vấn đề về hiệu suất?

Mỗi require() hoặc import đều có chi phí phát sinh trong JavaScript.

  • Trong quá trình phát triển: Làm chậm quá trình khởi động ban đầu và tải lại mô-đun nóng.
  • Trong quá trình sản xuất: Đặc biệt ảnh hưởng đến môi trường không có máy chủ (serverless), nơi thường xuyên khởi động nguội.

Một số thư viện có tới 10.000 lần xuất lại trong các tệp barrel của chúng!

optimizePackageImports trong Next.js

Cách hoạt động

Bạn có thể bật optimizePackageImports trong next.config.js cho các gói cụ thể để tối ưu hóa quá trình nhập.

module.exports = {
  experimental: {
    optimizePackageImports: ["lucide-react", "my-lib"],
  },
};

Enter fullscreen mode Exit fullscreen mode

Next.js phân tích tệp barrel của các gói này. Khi nó thấy import { AlertIcon } from 'lucide-react', nó tự động chuyển đổi tệp đó để import trực tiếp từ tệp module cụ thể. Giống như thay đổi import { AlertIcon } from 'lucide-react' thành import AlertIcon from 'lucide-react/dist/icons/alert' ở bên trong.

Khi nào nên sử dụng

Nên cân nhắc sử dụng optimizePackageImports khi:

  • Đang sử dụng các thư viện biểu tượng lớn (lucide-react, @tabler/icons-react).
  • Đang sử dụng các thư viện thành phần có nhiều exports (@mui/material).
  • Nhận thấy thời gian khởi động development server chậm.
  • Lo ngại về thời gian khởi động nguội trong production.
  • Việc tải lại mô-đun nóng có cảm giác chậm chạp.

Cải thiện hiệu suất

Môi trường Cải thiện hiệu suất
Development Thời gian khởi động nhanh hơn 15-70%
Build time Bản dựng nhanh hơn khoảng 28%
Cold Start Nhanh hơn tới 40%

Ví dụ: Khi sử dụng @material-ui/icons, thời gian phát triển giảm từ 10,2 giây xuống còn 2,9 giây.


Cách phát hiện khi cần tối ưu hóa

Bạn có thể kiểm tra các dấu hiệu sau:

  • node_modules chứa các gói có tệp index.js lớn với nhiều lần export (sử dụng trình phân tích gói).
  • Sử dụng các thư viện UI component hoặc thư viện biểu tượng phổ biến.
  • Máy chủ development khởi động chậm (mất vài giây).
  • Quá trình build chậm hơn mong đợi.
  • Nhận thấy vấn đề về hiệu suất khi nhập từ các thư viện lớn.
  • Có thể kiểm tra thời gian nhập bằng cách thêm console.time() trước và sau khi nhập.

Console time :

console.time("import");
import { AlertIcon } from "lucide-react";
console.timeEnd("import");

Enter fullscreen mode Exit fullscreen mode

Ưu điểm của optimizePackageImports

Điều hay ho là Next.js tự động xử lý mọi thứ. Bạn chỉ cần chọn các gói cần tối ưu hóa, và Next.js sẽ lo phần còn lại.


Không dành cho các tệp barrel của riêng bạn

optimizePackageImports chỉ áp dụng cho các gói trong node_modules, không phải cho các tệp barrel trong dự án của bạn.

// Using a barrel file
import { Button, Card, TextField } from "@/components";

Enter fullscreen mode Exit fullscreen mode
  • Đây là sự nhầm lẫn mà nhiều người gặp phải.
  • Đối với các tệp barrel của riêng, nên tránh hoàn toàn.
// Direct imports - better performance
import Button from "@/components/Button";
import Card from "@/components/Card";
import TextField from "@/components/TextField";

Enter fullscreen mode Exit fullscreen mode
  • Giải pháp: Cấu trúc lại mã để sử dụng import trực tiếp thay vì tối ưu hóa các tệp barrel.

Khi nào optimizePackageImports thực sự hữu ích?

optimizePackageImports hỗ trợ các gói bên thứ ba có cấu trúc phức tạp mà bạn không thể kiểm soát, đặc biệt là:

  • Thư viện biểu tượng (lucide-react, @tabler/icons).
  • Thư viện UI component (@mui/material).
  • Thư viện tiện ích lớn.

Nếu gặp vấn đề về hiệu suất với các tệp barrel của riêng bạn, hãy cấu trúc lại mã thay vì tìm cách tối ưu hóa chúng.


Top comments (0)