Table of contents
- We share essential steps every developer should follow to ensure their website performs at its best, with specific insights for Next.js
- Website performance is a fundamental aspect of user satisfaction and engagement
- Quick tips from Nearform’s website optimisation checklist
- Must-do: Set up effective monitoring
- Vital check: Perfect your caching setup
- Necessary validation: Confirm connection reuse
- Optimise your CDN strategy
- Data efficiency: Optimise __NEXT_DATA__
- Picture perfect: Ensuring ongoing image optimisation
- Future-proof: Maintaining the latest in Next.js
- Cut the clutter: Removing unused JS/CSS
- Building performance: piece by piece
By Paul Negrutiu
We share essential steps every developer should follow to ensure their website performs at its best, with specific insights for Next.js
In today's fast-paced digital landscape, the need for top speed and performance for your website has never been more critical. Whether it's to capture user attention, improve search engine optimisation (SEO) or simply provide a seamless browsing experience, performance optimisation is a priority for website developers across all stacks.
At Nearform we've had the privilege of working on a variety of projects, ranging from building apps from the ground up to critical interventions in ongoing developments. This extensive experience has given us deep insights into performance optimisation. We frequently collaborate with clients who demand exceptional scalability and performance, and our proven strategies have consistently delivered outstanding results.
Website performance is a fundamental aspect of user satisfaction and engagement
Lately, many developers have made Next.js their web development framework of choice. This is due to its ability to enhance SEO and improve search engine rankings, driving more traffic and engagement to their website.
The rise in popularity of Next.js can be attributed in part to its robust performance capabilities. With built-in server-side rendering (SSR) and static site generation (SSG), Next.js empowers developers to create blazing-fast web applications without compromising on functionality or user experience.
However, even the most powerful tools require fine-tuning to unleash their full potential. This guide will cover general optimisation techniques, with a specific focus on Next.js, to help you achieve superior performance and better rankings.
As we dive into the details of optimising Next.js website performance, it's essential to recognise that speed is not just a technical concern — it's a fundamental aspect of user satisfaction and engagement. Users expect websites to load quickly and seamlessly, regardless of the underlying technology stack, these are some of the things to be aware of:
47% of users expect a page to load in under 2 seconds
100ms in latency costs 1% in sales
Load times over 1s for a mobile site increase visitor bounce rate by 90%
While our focus is on Next.js, it's worth noting that many of the performance optimisation techniques we'll discuss can be applied across various technology stacks —- irrespective of the framework, the principles of performance optimisation remain largely consistent.
Quick tips from Nearform’s website optimisation checklist
Drawing from our past experiences, we've developed a checklist that can serve as a go-to guide for website optimisation. This checklist encapsulates some of the essential steps every developer should follow to ensure their website performs at its best. While we include general optimisation techniques, we also provide specific insights for Next.js.
Here are some quick tips from our checklist to get you started, and remember, our team at Nearform is always ready to provide expert guidance tailored to your specific needs.
Must-do: Set up effective monitoring
Before delving into the intricacies of performance optimisation, it's essential to establish a robust monitoring system tailored to your application. Effective monitoring not only allows you to track the impact of optimisations over time but also facilitates the identification of potential bottlenecks, empowering you to make informed decisions for further performance enhancements.
For real-time monitoring and visualisation, leveraging tools like Prometheus and Grafana is paramount. Prometheus excels in collecting metrics from both your application and infrastructure, while Grafana offers comprehensive visualisation and analysis capabilities. Together, they enable you to scrutinise crucial performance indicators and help with identifying performance bottlenecks and resource constraints, paving the way for targeted optimisations.
In addition to real-time monitoring, investing in performance monitoring tools like NewRelic or Datadog provides invaluable insights into your application's performance at a deeper level. By analysing this data, you can fine-tune your application's performance, ensuring seamless user experiences across various scenarios.
Vital check: Perfect your caching setup
Caching is one of the most effective ways to improve the performance of your web application. When implementing caching, it's essential to identify what resources and data should be cached, how long should those be cached for and when the cache should be refreshed.
When dealing with large volumes of data, slow performance can be a common issue. Even fetching cached data can unexpectedly take a significant amount of time. Our experience reveals the efficacy of compressing data (utilising formats like gzip or brotli) before caching, as it can notably enhance load times. It's worth noting that certain caching solutions offer this compression option, presenting a potential game-changer. Keeping a vigilant eye on such features could yield significant performance improvements.
Necessary validation: Confirm connection reuse
Connection reuse is a crucial strategy for optimising the performance of web applications. By reusing existing connections, instead of establishing new ones for each request, you can reduce latency, and improve throughput and the overall speed of your application. This is particularly important for applications that make numerous HTTP requests or database queries.
Reusing connections eliminates the need for repeated TCP handshakes, reducing the time it takes to establish a connection and start data transfer while also reducing the computational and memory overhead associated with establishing and tearing down connections, leading to more efficient resource utilisation.
Ensure that your web server is configured to support Keep-Alive connections. If your application makes frequent database queries, consider using connection pooling to reuse database connections. When making HTTP requests from your Next.js application, opt for HTTP clients that support Keep-Alive. For instance, Node.js's HTTP and HTTPS modules inherently support Keep-Alive, while some third-party libraries, such as axios, may require explicit configuration for this feature. Set an appropriate timeout value to strike a balance between reusing connections efficiently and avoiding the risks of keeping idle connections open for too long.
Optimise your CDN strategy
Content Delivery Networks (CDNs) play a vital role in improving the performance and reliability of web applications by distributing content closer to users.
Select a CDN provider that suits your needs. Popular options include Cloudflare, AWS CloudFront, Akamai and Fastly. Each provider offers different features and pricing models, so choose one that aligns with your performance and budget requirements. Enable compression on your CDN to further reduce the size of transmitted data. Most CDNs support Gzip and Brotli compression. Use HTTP headers to control how and when your assets are cached.
Data efficiency: Optimise __NEXT_DATA__
The __NEXT_DATA__
object is a global variable injected by Next.js into every page on the client side to help with faster rendering and it can grow in size extremely fast (read more).
Often times in cases when Next.js apps have performance issues, __NEXT_DATA__
is a good place to focus for performance improvements. While the __NEXT_DATA__
object in Next.js is a powerful tool, misusing its capabilities can lead to serious performance penalties. The key thing here is to only keep crucial and essential data about the page in this object.
Try to review the data and remove any piece of data that is not needed for the initial rendering. We’ve seen huge improvements just by double-checking for duplicate data or removing certain properties that weren’t needed initially (and you definitely have some of those).
Picture perfect: Ensuring ongoing image optimisation
Lighthouse, is an open-source automated tool for measuring website performance and quality. It often flags images as significant performance issues, especially on mobile. Common problems include improperly sized and unoptimised images. To address these issues, the Next.js next/image component is highly effective:
Automatic optimisation: Images are optimised based on device characteristics, reducing bandwidth and improving CLS metrics.
Lazy loading: Images load as they enter the viewport, enhancing initial page load times.
Modern formats: Supports WebP and AVIF formats, which offer better compression and quality.
Responsive images: Automatically selects appropriate sizes for various screen sizes.
Placeholders: Provides visual feedback during loading, improving perceived performance.
Future-proof: Maintaining the latest in Next.js
Maintaining an up-to-date Next.js application is crucial for ensuring optimal performance. Regular updates bring numerous benefits, including performance enhancements, security patches, and new features.
Each Next.js release often includes optimisations that enhance performance. These updates can reduce build times, improve server-side rendering speed, and enhance client-side performance.
Cut the clutter: Removing unused JS/CSS
Eliminating unused JavaScript and CSS is a key strategy for optimising the performance of your Next.js application. Removing unused code reduces the overall size of your application, leading to quicker load times and a more responsive user experience.
Metrics such as First Contentful Paint (FCP), Time to Interactive (TTI), and Largest Contentful Paint (LCP) improve when there is less code to parse, compile, and execute. Smaller files are more efficient to cache, making repeated visits faster and reducing server load.
What can you do? Analyse your bundle and get rid of unnecessary code; make sure the project is set up to use tree shaking, dynamic imports can help in certain situations.
Building performance: piece by piece
Every project is unique and fine-tuning an application’s performance will be unique to that application. The above list serves as a guide to follow to shave off some big wins when it comes to performance tuning. The most important thing is to have a strategy and improve the performance piece by piece.