𝗛𝗼𝘄 𝗪𝗲 𝗖𝘂𝘁 𝗦𝗹𝗼𝘄 𝗥𝗲𝘀𝗽𝗼𝗻𝘀𝗲𝘀 𝗯𝘆 𝟴𝟬%
Subito is a top marketplace in Italy. We handle thousands of requests every minute. Our ad detail page is vital for SEO and revenue.
We moved this page from Next.js Pages Router to App Router. We did not stop product work to do this. We moved in small steps.
Here is how we did it.
𝗧𝗵𝗲 𝗔𝗽𝗽𝗿𝗼𝗮𝗰𝗵
We used an incremental strategy. We added the App Router tree alongside the old Pages Router. This let us ship new features while we migrated.
We used Server Components to own data fetching. This removed the need to pass data through many layers. We also created a Data Access Layer. This made sure we only fetch data once per request.
We used Suspense and the use() hook to enable HTML streaming. This shows a skeleton screen while data loads. The user sees the page faster.
𝗧𝗵𝗲 𝗖𝗵𝗮𝗹𝗹𝗲𝗻𝗴𝗲𝘀
Problem 1: HTTP 410 Gone Search engines need a 410 status when a page is permanently removed. The App Router does not have a built-in way to send this. We solved this using our Express server. The server intercepts the response and changes the status code.
Problem 2: HTML Streaming We found that our loading skeletons did not appear. The page stayed blank for seconds.
We discovered that Nginx and Akamai were buffering our responses. If the CDN buffers the HTML, streaming fails. We had to turn off buffering in Nginx and apply custom settings in Akamai. Once we fixed this, content streamed to the user perfectly.
𝗧𝗵𝗲 𝗥𝗼𝗹𝗹𝗼𝘂𝘁
We rolled out in two phases to protect our SEO.
Phase 1: We moved traffic to the App Router but kept streaming off. We did this one category at a time.
Phase 2: We enabled HTML streaming. We tested this on small categories first. Our SEO team monitored rankings for two weeks before we moved to the next category.
𝗧𝗵𝗲 𝗥𝗲𝘀𝘂𝗹𝘁𝘀
The results were huge. Before the migration, up to 40% of our responses were slow. After the migration, slow responses dropped by 80%.
Most pages now load in under 500ms.
𝗧𝗮𝗸𝗲𝗮𝘄𝗮𝘆𝘀
- Use parallel routing to migrate without stopping feature work.
- A custom server layer helps you control traffic and fix framework gaps.
- Streaming requires configuration at every layer. Check Nginx and your CDN.
- Test your SEO metrics during the rollout.
Як ми скоротили кількість повільних відповідей на 80%, перейшовши на Next.js App Router
У цій статті ми розповімо про те, як перехід на Next.js App Router дозволив нам значно покращити продуктивність нашого застосунку та зменшити кількість повільних відповідей на 80%.
Проблема: Повільні відповіді та ефект «водоспаду»
У нашому попередньому середовищі, побудованому на Pages Router, ми зіткнулися з проблемою високої затримки (latency). Користувачі часто стикалися з повільним завантаженням сторінок, що негативно впливало на їхній досвід.
Аналіз показав, що основні проблеми полягали в наступному:
- Блокуюче отримання даних (Blocking Data Fetching): Використання
getServerSidePropsозначало, що сервер мав завершити отримання всіх необхідних даних перед тим, як почати надсилати будь-який HTML клієнту. Якщо один із запитів до API був повільним, вся сторінка чекала на нього. - Ефект «водоспаду» (Waterfall Effect): На клієнтській стороні ми часто стикалися з ситуацією, коли один компонент починав завантажувати дані лише після того, як завершувався попередній запит, що створювало ланцюгову реакцію затримок.
- Великий обсяг JavaScript: Щоб зробити сторінки інтерактивними, нам доводилося надсилати великі обсяги JS-коду клієнту для процесу гідрації (hydration).
Рішення: Next.js App Router
Ми вирішили мігрувати на Next.js App Router, щоб використати нову архітектуру React та можливості серверних компонентів.
React Server Components (RSC)
Однією з головних переваг стали Server Components. На відміну від компонентів, що виконуються на клієнті, RSC виконуються виключно на сервері. Це дозволило нам:
- Зменшити розмір бандла: Оскільки логіка отримання даних та важкі бібліотеки залишаються на сервері, клієнт отримує лише необхідний HTML та мінімальний JavaScript.
- Прямий доступ до даних: Ми можемо виконувати запити до бази даних або внутрішніх API безпосередньо в компонентах, що прибирає зайві мережеві запити з боку клієнта.
Streaming та Suspense
Завдяки механізму Streaming, ми більше не повинні чекати, поки вся сторінка буде готова, щоб почати її відображення. Тепер ми можемо надсилати частини сторінки (chunks) по мірі їх готовності.
Використовуючи Suspense, ми можемо обгорнути повільні компоненти та показувати скелетони (skeletons) або індикатори завантаження. Це дозволяє користувачеві бачити основний контент сторінки майже миттєво, поки решта даних підвантажується у фоновому режимі.
Паралельне отримання даних
В App Router ми можемо легко організувати паралельне отримання даних. Замість того, щоб чекати на завершення одного запиту, щоб розпочати інший, ми можемо запускати їх одночасно, що суттєво скорочує загальний час завантаження сторінки.
Результати
Після завершення міграції ми зафіксували наступні покращення:
- Зменшення кількості повільних відповідей на 80%: Більшість користувачів тепер отримують контент значно швидше.
- Покращення TTFB (Time to First Byte): Завдяки стрімінгу перші байти сторінки надсилаються набагато швидше, що покращує показники LCP (Largest Contentful Paint).
- Зменшення обсягу JavaScript: Кількість коду, який потрібно завантажувати та виконувати на клієнті, суттєво зменшилася, що зробило взаємодію з застосунком плавнішою.
Висновок
Перехід на Next.js App Router став ключовим кроком для покращення продуктивності нашого застосунку. Використання Server Components, стрімінгу та паралельного отримання даних дозволило нам вирішити фундаментальні проблеми з затримками, з якими ми не могли впоратися за допомогою Pages Router.