NextJS Code Splitting & Dynamic Imports

Quickly looking at dynamic imports using NextJS

Published on · 3 min read

NEXTJS

NextJS already does code-splitting based on routes(aka route-based splitting).

So, if you have multiple routes(based on the structure of your pages/ directory) like

components/ ├── SignupForm.js └── LoginForm.js pages/ ├── home.js ├── login.js └── profile.js

So, when you visit /home, only the data required for home.js will be fetched.

Then, when you go to /login or /profile, the data for them will be fetched separately.

Now, lets suppose we have a signup form in our /login page component, like

// pages/login.js import { useState } from "react"; import LoginForm from "components/LoginForm"; import SignupForm from "components/SignupForm"; export default function LoginPage() { const [showSignupForm, setShowSignupForm] = useState(false); function toggleSignupForm() { setShowSignupForm((state) => !state); } return ( <div> {showSignupForm ? <SignupForm /> : <LoginForm />} <button onClick={toggleSignupForm}> {showSignupForm ? "Login" : "Signup"} </button> </div> ); }

Without dynamic imports, this LoginPage will contain both the LoginForm component as well as SignupForm component in the bundle, i.e. when the data for /login is fetched.

This is an opportunity to dynamically import(sometimes called as component-based splitting) your SignupForm component. This means that the LoginPage bundle won't contain the SignupForm data, instead it will be fetched separately when the user asks for it. Thereby decreasing the data fetched when /login is accessed.

To use dynamic import with NextJS, there's a dynamic function provided by next/dynamic. Checkout the Official NextJS Docs on dynamic imports.

Use dynamic import,

// pages/login.js import { useState } from "react"; import dynamic from "next/dynamic"; import LoginForm from "components/LoginForm"; const SignupForm = dynamic(() => import("components/SignupForm")); // dynamically imported export default function LoginPage() { const [showSignupForm, setShowSignupForm] = useState(false); function toggleSignupForm() { setShowSignupForm((state) => !state); } return ( <div> {showSignupForm ? <SignupForm /> : <LoginForm />} <button onClick={toggleSignupForm}> {showSignupForm ? "Login" : "Signup"} </button> </div> ); }

Thus, when you look at the bundle size of your LoginPage, it will be less than it was before because the SignupForm is not included in the bundle, it is to be fetched separately, when user navigates to Signup form(setting showSignupForm to true).

TL;DR

Route based splitting splits your bundle based on routes.

Using dynamic imports, you are basically separating your component(which you have dynamically imported) from the rest of the page. This separated component will have its down chunk of data, that will be fetched separately when the user asks for it.

Read more at:

Other articles

Made with ❤️ by aayushmau5