Pemisahan kode dengan impor dinamis di Next.js

Cara mempercepat aplikasi Next.js dengan strategi pemisahan kode dan pemuatan cerdas.

Apa yang akan Anda pelajari?

Postingan ini menjelaskan berbagai jenis kode pemisahan dan cara menggunakan impor dinamis untuk mempercepat aplikasi Next.js.

Pemisahan kode berbasis rute dan berbasis komponen

Secara default, Next.js membagi JavaScript Anda menjadi potongan-potongan terpisah untuk setiap rute. Saat pengguna memuat aplikasi Anda, Next.js hanya mengirim kode yang diperlukan untuk rute awal. Saat pengguna menavigasi aplikasi, mereka mengambil potongan yang terkait dengan rute lainnya. Pemisahan kode berbasis rute meminimalkan skrip yang perlu diurai dan dikompilasi sekaligus, yang menghasilkan waktu muat halaman yang lebih cepat.

Meskipun pemisahan kode berbasis rute adalah default yang baik, Anda dapat lebih mengoptimalkan proses pemuatan dengan pemisahan kode di level komponen. Jika Anda memiliki sebaiknya Anda membaginya menjadi potongan-potongan terpisah. Dengan begitu, setiap komponen besar yang tidak penting atau hanya dirender pada interaksi pengguna (seperti mengklik tombol) dapat dimuat dengan lambat.

Next.js mendukung import() dinamis, yang memungkinkan Anda mengimpor modul JavaScript (termasuk komponen React) secara dinamis dan memuat setiap impor sebagai potongan terpisah. Hal ini memberi Anda pemisahan kode di level komponen dan memungkinkan Anda mengontrol pemuatan resource sehingga pengguna hanya mengunduh kode yang mereka butuhkan untuk bagian situs yang yang sedang mereka lihat. Di Next.js, komponen ini dirender sisi server (SSR) secara {i>default<i}.

Penerapan impor dinamis

Postingan ini menyertakan beberapa versi aplikasi contoh yang terdiri dari halaman web dengan satu tombol. Saat Anda mengklik tombol tersebut, Anda akan melihat anak yang lucu. Sebagai Anda menelusuri setiap versi aplikasi, Anda akan melihat bagaimana impor dinamis berbeda dari metrik statis impor dan bagaimana cara mengatasinya.

Di versi pertama aplikasi, anak tinggal di components/Puppy.js. Kepada menampilkan anak di halaman, aplikasi akan mengimpor komponen Puppy di index.js dengan pernyataan impor statis:

import Puppy from "../components/Puppy";

Untuk melihat cara Next.js memaketkan aplikasi, periksa pelacakan jaringan di DevTools:

  1. Untuk melihat pratinjau situs, tekan Lihat Aplikasi. Lalu tekan Layar penuh layar penuh.

  2. Tekan `Control+Shift+J` (atau `Command+Option+J` di Mac) untuk membuka DevTools.

  3. Klik tab Jaringan.

  4. Centang kotak Disable cache.

  5. Muat ulang halaman.

Saat Anda memuat halaman, semua kode yang diperlukan, termasuk Puppy.js yang digabungkan dalam index.js:

Tab Jaringan DevTools menampilkan enam file JavaScript: index.js, app.js, webpack.js, main.js, 0.js, dan file dll (library link dinamis).

Saat Anda menekan tombol Click me, hanya permintaan untuk puppy JPEG yang akan ditambahkan ke tab Jaringan:

Tab Jaringan DevTools setelah klik tombol, menampilkan enam file JavaScript dan satu gambar yang sama.

Kelemahan dari pendekatan ini adalah bahwa bahkan jika pengguna tidak mengeklik tombol untuk melihat anak anjingnya, mereka harus memuat komponen Puppy karena itu termasuk dalam index.js. Dalam contoh kecil ini, hal itu bukanlah masalah besar, tetapi di dunia nyata sering kali merupakan peningkatan besar untuk memuat komponen besar hanya ketika diperlukan.

Sekarang lihat versi kedua aplikasi, di mana impor statis diganti dengan impor dinamis. Next.js menyertakan next/dynamic, yang membuatnya dapat menggunakan impor dinamis untuk komponen apa pun dalam Berikutnya:

import Puppy from "../components/Puppy";
import dynamic from "next/dynamic";

// ...

const Puppy = dynamic(import("../components/Puppy"));

Ikuti langkah-langkah dari contoh pertama untuk memeriksa pelacakan jaringan.

Saat pertama kali memuat aplikasi, hanya index.js yang didownload. Kali ini 0,5 KB lebih kecil (turun dari 37,9 KB menjadi 37,4 KB) karena tidak menyertakan kode untuk komponen Puppy:

Jaringan DevTools menampilkan enam file JavaScript yang sama, kecuali index.js yang sekarang lebih kecil 0,5 KB.

Komponen Puppy sekarang berada di potongan terpisah, 1.js, yang hanya dimuat ketika Anda menekan tombol:

Tab Jaringan DevTools setelah klik tombol, menunjukkan file 1.js tambahan dan gambar yang ditambahkan ke bagian bawah daftar file.

Dalam penerapan dunia nyata, komponen sering banyak lebih besar, dan pemuatan lambat dapat memangkas {i>payload<i} JavaScript awal Anda hingga ratusan kilobita.

Impor dinamis dengan indikator pemuatan kustom

Saat Anda memuat resource secara lambat, berikan indikator pemuatan jika terjadi keterlambatan. Di Next.js, Anda dapat melakukannya dengan memberikan argumen tambahan ke fungsi dynamic():

const Puppy = dynamic(() => import("../components/Puppy"), {
  loading: () => <p>Loading...</p>
});

Untuk melihat cara kerja indikator pemuatan, simulasikan koneksi jaringan lambat di DevTools:

  1. Untuk melihat pratinjau situs, tekan Lihat Aplikasi. Lalu tekan Layar penuh layar penuh.

  2. Tekan `Control+Shift+J` (atau `Command+Option+J` di Mac) untuk membuka DevTools.

  3. Klik tab Jaringan.

  4. Centang kotak Disable cache.

  5. Di menu drop-down Throttling, pilih 3G Cepat.

  6. Tekan tombol Klik saya.

Sekarang, saat Anda mengklik tombol, perlu waktu beberapa saat untuk memuat komponen dan aplikasi menampilkan pesan "Memuat..." pesan pada saat itu.

Layar gelap dengan teks

Impor dinamis tanpa SSR

Jika Anda perlu merender komponen hanya di sisi klien (misalnya, chat ) Anda dapat melakukannya dengan menetapkan opsi ssr ke false:

const Puppy = dynamic(() => import("../components/Puppy"), {
  ssr: false,
});

Kesimpulan

Dengan dukungan untuk impor dinamis, Next.js memberi Anda kode tingkat komponen terpisah, yang dapat meminimalkan payload JavaScript dan meningkatkan performa aplikasi waktu pemuatan. Semua komponen dirender di sisi server secara default dan Anda dapat nonaktifkan opsi ini bila diperlukan.