Pemisahan kode dengan impor dinamis di Next.js

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

Dipublikasikan: 8 November 2019

Pelajari berbagai jenis pemisahan kode dan cara menggunakan impor dinamis untuk mempercepat aplikasi Next.js Anda.

Pemisahan kode berbasis rute dan berbasis komponen

Secara default, Next.js membagi JavaScript Anda menjadi chunk terpisah untuk setiap rute. Saat pengguna memuat aplikasi Anda, Next.js hanya mengirimkan kode yang diperlukan untuk rute awal. Saat menjelajahi aplikasi, pengguna mengambil chunk yang terkait dengan rute lainnya. Pemisahan kode berbasis rute meminimalkan jumlah skrip yang perlu diuraikan dan dikompilasi sekaligus, sehingga menghasilkan waktu pemuatan halaman yang lebih cepat.

Meskipun pemisahan kode berbasis rute adalah default yang baik, Anda dapat lebih mengoptimalkan proses pemuatan dengan pemisahan kode di tingkat komponen. Jika Anda memiliki komponen besar di aplikasi, sebaiknya pisahkan komponen tersebut menjadi beberapa bagian. Dengan begitu, komponen besar yang tidak penting atau hanya dirender pada interaksi pengguna tertentu (seperti mengklik tombol) dapat dimuat secara lambat.

Next.js mendukung import()dinamis, yang memungkinkan Anda mengimpor modul JavaScript (termasuk komponen React) secara dinamis dan memuat setiap impor sebagai chunk terpisah. Hal ini memberi Anda pemisahan kode tingkat komponen dan memungkinkan Anda mengontrol pemuatan resource sehingga pengguna hanya mendownload kode yang mereka butuhkan untuk bagian situs yang mereka lihat. Di Next.js, komponen ini dirender sisi server (SSR) secara default.

Cara kerja impor dinamis

Postingan ini mencakup beberapa versi aplikasi contoh yang terdiri dari halaman sederhana dengan satu tombol. Saat mengklik tombol, Anda akan melihat anak yang lucu. Saat Anda berpindah ke setiap versi aplikasi, Anda akan melihat bagaimana impor dinamis berbeda dari impor statis dan cara menggunakannya.

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

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

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

  1. Untuk melihat pratinjau situs, tekan Lihat Aplikasi. Kemudian 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 Nonaktifkan cache.

  5. Muat ulang halaman.

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

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

Saat Anda menekan tombol Click me, hanya permintaan untuk JPEG anak yang ditambahkan ke tab Network:

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

Kelemahan pendekatan ini adalah meskipun pengguna tidak mengklik tombol untuk melihat anak, mereka harus memuat komponen Puppy karena disertakan dalam index.js. Dalam contoh kecil ini, hal tersebut tidak menjadi masalah besar, tetapi dalam aplikasi dunia nyata, memuat komponen besar hanya saat diperlukan sering kali memberikan peningkatan yang sangat besar.

Sekarang, lihat versi kedua aplikasi, yang impor statisnya diganti dengan impor dinamis. Next.js menyertakan next/dynamic, yang memungkinkan penggunaan impor dinamis untuk komponen apa pun di Next:

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

// ...

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

Ikuti langkah-langkah dari contoh pertama untuk memeriksa rekaman aktivitas jaringan.

Saat Anda pertama kali memuat aplikasi, hanya index.js yang didownload. Kali ini, ukurannya 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 berukuran 0,5 KB lebih kecil.

Komponen Puppy kini berada di chunk terpisah, 1.js, yang dimuat hanya saat Anda menekan tombol:

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

Dalam aplikasi dunia nyata, komponen sering kali jauh lebih besar, dan pemuatan lambatnya dapat memangkas payload JavaScript awal Anda hingga ratusan kilobyte.

Impor dinamis dengan indikator pemuatan kustom

Saat Anda memuat resource secara lambat, sebaiknya berikan indikator pemuatan jika terjadi penundaan. 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 indikator pemuatan beraksi, simulasikan koneksi jaringan lambat di DevTools:

  1. Untuk melihat pratinjau situs, tekan Lihat Aplikasi. Kemudian 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 Nonaktifkan cache.

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

  6. Tekan tombol Click me.

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

Layar gelap dengan teks

Impor dinamis tanpa SSR

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

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

Kesimpulan

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