Optimizations
NextJS top 5 optimization tips
Made by Nextjs team
Next JS is a popular framework for building React-based web applications. It provides many features such as generation of static and dynamic pages, support for API Roots, incremental data regeneration and much more. However, like any other framework, Next JS requires some effort to achieve high performance and optimal resource utilisation. In this article, we will look at some tips and best practices for optimising a Next JS application.
1. Use the bundle analysers
Bandle analysers are tools that help you understand which modules and dependencies take up the most space in your bandle (a file containing all the code of your application). They allow you to visualise the structure and size of your bundle and identify potential problems such as duplicate code, unused modules or too large dependencies. Some of the popular bandle analysers for Next JS are webpack-bundle-analyzer, next-bundle-analyzer and next-plugin-visualizer. You can integrate them into your project using special plugins or configuration files.
1const withBundleAnalyzer = require('@next/bundle-analyzer')({
2 enabled: process.env.ANALYZE === 'true',
3})
4
5module.exports = withBundleAnalyzer({
6 // your next config
7})
2. Separate the code into chunks
Code splitting is a technique that allows you to split your bundle into several smaller parts (chunks) that are loaded as needed. This improves the load time of your application, as the user doesn't have to wait for the whole chunk to load, but only the chunks that are needed to display the current page. Next JS automatically separates code into chunks at the page level, meaning each page has its own chunk that is only loaded when the user navigates to that page. You can also use dynamic import to chunk code at the component level. To do this, you can use the import() function or the next/dynamic component. Translated with www.DeepL.com/Translator (free version)
1import dynamic from 'next/dynamic'
2
3const DynamicComponent = dynamic(() => import('../components/hello'))
4
5function Home() {
6 return (
7 <div>
8 <Header />
9 <DynamicComponent />
10 <p>HOME PAGE is here!</p>
11 </div>
12 )
13}
14
15export default Home
3. Defer rendering of non-critical components
Deferred rendering is a technique that allows you to delay rendering certain components until they are visible or needed by the user. This improves the first paint and first interactive time of your application, as you save time and resources on rendering things that the user cannot see or use yet. You can use different ways for delayed rendering in Next JS, for example:
- Use the loading="lazy" attribute for images and iframes so that they only load when they appear in the scope.
- Use the next/image component to optimize and lazily load images using the built-in Next JS mechanism.
- Use the next/script component to delay loading scripts that are not needed for the initial page rendering, such as analytics, social media widgets, or third-party libraries.
- Use libraries such as react-intersection-observer or react-visibility-sensor to track the visibility of components and render them only when needed.
4. Use pre-rendering and incremental data regeneration
Pre-rendering is a technique that allows your application's HTML code to be generated server-side or at build time, rather than at runtime in the browser. This improves the performance of your application because you reduce the time it takes to render the page in the browser, and it also improves SEO (search engine optimization) because you provide search engine robots with ready-made HTML code. Next JS supports two types of pre-rendering: static and server-side. Static pre-rendering means that you generate HTML code for each page during build time and save it as static files, which are then distributed using a CDN (content delivery network). Server-side pre-rendering means that you generate HTML code for each request at runtime on the server side. You can choose the type of pre-rendering for each page depending on its specifics and needs. To do this, you can use the getStaticProps, getStaticPaths, and getServerSideProps functions in your page components.
1export async function getStaticProps() {
2 const res = await fetch('https://.../posts')
3 const posts = await res.json()
4
5 return {
6 props: {
7 posts,
8 },
9 }
10}
5. Use image caching and optimization
Caching is a technique that allows you to store copies of frequently used data or resources in memory or on disk for quick access. This improves the performance of your application because you reduce the number of requests to the server or database and also reduce the time it takes to load resources. You can use caches in different ways
1import { getServerSideCache } from 'next/dist/server/utils'
2
3const cache = getServerSideCache()
4
5export async function getServerSideProps(context) {
6 const { req, res } = context
7
8 const cached = await cache.get(req, res)
9 if (cached) {
10 return { props: cached }
11 }
12
13 const data = await fetch('https://.../data')
14 const json = await data.json()
15
16 await cache.set(req, res, { props: json })
17
18 return { props: json }
19}
Conclusion
In this article, we looked at some tips and best practices for optimising a Next JS application. We learned how to use bandle analysers to identify potential problems in our code, how to split our code into chunks to improve load time, how to defer rendering of non-critical components to improve first paint and first interactive time, how to use pre-rendering and incremental data regeneration to improve performance and SEO, and how to use image caching and optimisation to reduce the number of requests to the server and improve load time. I hope you found this article useful and learned something new. If you have any questions or comments, please leave them in the comments section below. Thank you for reading!