Next.js: Reshaping Web App Architecture for Performance Excellence

Rate this content
Bookmark

Are you struggling to achieve optimal performance in your web applications? Are you unsure about how to effectively manage your application's routes while ensuring maximum security for your sensitive data? These are the most recent problems we encountered at l’Oréal Tech Accelerator where our users used to wait in front of empty white screens long before getting the needed information. After extensive research and deliberation, we looked at Next.js as a potential solution to our woes. However, adopting Next.js presented us with a new set of challenges. We had to rethink our architecture and determine the best approach for integrating the frontend, backend, and our core backend systems. In this talk we will discuss in more details the obstacles we faced and the innovative solutions we implemented to overcome them.

This talk has been presented at React Summit 2024, check out the latest edition of this React Conference.

FAQ

L'Oreal Tech Accelerator is an internal department dedicated to driving digital innovation at L'Oreal. They design apps to help L'Oreal staff be more productive.

Myrna Sochnaeser is a lead full-stack developer at L'Oreal Tech Accelerator.

L'Oreal Tech Accelerator decided to use Next.js to improve the performance of their web applications by leveraging features like automatic code splitting and different types of rendering (client-side rendering, server-side rendering, and static site generation).

At L'Oreal Tech Accelerator, a good application is defined by factors such as performance, accessibility, and security.

In client-side rendering, the browser fetches the index.html and bundled.js files from the CDN. After executing the JavaScript, the web page becomes visible to the user. The browser then fetches the necessary data from the server to populate the components, resulting in an initially slower page load but reduced server load.

Server-side rendering (SSR) involves the server sending a fully rendered HTML file to the browser, which includes the correct data. This results in a faster initial page load and better performance for users on low-end devices or slow internet connections. However, it increases server load and may reduce interactivity.

Static site generation (SSG) creates the index.html and bundled.js files during the build process and stores them in the CDN. It should be used for pages with heavy or static content, such as blogs, documentation, and portfolios, to provide faster page loads and better performance.

By using static site generation with Next.js, the homepage now has an instant display on the web app, eliminating the previous two-second white screen.

The data visualization page was enhanced using server-side rendering in Next.js, reducing the loading state from five seconds to less than a second.

The data creation page will use client-side rendering because it involves a lot of interactions between the users and the web app.

Mia NASR KHNEISSER
Mia NASR KHNEISSER
9 min
18 Jun, 2024

Comments

Sign in or register to post your comment.

Video Summary and Transcription

This Talk discusses how Next.js was used to reshape web app architecture for performance excellence. Next.js allows for server-side rendering (SSR) and client-side rendering (CSR), improving performance and user experience. The implementation of Next.js on the application resulted in faster initial page loads, reduced white screen time, and improved loading states. It is important to use the different rendering options correctly to maximize performance.

1. Introduction to Next.js and Web App Architecture

Short description:

I am a full-stack developer at L'Oreal Tech Accelerator, and today I will discuss how we reshaped our web app architecture using Next.js for performance excellence. Next.js allows us to render code either on the server or client-side, improving performance and user experience. We are moving from a single page application to Next.js, which enables us to have an index.html and bundled.js file per page, reducing the amount of unnecessary data on each page. Client-side rendering reduces server load and simplifies backend logic, but it has a slower initial page load. Server-side rendering fills the HTML file with data, but hydration is required for interactivity.

Hello, my name is Myrna Sochnaeser and I'm a lead full-stack developer at L'Oreal Tech Accelerator. Tech Accelerator is an internal department dedicated to driving digital innovation at L'Oreal. We design apps to help L'Oreal staff be more productive.

Today we are going to see how we reshaped our web app architecture for performance excellence and why we decided to use Next.js. At L'Oreal, there are some factors that let us define if we have a good application, like performance, accessibility, security, etc. But today we're going to focus on performance which indirectly also lets us improve our user experience.

At Tech Accelerator, we have an architecture that all our applications rely on. Our browser will try to fetch the data or the information, the files it needs from the CDN. If you do not succeed, you will go get them from the two applications hosted on App Engine. Our backend containing all our endpoints is hosted on CloudRAM and the data is hosted on Cloud SQL. We will try to replace the two applications hosted on App Engine with Next.js and have only one application.

Let's refresh our memory while checking the different renderings we can do with Next.js. Next.js is a framework that lets us create a web application where parts of our code can be rendered either on the server or on the client. This is why we talk about client-side rendering or pre-rendered on the server. And even the pre-rendered on the server is divided into many types like server-side rendering or static-side generation or others. We at first had a single page application where we needed to download one HTML file and one big JS file for all the applications. The HTML file was almost empty and the bundled contained all the information needed. But with Next.js, we will have an index.html in the chunk or bundled.js file per page. And these files will only contain the necessary to render this specific page we are at.

How does the client-side rendering work? After building our front end, we will get two files, the index.html and the bundled.js that was stored into the CDN. Once we try to access our application, the browser will go get the index.html from the CDN and then we will download, the browser will download the JS file and execute it. And once the execution is done, the web page will be visible to the user. But we will still need to go fetch the data from the server to fit the components with the correct data and remove the loading state. So in resume, we will have a white page until we download and execute the bundled.js and the loading page until we fetch the data that we need.

With the client-side rendering, we reduce the server load as the server only needs to provide the initial HTML and JavaScript file and to also simplify the backend logic because the server will primarily act as a data API leading to a cleaner and simpler backend codebase. But on the other hand, we have a slower initial page load since the browser needs to download and execute the JavaScript before rendering the page or displaying anything.

As for the server-side rendering, the browser will get the HTML file from the server. The HTML file will be filled with the correct data. We can directly see the components filled with the correct data on the browser, but they will not be hydrated. The interaction with buttons with links won't work until we fetch and download the JS file from the CDN.

2. Improving Performance with Next.js

Short description:

With SSR, we get faster initial page loads and better performance for low-end devices or slow internet connections. However, it increases server load and reduces interactivity. Static site generation is ideal for providing faster page loads and handling static content. Next.js streamlines the process, improving the initial loading state and user experience. We implemented this on our application, reducing white screen time and loading states. Next.js offers different rendering options, but it's crucial to use them correctly to maximize performance.

We can see that the white page block is reduced and we can directly see something on the web app. So with SSR, we have a faster initial page load and we have a better performance for users on low-end devices or a slow internet connection since most of the rendering process is handled by the server. But on the other hand, we increase the server load especially when dealing with a large number of simultaneous requests, impacting server response times. And we reduce interactivity as additional requests may be needed to update the page content. So SSR is perfect for content websites.

The static site generation is like server-side rendering, but with a small difference that both index.html and bundle.js are created on the build of the application and stored into the CDN. So we display an interactive page very fast. You should use static site generation with Next.js when you want to provide faster page loads and upload pages with heavy content or content that will never change, that are static. Like for example for blogs, for documentation, for portfolios, etc.

This being said, I'm going to give you some context on the application we want to improve in terms of performance. The application is a single page application and we have three types of pages. We have the homepage that is the same for all users and that is static, a page to visualize the data, and a page to create data based on a preset configuration and API algorithm. The application is used by 40 users in six different countries and we have a little bit more than six gigabytes of data. On this application the user has approximately a two-second white page. This is due to the fact that in order for the web app to be visible and actable, the browser needs to download the JS file and execute React. But since the JS file is big, the download and execution of the file took a little bit of time. Once the user started seeing something on the web app, it was the loading state for a certain period of time depending on the page he was looking at.

The solution for us was Next.js. Next.js streamlines the process of dividing the index.html and the bundle.js file into multiple ones per page, providing automatic code splitting. This approach helps improve the initial loading state of web pages, providing a faster and more efficient user experience. So here for example we can see some numbers we had we made in our book. For the home page we had a two second white screen and now with the static site generation that we added on, like where we modified our home page to use this type of rendering, we have an instant display on the web app. For the data visualization page we added server-side rendering and before with a single page application we had a five second loading state where we had seen the page but it was loading the data. Now since we are doing all the implementation and fetching the data on the server side, in less than a second we will display the data. Concerning the creation of a new data page, it's still in progress. We didn't work on it yet but we are going to use the client side rendering for it since there will be a lot of interactions between the users and the web app. In conclusion, with Next.js we can improve the performance of our applications since we have automatic code splitting and different types of rendering that we can put on the different pages. But if we do not use the rendering in the correct way we might decrease the performance of applications. So we need to think more of how to do the renderings.

That's it, thank you!

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

A Guide to React Rendering Behavior
React Advanced Conference 2022React Advanced Conference 2022
25 min
A Guide to React Rendering Behavior
Top Content
This transcription provides a brief guide to React rendering behavior. It explains the process of rendering, comparing new and old elements, and the importance of pure rendering without side effects. It also covers topics such as batching and double rendering, optimizing rendering and using context and Redux in React. Overall, it offers valuable insights for developers looking to understand and optimize React rendering.
Speeding Up Your React App With Less JavaScript
React Summit 2023React Summit 2023
32 min
Speeding Up Your React App With Less JavaScript
Top Content
Watch video: Speeding Up Your React App With Less JavaScript
Mishko, the creator of Angular and AngularJS, discusses the challenges of website performance and JavaScript hydration. He explains the differences between client-side and server-side rendering and introduces Quik as a solution for efficient component hydration. Mishko demonstrates examples of state management and intercommunication using Quik. He highlights the performance benefits of using Quik with React and emphasizes the importance of reducing JavaScript size for better performance. Finally, he mentions the use of QUIC in both MPA and SPA applications for improved startup performance.
Routing in React 18 and Beyond
React Summit 2022React Summit 2022
20 min
Routing in React 18 and Beyond
Top Content
Routing in React 18 brings a native app-like user experience and allows applications to transition between different environments. React Router and Next.js have different approaches to routing, with React Router using component-based routing and Next.js using file system-based routing. React server components provide the primitives to address the disadvantages of multipage applications while maintaining the same user experience. Improving navigation and routing in React involves including loading UI, pre-rendering parts of the screen, and using server components for more performant experiences. Next.js and Remix are moving towards a converging solution by combining component-based routing with file system routing.
React Concurrency, Explained
React Summit 2023React Summit 2023
23 min
React Concurrency, Explained
Top Content
Watch video: React Concurrency, Explained
React 18's concurrent rendering, specifically the useTransition hook, optimizes app performance by allowing non-urgent updates to be processed without freezing the UI. However, there are drawbacks such as longer processing time for non-urgent updates and increased CPU usage. The useTransition hook works similarly to throttling or bouncing, making it useful for addressing performance issues caused by multiple small components. Libraries like React Query may require the use of alternative APIs to handle urgent and non-urgent updates effectively.
The Future of Performance Tooling
JSNation 2022JSNation 2022
21 min
The Future of Performance Tooling
Top Content
Today's Talk discusses the future of performance tooling, focusing on user-centric, actionable, and contextual approaches. The introduction highlights Adi Osmani's expertise in performance tools and his passion for DevTools features. The Talk explores the integration of user flows into DevTools and Lighthouse, enabling performance measurement and optimization. It also showcases the import/export feature for user flows and the collaboration potential with Lighthouse. The Talk further delves into the use of flows with other tools like web page test and Cypress, offering cross-browser testing capabilities. The actionable aspect emphasizes the importance of metrics like Interaction to Next Paint and Total Blocking Time, as well as the improvements in Lighthouse and performance debugging tools. Lastly, the Talk emphasizes the iterative nature of performance improvement and the user-centric, actionable, and contextual future of performance tooling.
Optimizing HTML5 Games: 10 Years of Learnings
JS GameDev Summit 2022JS GameDev Summit 2022
33 min
Optimizing HTML5 Games: 10 Years of Learnings
Top Content
PlayCanvas is an open-source game engine used by game developers worldwide. Optimization is crucial for HTML5 games, focusing on load times and frame rate. Texture and mesh optimization can significantly reduce download sizes. GLTF and GLB formats offer smaller file sizes and faster parsing times. Compressing game resources and using efficient file formats can improve load times. Framerate optimization and resolution scaling are important for better performance. Managing draw calls and using batching techniques can optimize performance. Browser DevTools, such as Chrome and Firefox, are useful for debugging and profiling. Detecting device performance and optimizing based on specific devices can improve game performance. Apple is making progress with WebGPU implementation. HTML5 games can be shipped to the App Store using Cordova.

Workshops on related topic

React Performance Debugging Masterclass
React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Top Content
Featured WorkshopFree
Ivan Akulov
Ivan Akulov
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
Building WebApps That Light Up the Internet with QwikCity
JSNation 2023JSNation 2023
170 min
Building WebApps That Light Up the Internet with QwikCity
Featured WorkshopFree
Miško Hevery
Miško Hevery
Building instant-on web applications at scale have been elusive. Real-world sites need tracking, analytics, and complex user interfaces and interactions. We always start with the best intentions but end up with a less-than-ideal site.
QwikCity is a new meta-framework that allows you to build large-scale applications with constant startup-up performance. We will look at how to build a QwikCity application and what makes it unique. The workshop will show you how to set up a QwikCitp project. How routing works with layout. The demo application will fetch data and present it to the user in an editable form. And finally, how one can use authentication. All of the basic parts for any large-scale applications.
Along the way, we will also look at what makes Qwik unique, and how resumability enables constant startup performance no matter the application complexity.
Build a Headless WordPress App with Next.js and WPGraphQL
React Summit 2022React Summit 2022
173 min
Build a Headless WordPress App with Next.js and WPGraphQL
Top Content
WorkshopFree
Kellen Mace
Kellen Mace
In this workshop, you’ll learn how to build a Next.js app that uses Apollo Client to fetch data from a headless WordPress backend and use it to render the pages of your app. You’ll learn when you should consider a headless WordPress architecture, how to turn a WordPress backend into a GraphQL server, how to compose queries using the GraphiQL IDE, how to colocate GraphQL fragments with your components, and more.
Next.js 13: Data Fetching Strategies
React Day Berlin 2022React Day Berlin 2022
53 min
Next.js 13: Data Fetching Strategies
Top Content
WorkshopFree
Alice De Mauro
Alice De Mauro
- Introduction- Prerequisites for the workshop- Fetching strategies: fundamentals- Fetching strategies – hands-on: fetch API, cache (static VS dynamic), revalidate, suspense (parallel data fetching)- Test your build and serve it on Vercel- Future: Server components VS Client components- Workshop easter egg (unrelated to the topic, calling out accessibility)- Wrapping up
Create a Visually Editable Next.js Website Using React Bricks, With Blog and E-commerce
React Summit 2023React Summit 2023
139 min
Create a Visually Editable Next.js Website Using React Bricks, With Blog and E-commerce
Top Content
WorkshopFree
Matteo Frana
Matteo Frana
- React Bricks: why we built it, what it is and how it works- Create a free account- Create a new project with Next.js and Tailwind- Explore the directory structure- Anatomy of a Brick- Create a new Brick (Text-Image)- Add a title and description with RichText visual editing- Add an Image with visual editing- Add Sidebar controls to edit props (padding and image side)- Nesting Bricks using the Repeater component- Create an Image gallery brick- Publish on Netlify or Vercel- Page Types and Custom fields- Access Page meta values- Internationalization- How to reuse content across pages: Stories and Embeds- How to create an E-commerce with Products’ data from an external database and landing pages created visually in React Bricks- Advanced enterprise features: flexible permissions, locked structure, custom visual components
From Todo App to B2B SaaS with Next.js and Clerk
React Summit US 2023React Summit US 2023
153 min
From Todo App to B2B SaaS with Next.js and Clerk
WorkshopFree
Dev Agrawal
Dev Agrawal
If you’re like me, you probably have a million side-project ideas, some that could even make you money as a micro SaaS, or could turn out to be the next billion dollar startup. But how do you know which ones? How do you go from an idea into a functioning product that can be put into the hands of paying customers without quitting your job and sinking all of your time and investment into it? How can your solo side-projects compete with applications built by enormous teams and large enterprise companies?
Building rich SaaS products comes with technical challenges like infrastructure, scaling, availability, security, and complicated subsystems like auth and payments. This is why it’s often the already established tech giants who can reasonably build and operate products like that. However, a new generation of devtools are enabling us developers to easily build complete solutions that take advantage of the best cloud infrastructure available, and offer an experience that allows you to rapidly iterate on your ideas for a low cost of $0. They take all the technical challenges of building and operating software products away from you so that you only have to spend your time building the features that your users want, giving you a reasonable chance to compete against the market by staying incredibly agile and responsive to the needs of users.
In this 3 hour workshop you will start with a simple task management application built with React and Next.js and turn it into a scalable and fully functioning SaaS product by integrating a scalable database (PlanetScale), multi-tenant authentication (Clerk), and subscription based payments (Stripe). You will also learn how the principles of agile software development and domain driven design can help you build products quickly and cost-efficiently, and compete with existing solutions.