<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Next js 16+ cacheComponents, переучиваемся кешировать, примеры]]></title><description><![CDATA[<p dir="auto">Переход на Next.js 16 с флагом cacheComponents  кардинально меняет философию работы с данными. Раньше фреймворк стремился все кэшировать и делал это неявно, а теперь по умолчанию все динамическое, и вы сами явно указываете, что хотите закэшировать.</p>
<p dir="auto">Это переход от модели “статики по умолчанию” к “динамике по умолчанию” с полным контролем разработчика. От себя скажу, что для разработчика это хорошо, меньше магии и больше понимания того что ты делаешь.</p>
<h2>История. Как  Next.js переобулся</h2>
<h3>Next.js 14</h3>
<p dir="auto">Тут кешировалось все, что только могло кешироваться.</p>
<p dir="auto">Фреймворк по умолчанию стремился к статической генерации страниц (SSG) во время сборки. Он переключался на динамический рендеринг (SSR) только при обнаружении «динамических» функций, таких как <code>cookies()</code> или <code>headers()</code>.</p>
<pre><code class="language-js">// app/blog/[slug]/page.tsx

export const dynamic = 'auto' // 'auto' | 'force-dynamic' | 'error' | 'force-static'
export const dynamicParams = true // true | false
export const revalidate = 3600 // false | 0 | number (в секундах)
export const fetchCache = 'auto' // 'auto' | 'force-no-store' | 'only-cache' | ...
</code></pre>
<p dir="auto">Все fetch-запросы по умолчанию кэшировались (аналог <code>cache: 'force-cache'</code>). Это означало, что если вы не указывали опции явно, данные запрашивались один раз при сборке, и все пользователи видели одну и ту же версию</p>
<pre><code class="language-js">// Данные будут получены один раз при сборке и закешированы навсегда.
// Опцию cache: 'force-cache' можно не указывать, это значение по умолчанию.
await fetch('https://api.example.com/posts', { cache: 'force-cache' });
</code></pre>
<h3>Next.js 15</h3>
<p dir="auto">Самым значимым и обсуждаемым изменением в Next.js 15 стал полный пересмотр стратегии кэширования данных. Разработчики фреймворка прислушались к сообществу, которое часто сталкивалось с непредсказуемым поведением из-за агрессивного кэша в 14-й версии.</p>
<p dir="auto"><img src="https://forum.exlends.com/assets/plugins/nodebb-plugin-emoji/emoji/android/1f4e1.png?v=a9b928d4b2f" class="not-responsive emoji emoji-android emoji--satellite_antenna" style="height:23px;width:auto;vertical-align:middle" title="📡" alt="📡" /> И вот теперь <code>fetch()</code> больше не кэширует данные.<br />
В Next.js 15 поведение по умолчанию изменилось на cache: ‘no-store’. Это значит, что каждый запрос fetch() будет выполняться заново при каждом обращении к странице, если вы явно не укажете иное. Это делает поведение в разработке и на продакшене более предсказуемым, но требует более осознанного подхода к оптимизации.</p>
<p dir="auto"><img src="https://forum.exlends.com/assets/plugins/nodebb-plugin-emoji/emoji/android/1f6e3.png?v=a9b928d4b2f" class="not-responsive emoji emoji-android emoji--motorway" style="height:23px;width:auto;vertical-align:middle" title="🛣" alt="🛣" />️ GET Route Handlers также стали динамическими<br />
Изменение коснулось и обработчиков маршрутов (Route Handlers). В 14-й версии GET-запросы кэшировались по умолчанию. В 15-й версии они также стали динамическими.</p>
<p dir="auto">Изменения затронули и клиентскую часть.<br />
В Next.js 14 кэш роутера на стороне клиента (Router Cache) по умолчанию сохранял посещенные страницы на 30 секунд для динамических и на 5 минут для статических страниц. В Next.js 15 клиентский кэш по умолчанию отключен для всех страниц. Теперь при переходе по страницам они будут загружаться заново, гарантируя, что пользователь всегда видит актуальную информацию. Если вам нужно ускорить навигацию и вы готовы пойти на компромисс, время жизни кэша можно настроить вручную в next.config.ts:</p>
<pre><code class="language-typescript">// next.config.ts
const nextConfig = {
  experimental: {
    staleTimes: {
      dynamic: 30, // 30 секунд для динамических страниц
      static: 180,  // 3 минуты для статических страниц
    },
  },
};
</code></pre>
<h3>Next.js 16</h3>
<p dir="auto">В 16-й версии Next.js добавляет флаг cacheComponents который действительно полностью меняет правила игры: он отключает всю старую модель кэширования и заменяет ее на новую, полностью явную. Всё, что вы знали о <code>fetch</code>, <code>revalidate</code> и <code>export const dynamic</code> раньше, больше не работает.</p>
<p dir="auto">Это все значит, что нам опять переучиваться ( ну, нам с  <a class="plugin-mentions-user plugin-mentions-a" href="/user/kirilljsx" aria-label="Profile: kirilljsx">@<bdi>kirilljsx</bdi></a> не привывать).  Новые проблемы -&gt;  новая работа -&gt; новые вакансии <img src="https://forum.exlends.com/assets/plugins/nodebb-plugin-emoji/emoji/android/1f618.png?v=a9b928d4b2f" class="not-responsive emoji emoji-android emoji--kissing_heart" style="height:23px;width:auto;vertical-align:middle" title=":kissing_heart:" alt="😘" /> . Об этом всем можно и поныть, но  на мой субъективный взгляд,  надо было изначально делать таким фреймворк, а  не подстраиваться под стадо  вебмакак низшего эшелона добавляю свою магию везде, где нужно и не нужно.</p>
<h2>cacheComponents - Новая реальность</h2>
<p dir="auto">Теперь, когда старые правила отключены, все решения о кэшировании принимаются явно и на уровне кода с помощью новой директивы ‘use cache’ и сопутствующих функций. Основной принцип прост: по умолчанию не кэшируется ничего.</p>
<p dir="auto"><strong>Директива <code>'use cache'</code></strong> — это ваш главный инструмент. Её можно применять на трех уровнях:</p>
<ol>
<li>
<p dir="auto">На уровне файла (страницы или компонента): Поместите директиву в самом верху файла, и все экспортируемые из него асинхронные функции будут кэшироваться.</p>
</li>
<li>
<p dir="auto">На уровне компонента: Используйте директиву внутри тела компонента, чтобы закэшировать результат его рендеринга.</p>
</li>
<li>
<p dir="auto">На уровне функции: Применяйте к асинхронным функциям, чтобы кэшировать возвращаемые ими данные.</p>
</li>
</ol>
<p dir="auto"><strong>cacheLife</strong> - Управление временем жизни кэша<br />
Для управления временем жизни кэша используется функция cacheLife. Она должна вызываться внутри области действия ‘use cache’.</p>
<p dir="auto">Вы можете использовать один из предустановленных профилей или создать свой собственный. Профили определяют три ключевых параметра: <strong><code>stale</code></strong>, <strong><code>revalidate</code></strong> и <strong><code>expire</code></strong>:</p>
<p dir="auto">Разберем подробнее, какой параметр за что отвечает.</p>
<ol>
<li>
<p dir="auto"><strong>stale (Клиентский кеш)</strong><br />
Определяет, как долго клиент (браузер) может показывать данные из кеша, вообще не связываясь с сервером для проверки.<br />
Пока не истечет это время, при повторном посещении страницы она загрузится мгновенно из памяти.<br />
Параметр чисто клиентской производительности, призванный ускорить навигацию.</p>
</li>
<li>
<p dir="auto"><strong>revalidate (Фоновая проверка)</strong><br />
Частота, с которой кеш в фоновом режиме запрашивает свежие данные с сервера.<br />
Как только время revalidate истекает, Next.js все равно мгновенно отдает клиенту “устаревший” кеш, но в фоне запускает процесс генерации новой версии. Новые данные подготовятся к следующему запросу.<br />
Механизм stale-while-revalidate. Пользователь всегда получает быстрый ответ, даже если данные немного устарели.</p>
</li>
<li>
<p dir="auto"><strong>expire (Крайний срок)</strong><br />
Максимальное время, в течение которого данные могут оставаться “устаревшими” до того, как они будут считаться полностью недействительными.<br />
Если данные в кеше находятся в состоянии “stale” (после revalidate) дольше, чем позволяет expire, Next.js больше не будет отдавать их мгновенно. Вместо этого он заблокирует ответ и заставит пользователя подождать, пока новые данные будут получены с сервера (динамический рендеринг).<br />
Защитный механизм от показа “совсем старых” данных. expire всегда должен быть больше revalidate.</p>
</li>
</ol>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Профиль</th>
<th>stale</th>
<th>revalidate</th>
<th>expire</th>
<th>Описание</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>'seconds'</code></td>
<td>30 сек</td>
<td>1 сек</td>
<td>1 мин</td>
<td>Для контента, который должен обновляться почти мгновенно.</td>
</tr>
<tr>
<td><code>'minutes'</code></td>
<td>5 мин</td>
<td>1 мин</td>
<td>1 час</td>
<td>Для часто обновляемого контента.</td>
</tr>
<tr>
<td><code>'hours'</code></td>
<td>5 мин</td>
<td>1 час</td>
<td>1 день</td>
<td>Для контента, обновляемого несколько раз в день.</td>
</tr>
<tr>
<td><code>'days'</code></td>
<td>5 мин</td>
<td>1 день</td>
<td>1 неделя</td>
<td>Для контента, обновляемого ежедневно.</td>
</tr>
<tr>
<td><code>'weeks'</code></td>
<td>5 мин</td>
<td>1 неделя</td>
<td>30 дней</td>
<td>Для контента, обновляемого еженедельно.</td>
</tr>
<tr>
<td><code>'max'</code></td>
<td>5 мин</td>
<td>30 дней</td>
<td>1 год</td>
<td>Для очень стабильного контента.</td>
</tr>
</tbody>
</table>
<p dir="auto">Важно: Если вы не укажете cacheLife, будет применен профиль ‘default’, который подходит для большинства случаев.</p>
<h3>включаем новый режим</h3>
<p dir="auto">Для активации новой модели необходимо добавить флаг <code>cacheComponents: true</code> в ваш файл next.config.ts. Это глобальный переключатель, который меняет поведение всего приложения:</p>
<pre><code class="language-typescript">// next.config.ts
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  cacheComponents: true,
}

export default nextConfig
</code></pre>
<h3>Используем “use cache”</h3>
<h4>На уровне файла (страницы)</h4>
<p dir="auto">Если поместить ‘use cache’ в самом верху файла, она применяется ко всем экспортируемым асинхронным функциям в этом файле. Это удобно для кэширования целой страницы или группы связанных функций.</p>
<pre><code class="language-typescript">// app/blog/page.tsx
'use cache'; // &lt;-- Директива на уровне всего файла

import { cacheLife } from 'next/cache';

// Эта функция тоже будет закэширована, так как она экспортируется и асинхронная
export async function getFeaturedPosts() {
  // fetch без дополнительных опций, т.к. кэшированием управляет директива
  const res = await fetch('https://api.example.com/featured-posts');
  return res.json();
}

// Основной компонент страницы — экспортируемая асинхронная функция
export default async function BlogPage() {
  cacheLife('hours'); // Устанавливаем время жизни кэша для всей страницы

  const posts = await getFeaturedPosts();

  return (
    &lt;main&gt;
      &lt;h1&gt;Блог&lt;/h1&gt;
      {posts.map((post) =&gt; (
        &lt;article key={post.id}&gt;{post.title}&lt;/article&gt;
      ))}
    &lt;/main&gt;
  );
}
</code></pre>
<p dir="auto">Важно: Если в этом же файле есть синхронные компоненты (например, function Sidebar()), они не попадают под действие ‘use cache’, потому что директива влияет только на асинхронные экспорты.</p>
<h4>На уровне компонента</h4>
<p dir="auto">В этом случае директива помещается внутрь тела асинхронного компонента. Она кэширует результат рендеринга этого конкретного компонента.</p>
<pre><code class="language-tsx">// app/components/ProductList.tsx
import { cacheLife, cacheTag } from 'next/cache';

export async function ProductList({ category }: { category: string }) {
  'use cache'; // &lt;-- Директива внутри компонента
  cacheLife('days');
  cacheTag(`products-${category}`); // Тег для точечной инвалидации

  const products = await fetch(
    `https://api.example.com/products?category=${category}`
  ).then((res) =&gt; res.json());

  return (
    &lt;div className="grid"&gt;
      {products.map((product) =&gt; (
        &lt;div key={product.id}&gt;{product.name}&lt;/div&gt;
      ))}
    &lt;/div&gt;
  );
}
Как использовать на странице:

tsx
// app/products/page.tsx
import { Suspense } from 'react';
import { ProductList } from '@/components/ProductList';

export default function ProductsPage() {
  return (
    &lt;div&gt;
      &lt;h1&gt;Товары&lt;/h1&gt;
      {/* Этот компонент будет закэширован */}
      &lt;ProductList category="electronics" /&gt;
      
      {/* А этот останется динамическим, так как не обёрнут в 'use cache' */}
      &lt;Suspense fallback={&lt;p&gt;Загрузка рекомендаций...&lt;/p&gt;}&gt;
        &lt;PersonalRecommendations /&gt;
      &lt;/Suspense&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<h4>На уровне функции</h4>
<p dir="auto">Этот подход позволяет кэшировать результат конкретной асинхронной функции, например, запрос к базе данных. Это полезно, когда одну и ту же функцию нужно использовать в нескольких местах без повторного выполнения.</p>
<pre><code class="language-typescript">// app/lib/data.ts
import { cacheLife, cacheTag } from 'next/cache';

// Кэшируемая функция получения данных
export async function getUserProfile(userId: string) {
  'use cache'; // &lt;-- Директива на уровне функции
  cacheLife('minutes');
  cacheTag(`user-${userId}`);

  console.log('Выполняется запрос к БД'); // Увидим только при первом вызове
  const user = await db.user.findUnique({ where: { id: userId } });
  return user;
}
</code></pre>
<p dir="auto">Использование в компонентах:</p>
<pre><code class="language-tsx">// app/profile/page.tsx
import { getUserProfile } from '@/lib/data';

export default async function ProfilePage() {
  const user = await getUserProfile('user-123'); // Кэшируется

  return (
    &lt;div&gt;
      &lt;h1&gt;Привет, {user.name}!&lt;/h1&gt;
      &lt;UserDetails user={user} /&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p dir="auto">Если getUserProfile вызвать ещё раз в другом компоненте на той же странице, запрос к БД не повторится — Next.js вернёт закэшированный результат.</p>
<h4><img src="https://forum.exlends.com/assets/plugins/nodebb-plugin-emoji/emoji/android/1f4a1.png?v=a9b928d4b2f" class="not-responsive emoji emoji-android emoji--bulb" style="height:23px;width:auto;vertical-align:middle" title="💡" alt="💡" /> Дополнительно: Комбинирование уровней</h4>
<p dir="auto">Вы можете комбинировать директивы. Например, страница закэширована целиком, но внутри есть функция, у которой свой собственный cacheLife.</p>
<pre><code class="language-tsx">// app/dashboard/page.tsx
'use cache'; // Кэшируем всю страницу

import { cacheLife } from 'next/cache';
import { getStats } from '@/lib/stats';

export default async function DashboardPage() {
  cacheLife('hours'); // Основное время жизни для страницы

  const stats = await getStats(); // Функция getStats может иметь свой 'use cache' и cacheLife

  return &lt;Dashboard stats={stats} /&gt;;
}
</code></pre>
<pre><code class="language-typescript">// app/lib/stats.ts
import { cacheLife } from 'next/cache';

export async function getStats() {
  'use cache';
  cacheLife('minutes'); // Этот кэш будет обновляться чаще, чем вся страница

  const res = await fetch('https://api.example.com/stats');
  return res.json();
}
</code></pre>
<p dir="auto">В этом случае общий HTML страницы будет жить по правилам hours, а данные из getStats — по правилам minutes, но они всё равно встроены в статический каркас страницы.</p>
<h3><img src="https://forum.exlends.com/assets/plugins/nodebb-plugin-emoji/emoji/android/1f6d1.png?v=a9b928d4b2f" class="not-responsive emoji emoji-android emoji--octagonal_sign" style="height:23px;width:auto;vertical-align:middle" title="🛑" alt="🛑" />  Подводные камни (Важно!)</h3>
<p dir="auto">Не все так гладко, просто так включить флаг и пользоваться скорее всего не выйдет, если вы не подготовили проект к такому переходу <img src="https://forum.exlends.com/assets/plugins/nodebb-plugin-emoji/emoji/android/1f921.png?v=a9b928d4b2f" class="not-responsive emoji emoji-android emoji--clown_face" style="height:23px;width:auto;vertical-align:middle" title=":clown_face:" alt="🤡" /></p>
<p dir="auto">Когда вы включаете cacheComponents в Next.js 16, фреймворк переходит к новой стратегии рендеринга — Partial Prerendering (PPR). В её основе лежит жёсткое требование: во время сборки (next build) должен быть сформирован мгновенно загружаемый статический “каркас” (static shell). Из-за этого асинхронное получение данных без <code>'use cache'</code> и без <code>&lt;Suspense&gt;</code> приводит к ошибке сборки <code>Uncached data was accessed outside of &lt;Suspense&gt;</code>.</p>
<p dir="auto">Причина ошибки: блокировка статического каркаса<br />
Раньше Next.js мог “подождать” данные и отдать готовую страницу (SSR), но с cacheComponents он всегда пытается сгенерировать статическую оболочку на этапе сборки.</p>
<p dir="auto">Проблема возникает, когда в компоненте есть асинхронный вызов (например, fetch или await params), который не может завершиться во время сборки и при этом не обрамлён. В этом случае сборка падает с ошибкой.</p>
<p dir="auto">Если фреймворк не знает, что показывать пользователю, пока данные грузятся (нет fallback из ), он не может собрать статический каркас. Это защита от “медленной” страницы, где пользователь видит белый экран до полной загрузки всех данных на сервере.</p>
<h4>Как исправить: два пути на выбор</h4>
<p dir="auto">У вас есть два варианта решения этой ошибки, в зависимости от ваших задач:</p>
<ol>
<li>
<p dir="auto">Закэшировать данные в статический каркас: Если данные меняются редко, их можно сделать частью мгновенно загружаемого каркаса. Для этого нужно добавить директиву <code>'use cache'</code> прямо в асинхронную функцию. Тогда данные будут получены на этапе сборки и закэшированы.</p>
</li>
<li>
<p dir="auto">Оставить данные динамическими, но с заглушкой: Если данные должны запрашиваться при каждом визите (персонализированная информация, часто меняющиеся данные), их нужно обернуть в <code>&lt;Suspense&gt;</code>. Это указывает Next.js оставить в статическом каркасе “заглушку” (fallback), а сами данные догрузить уже на клиенте в фоне.</p>
</li>
</ol>
<p dir="auto">( кейсы попробую подготовить далее в комментариях)</p>
<h3>Как это работает?</h3>
<h4>🧱 Статический каркас (Static Shell) — что это?</h4>
<p dir="auto">Когда вы включаете cacheComponents, Next.js перестаёт генерировать страницу целиком динамически на сервере по каждому запросу. Вместо этого он во время сборки (build) пытается создать каркас страницы — мгновенно загружаемый HTML, который видит пользователь в первую секунду.</p>
<p dir="auto">Внутри этого каркаса могут быть:</p>
<ul>
<li>Статический контент (заголовки, подвалы).</li>
<li>Закэшированные данные.</li>
<li>“Дырки” (Suspense Fallback) для тех данных, которые ещё не готовы.</li>
</ul>
<h4><img src="https://forum.exlends.com/assets/plugins/nodebb-plugin-emoji/emoji/android/2699.png?v=a9b928d4b2f" class="not-responsive emoji emoji-android emoji--gear" style="height:23px;width:auto;vertical-align:middle" title="⚙" alt="⚙" />️ Как именно кеш помогает отрисовать этот каркас?</h4>
<p dir="auto">Ответ кроется в том, в какой момент времени выполняется код.</p>
<p dir="auto">Без кеша (ошибка сборки)</p>
<pre><code class="language-tsx">// ❌ Ошибка при сборке
export default async function Page() {
  const data = await fetch('...'); // Запрос без 'use cache'
  return &lt;div&gt;{data}&lt;/div&gt;;
}
</code></pre>
<p dir="auto">Во время сборки Next.js запускает этот компонент.</p>
<p dir="auto">Он натыкается на await fetch. Стоп-машина. Потому что по новым правилам fetch по умолчанию динамический (no-store).</p>
<p dir="auto">Next.js не может выполнить динамический запрос во время сборки (в окружении CI/CD нет контекста пользователя, да и смысла нет — данные же должны быть свежими при каждом запросе).</p>
<p dir="auto">Next.js не знает, что рисовать в этом месте каркаса, и выбрасывает ошибку: “Я не могу собрать статику, потому что тут висит незавершенный асинхронный хвост”.</p>
<p dir="auto"><strong>С кешем (успешная сборка)</strong></p>
<pre><code class="language-tsx">// ✅ Успешная сборка
export default async function Page() {
  'use cache'; // &lt;-- Включаем кеш
  const data = await fetch('...');
  return &lt;div&gt;{data}&lt;/div&gt;;
}
</code></pre>
<ol>
<li>
<p dir="auto">Выполнение во время сборки: Директива <code>'use cache'</code> говорит фреймворку: "выполни этот <code>fetch</code> прямо сейчас, во время <code>npm run build</code> !!! ".</p>
</li>
<li>
<p dir="auto">Сохранение результата: Next.js делает запрос к API, получает ответ и сохраняет его в кеш (на диск или в CDN).</p>
</li>
<li>
<p dir="auto">Генерация HTML: Next.js берет полученные данные, рендерит их в HTML-строку </p><div>Данные из кеша</div> и вшивает этот HTML прямо в файл page.html.<p></p>
</li>
<li>
<p dir="auto">Результат: Пользователь, заходя на сайт, мгновенно получает готовую страницу с уже встроенным текстом “Данные из кеша”.</p>
</li>
</ol>
<h4><img src="https://forum.exlends.com/assets/plugins/nodebb-plugin-emoji/emoji/android/1f4a1.png?v=a9b928d4b2f" class="not-responsive emoji emoji-android emoji--bulb" style="height:23px;width:auto;vertical-align:middle" title="💡" alt="💡" />Если данные нужны свежие, но каркас тоже нужен?</h4>
<p dir="auto">Тут в игру вступает <code>&lt;Suspense&gt;</code> Он позволяет обмануть сборку.</p>
<pre><code class="language-tsx">// ✅ Сборка проходит, данные свежие
import { Suspense } from 'react';

async function FreshData() {
  const data = await fetch('...'); // Нет 'use cache'
  return &lt;div&gt;{data}&lt;/div&gt;;
}

export default function Page() {
  return (
    &lt;main&gt;
      &lt;h1&gt;Статический заголовок&lt;/h1&gt;
      &lt;Suspense fallback={&lt;div&gt;Загрузка данных...&lt;/div&gt;}&gt;
        &lt;FreshData /&gt;
      &lt;/Suspense&gt;
    &lt;/main&gt;
  );
}
</code></pre>
<p dir="auto">Как здесь помогает кеш? В этом примере кеша нет, но сборка всё равно проходит. Почему? Потому что  физически вырезает проблемный компонент FreshData из процесса статической сборки.</p>
<p dir="auto"><strong>Во время build:</strong></p>
<ol>
<li>
<p dir="auto">Next.js рендерит <code>&lt;h1&gt;Статический заголовок&lt;/h1&gt;</code>.</p>
</li>
<li>
<p dir="auto">Доходит до . Вместо того чтобы лезть внутрь FreshData, он просто записывает в HTML строку <code>&lt;div&gt;Загрузка данных...&lt;/div&gt;</code>(то, что в fallback).</p>
</li>
<li>
<p dir="auto">Каркас готов! FreshData при сборке не вызывается вообще.</p>
</li>
<li>
<p dir="auto">Когда пользователь открывает страницу, он видит “Загрузка…”, а React на клиенте (или сервере при стриминге) запускает FreshData, получает свежие данные и заменяет заглушку на реальный контент.</p>
</li>
</ol>
]]></description><link>https://forum.exlends.com/topic/2047/next-js-16-cachecomponents-pereuchivaemsya-keshirovat-primery</link><generator>RSS for Node</generator><lastBuildDate>Fri, 10 Apr 2026 21:53:02 GMT</lastBuildDate><atom:link href="https://forum.exlends.com/topic/2047.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 10 Apr 2026 07:08:56 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Next js 16+ cacheComponents, переучиваемся кешировать, примеры on Fri, 10 Apr 2026 08:44:01 GMT]]></title><description><![CDATA[<p dir="auto">Не то что переобулся, а в воздухе шнурки меняет - вот честно уже достало. Я конечно понимаю ИИ бустанул разработку, но с такой скоростью летать это пзд*ц какой-то</p>
]]></description><link>https://forum.exlends.com/post/2972</link><guid isPermaLink="true">https://forum.exlends.com/post/2972</guid><dc:creator><![CDATA[kirilljsx]]></dc:creator><pubDate>Fri, 10 Apr 2026 08:44:01 GMT</pubDate></item></channel></rss>