During some late night performance testing, I kept asking myself, “How can I reduce page load times in Next.js load times?” While obsessing over the Network Panel tool, I did what most engineers do in times of desperation and hit the Google. That’s when I discovered the amazing world of dynamic imports.
Note: Dynamic imports were introduced in ES2020 and may require additional setup. At the time of writing this, dynamic imports in Next.js are only supported for components.
What are Dynamic Imports?
Unlike regular import modules, dynamic imports are flexible about when and how they are loaded. Instead of being forced to load the module file at read time, dynamic imports can be requested at the time of use. By code splitting the module into a separate bundle file it can be fetched separately which reduces the initial page load.
How to Set Up Dynamic Imports in Next.js
Before proceeding, there are some things to be aware of about dynamic imports. While dynamic importing can reduce page load, it’s very important to know how the bundle fetching process behaves to avoid negative side effects that would increase page load.
- Dynamic imports are fetched when the component is rendered for the first time.
- Already rendered imports do not trigger an additional re-fetch.
- Each dynamic import will create a newly incremented bundle file. This includes nested dynamic imports.
- Each dynamic import adds a new server request.
Building an Example
Setting up dynamic imports in Next.js can be done in a few lines of code that are demonstrated in the example below. For more advanced ways to use the dynamic function, make sure to check out the Next.js Dynamic Imports.
- First, import the
dynamic
function usingimport dynamic from "next/dynamic";
. - Next, create a new constant. Assign the
dynamic
function to reference your component. Ex:const GoodbyeDynamic = dynamic(() => import("../components/Goodbye"));
- Now the const can be used just like the original
Goodbye
component.
The following example demonstrates Goodbye
component being dynamically imported. When the app is first rendered, the console statement from <Hello />
is immediately invoked. Meanwhile, the console statement from <Goodbye />
does not invoke until after the button is clicked which triggers the component to <GoodbyeDynamic />
component to render.
Checking Your Work
You can verify the magic of dynamic importing by checking out the Network Panel in the code and interacting looking for number JS files such as 0.js
. In Next.js 0.js
is the main bundle file. Meanwhile, dynamic imports start at 1.js
and increment a new bundle per new dynamic import.
Knowing When to Use Dynamic Imports
It may take some trial and error to identify the best places to utilize dynamic importing since it’s not always necessary. Here is a list of things I found helpful while experimenting.
Things to Look for:
- Scenarios where resource heavy components are not rendered on page load are great for dynamic imports
- Modules that rely on external resources can take advantage of asynchronous importing
- The need to display a loading component while a component is rendering. This can be easier to spot with a throttled network connection
Things to Avoid:
- If a dynamically imported component renders immediately, the payload size is the same and adds an extra server request for the additional code bundle.
- Avoid over using dynamic imports. Each use case adds a new server request and code bundle. This could be costly if this feature is overused.
- Avoid nesting dynamic imports when possible. This can easily add extra server requests and code bundles.
- Dynamic imports in Next.js do not work on functions. This might be possible in the future, but for now, isn’t highly supported.
Real-Life Scenarios
Here are some typical components that would be great for dynamic imports:
- UI components such as modals, drawers, and toggles that don’t display content until an interaction occurs
- Search components that rely on some form of text input or button click
- “Load More” components that render additional content on user interaction
- Module queries from an external API
- Components that are slow loading and could benefit from a loading component while the import resolves
Takeaways
If you have heavy resource components that don’t need to render on page load, absolutely use dynamic imports. This can make a huge impact in page load times and lighthouse scores with minimal effort. This feature is really easy to use, and you don’t have much to lose by trying it out.
Need to hire a development team to help you with your upcoming Next.js project? Contact WebDevStudios.
Comments