Сучасныя можнасці Next.js Mapped: што заменяе кожная з іх функцый і калі яе вжываць
Экскурсія па восьмі можлівасцях Next.js, ад серверных компанентаў да API для метадаў, якая паказвае, калішніяя старыя патэрны заменяюцца кожнай з іх і дзе гэта можа стварыць проблемы.
Next.js зараз карае рутаванне, запошук дадзейнаў, кэшаванне, стратэгію атрыбутавання і большую частку API-функцыяў. Аднак команды часта яго адмацоўваюць і застаюцца пры старых прычынках: запошук дадзейнаў у useEffect, ручная наработка API-маршрутаў для кожнай формы, правілы кэшавання, якія ніхто не можа поясніць. Шырокі практычны нараддзе раскрывае восьмі ключовыя можлівасці, старыя падходы, якія яны заменяюць, і деталі, якія ствараюць проблемы ў рэальных проектах, тады вы зможаце практычна для кожнай функцыі адлучыць, што патрабуецца ў вашай базе кода.
Чаму фрэймворк зараз карае весь цікл разработкі
Walmart, Nike, TikTok, OpenAI і Airbnb адмацоўваюць веб-прыемлі на Next.js, і галоўная перавага — адзінство: рутаванне, зборка кода, способы атрыбутавання, доступ да дадзейнаў і серверныя канцэнтры разделяюць аднойчы репазітарый і аднаковыя стандарты. Выбор рутера і налаштаванне збарачвальніка больш не ўскладняюць пачатак проекта, таму час перакідаецца на сам продукт.
1. Компаненты сервера робяць сервер стандартным месца для атрыбутавання
React Server Components (RSC) — гэта самая значныя архітектурная змена ў гэтым спісе. Компанент сервера выконваецца толькі на сервере і надае атрыбутаваны выхід браузеру, таму яго код ніколі не стае часткаю пакета JavaScript кліента.
Што зникае з стороннім дадзенням наполненыя сторунки
У класычным React, які атрыбутуецца на кліянцы, нават компанент, який толькі чытае дадзенні і выводзіць спіс, дадае свой код, логіку запрашэння дадзенняў і свае залежнасці ў пакет, а потым запускаецца ў браузеры. З RSC компанент чытае дадзенні на сервере і надае толькі рэзультат. У App Router кожны компанент є компанентам сервера, якщо толькі вы не заявіце іншае, таму файл падаў някіх дырэктываў не трэбуе:
// app/products/page.tsx
// This component runs ONLY on the server. No "use client" directive needed.
Старонка ўособліва async функцыя, яка безпосередньа запрашвае базу дадзеных і вяртае маркап. Не існуе жадных API-шляхоў або запытак з боку кліента:
import { db } from "@/lib/db";export default async function ProductsPage() {
// Direct database access. No API route. No fetch boilerplate.
const products = await db.product.findMany({ take: 20 }); return (
<main>
<h1>Our Products</h1>
<ul>
{products.map((product) => (
<li key={product.id}>
<h2>{product.name}</h2>
<p>${product.price}</p>
</li>
))}
</ul>
</main>
);
}
Няма useState, няма useEffect, няма флага загрузкі, няма fetch да сэрвера. У браузеры запускаецца менш коду, HTML прыходзіць цэлым (чаму добра для пошуковых сяржысоў), і ёсць менш таго, што трэба падтрымваць. Паколькі гэты код безпасередньа з’яўляецца ў базе дадзеных, ніколы не імпортуйце яго ў файл кліента; модуль дадзеных, прызначаны толькі для сервера, чыста паказвае гэтыя межы.
Дзе яшчэ патрэбны кліентскія компоненты
Вам яшчэ патрэбны кліентскія компоненты для всього інтэрактыўнага: працоўнікі запытак, стан, эфекты і API браузера, такія як localStorage. Такі файл пазначаецца за дапамогою дырэктывы "use client" у верхней частцы:
// components/AddToCartButton.tsx
"use client";
Кнопка, яка знаходзіцца нижчэ, зберагае частку локальнага стану і реагуе на клікі, што якраз ёсць тыя дзеянні, якія павінны выконввацца ў браузеры:
import { useState } from "react";export function AddToCartButton({ productId }: { productId: string }) {
const [added, setAdded] = useState(false); return (
<button onClick={() => setAdded(true)}>
{added ? "Added!" : "Add to Cart"}
</button>
);
}
Пачніце з серверных компанентоў і перайшыце на іншы формат толькі там, дзе цэга якась інтерактыўнасці, выкорыстоўваючы "use client" якомога далей у іерархіі: сторонняя сторынка, якая включае адну маленькую кліентскую кнопку, выкарыстоўвае значна менш JavaScript, чым сторонняя сторынка, якая ўжо з самага пачатку ёсць кліентскім компанентам. Чырпнуць глэбачэ за тым, як працюе модель атрыбутавання пад капотам, можна за лінкам архітектура атрыбутавання без выкарыстоўвання бандліва.
2. Дзеянні сервера заменяюць маршруты API для выканання змін
Server Actions дазваляюць напісаць функцыю, яка выконваецца на сервере, і вызваць яе безпосередна з компонента. Next.js генеруе HTTP-канцэнтр, серыялізуе аргументы і вяртае рэзультат, таму вам больш не трэба падтрымваць окольны маршрут толькі для прыймання даных з формы.
Шаблон з двума файламі, які ён заменяе
Раней для выконання змэны быў неабходны хэндлер у папцы api роутера Pages, який чытаў тэла запиту, збірваў даныя ў базе дадзенаў і адпавідаў у формате JSON:
// You needed an API route
// pages/api/create-post.ts
export default async function handler(req, res) {
const { title, content } = req.body;
await db.post.create({ data: { title, content } });
res.status(200).json({ success: true });
}
Потым компонент павінен быў ручна вызваць гэты канцэнтр, сам ствараючы серыялізаваны пакет дадзенаў:
// Then in your component:
const response = await fetch("/api/create-post", {
method: "POST",
body: JSON.stringify({ title, content }),
});
Акцыя, якая пераверана, і якая знаходзіцца разам з формай
За дапамогою Server Actions стораніца імпортуе все, што ёй трэба, укладаючы ў тое ж Зод для пераверання вхідных дадзенаў:
// app/posts/new/page.tsx
import { redirect } from "next/navigation";
import { db } from "@/lib/db";
import { z } from "zod";
Дзеянне прызначаецца ляжачы ў кантэксте формы. Дыректыва "use server" у тэле функцыі пазначае яго як код, доступны толькі на серверы; форма перадае яго ў атрыбут action. Дзеянне перавершае даныя типу FormData за дапамою функціі safeParse, якщо перавершэнне не ўспіваецца — вяртае паведамленні пра адміністрацыю полей, а інакш пісае даныя пасляавталенняў і перакідае на іншую сторону:
const schema = z.object({
title: z.string().min(3, "Title must be at least 3 characters"),
content: z.string().min(10, "Content is too short"),
});async function createPost(formData: FormData) {
"use server"; const parsed = schema.safeParse({
title: formData.get("title"),
content: formData.get("content"),
}); if (!parsed.success) {
return { error: parsed.error.flatten().fieldErrors };
} await db.post.create({ data: parsed.data });
redirect("/posts");
}export default function NewPostPage() {
return (
<form action={createPost}>
<input name="title" placeholder="Post title" required />
<textarea name="content" placeholder="Write something..." required />
<button type="submit">Publish</button>
</form>
);
}
Перавершэнне є неабходным, таму што дзеянне на серверы ўжо є публічным канцэнтрам, які можа вызваць будзь-хто з даколькіма данымі. З той жа разу перакананні ў правах таксама павінны знаходзіцца ў самай функцыі дзеяння; прычыны, чаму дзеяння на серверы патрабуюць перакананняў у правах у кожным тэле функцыі детальна распрацоўваюць гэта. Таксама зазначыце, што тут нічога не чытае вярнуты об’ект з адміністрацыяю, таму пра брак перавершэння нічога не паказваецца. Наступны патэрн гэта выправляе.
Адказы пра бягі і статус «чакаецца» з useActionState
Калі форма павінна адказваць на прытакання данных або выключыць кнопку па час обработкі запиту, перакладзіце форму ў кліентскі компонент і абгорніце дзейства за дапамою хука React useActionState:
"use client";
Хук вяртае найсвежэйшы статус, утвораны дзействам, абгорнуты formAction для перадачы форме, а таксама флаг isPending. Компонент адразу паказвае першыя адказы пра кожнае поль і зменяе тэкст кнопкі па час обработкі запиту:
import { useActionState } from "react";
import { createPost } from "./actions";export function PostForm() {
const [state, formAction, isPending] = useActionState(createPost, null); return (
<form action={formAction}>
<input name="title" placeholder="Post title" />
{state?.error?.title && (
<p className="text-red-500">{state.error.title[0]}</p>
)}
<textarea name="content" placeholder="Write something..." />
{state?.error?.content && (
<p className="text-red-500">{state.error.content[0]}</p>
)}
<button type="submit" disabled={isPending}>
{isPending ? "Publishing..." : "Publish"}
</button>
</form>
);
}
Дзеянне, якое частаючы выклікае плутанне: калі дзеянне выкорыстоўваецца через useActionState, React вызывае яго з пярэднім станам як першым аргументам і FormData як другім. Функцыя createPost, показаная ранейш, прыймае толькі formData, таму версія, якая экспортуецца з ./actions для гука, патрэбна з сігнатурой (prevState, formData). Дзеянне таксама павінна знаходзіцца ў окремым файле з "use server" у верхней частцы, таму што кліентскі компонент не можа визначаць функцыі сервера безпосередна.
3. Turbopack скарочвае цыкл адзывнасці пад час разработкі
Дзеўнаць гадоў webpack быў лідерам у процесе локальнага развіцця. Функцыя Fast Refresh была выгодной, калі сервер працаваў, але запуск вялікіх прыложэнняў з нуля могаў займаць 30–60 секунд. Turbopack — это бандлер на базе Rust ад Vercel, створаны для усунення гэтага бар’еру.
Turbopack пасягнуў 100% рэштацыі ў всіх 8,298 тэстаў інтеграцыі з Next.js, а команды паведамляюць, што час запуску прыложэнняў з нуля становіць менейш 3 секунды ў проектах, якім ранейш трэбавалася больш за хвіліну. Його ранг готовасці шыбка зміняецца между выпускамі, таму неабходна пераканацца ў актуальных інструкцыях па його статусе ў вашай версіи, у чымасці паўтарных запускаў у працэсе розработы.
Увёмкнэнне
Ёсць адзіны параметр у скрыптэ для развіцця, які дазволяе ўвёмкнуць гэту функцыю:
// package.json
{
"scripts": {
"dev": "next dev --turbopack",
"build": "next build"
}
}
Няма патрэбы ў дадатковай наладцы. Turbopack выконвае роботу пошагова, перзначаючы толькі тое, што зменілася, таму большыя проекты отрымаюць наібольшую выгоду. Якщо вы павяржаецеся на спецыяльныя кантэйнеры webpack або плагіны, спачатку пераканайцеся ў наявнасці адпаведных варыянтов у Turbopack. Наша параболіка кантэйнероў рассказвае пра гэтыя варыянты.
4. Частковая прадзейсвоўка спалучае статычную шэлку з дадзеннямі, якія передаюцца прайом
Частковая прадзейсвоўка (PPR) негаразду падае ўжо створаную статычную шэлку HTML і прайом передае дынамічныя часткі той самай сторанцы, усё гэта ў межах адной адпаведзі.
На сторанцы продукту лейаут, навігацыя і апісанне застаюцца однаковымі для всіх; персоналізаваная цена, кошык і колькасць залягоў не ўнізі. PPR адразу падае шэлку і запоўняе часткі, якія патрабуюцца кожнага запиту, калі гэтыя часткі становяцца доступнымі.
Старонка імпортуе адну статычную складовую і два дынамічныя:
// app/product/[id]/page.tsx
import { Suspense } from "react";
import { ProductDetails } from "./ProductDetails"; // static
import { PersonalizedPrice } from "./PersonalizedPrice"; // dynamic
import { StockStatus } from "./StockStatus"; // dynamic
Граніца межы статычных і дынамічных элементаў пазначаецца за дапамою Suspense. Всё, што знаходзіцца за граніцай, можа быць прадрукавана заздалегідь; кожны элемент Suspense стае заместнікам у шэле, які заменяецца, калі його дзеціны элементы завершаюць прадрукаванне на сервере:
export default function ProductPage({ params }: { params: { id: string } }) {
return (
<div>
{/* This renders statically - instant */}
<ProductDetails id={params.id} /> {/* These stream in dynamically */}
<Suspense fallback={<div>Loading price...</div>}>
<PersonalizedPrice productId={params.id} />
</Suspense> <Suspense fallback={<div>Checking stock...</div>}>
<StockStatus productId={params.id} />
</Suspense>
</div>
);
}
Заўважыце, што params тут задаецца як звычны об’ект. У новейшых версіях Next.js params пасылаецца як Promise і трэба на яго чакаць, таму паспрабуйце прыстосаваць сінтаксіс да версіі, якую вы вядомаеце.
Функцыя PPR была адкрытая за дапамою эксперыментальнага флажка ў налашчэннях Next.js, пачынаючы з імпорту типаў:
// next.config.ts
import type { NextConfig } from "next";
а потым сам флажок:
const nextConfig: NextConfig = {
experimental: {
ppr: true,
},
};export default nextConfig;
У момент напісання цього тексту гэты флаг быў перарганізаваны ў новейшых версіях (працэс PPR аўтаматычна прыяўляецца да настройкі Cache Components у Next.js 16), таму спрыймайце гэты фрагмент як ілюстрацыю та пераканайцеся ў актуальнай назве опцыі. У будзь-якім случае сторанка здаецца статычной, таму што ўсё ее зместа кэшуецца, а даны застаюць актуальнымі. Больш дакладна мы розглядаем гэты механізм у статті «Чым є частковая прадзеявка та паралельная дзеявка».
5. Дырэктыва use cache робіць кэшаванне явным
У Next.js 13 та 14 кэшаванне было актыўнае за замовчаннем, і багато командаў знаходзілі застарэлыя сторанкі ў працоўнай среде без явных прычын. Next.js 16 пераходзіць да кэшавання за жаданнем за дапамогою Cache Components та дырэктывы use cache: вы самі вказываеце, што трэба кэшаваць, замест таго каб здогадваліся, што вже кэшуецца.
Размішчання дырэктывы ў верхней частцы асінхроннага компанента кэшуе яго вырадзаны выхід:
// A component that caches its output for 1 hour
async function PopularArticles() {
"use cache";
Рэшта компанента запрашоўвае і вырадзае тыпова:
const articles = await fetch("https://api.example.com/popular-articles").then(
(r) => r.json()
); return (
<ul>
{articles.map((article: { id: string; title: string }) => (
<li key={article.id}>{article.title}</li>
))}
</ul>
);
}
У каментары згадваецца адна гадзіна, але сама дырэктыва не задае трымкі; трымкі вылучаюцца з профілю кэшу, прыкладзенага за дапамою cacheLife, а якщо гэта немагчыма — выкарыстоўваецца стандартны профіль. Адзінаковыя профілі прызначаюцца ў налашчаннях:
// next.config.ts
const nextConfig = {
experimental: {
cacheLife: {
"stale-for-a-day": {
stale: 60 * 60, // 1 hour
revalidate: 60 * 60 * 24, // 1 day
expire: 60 * 60 * 24 * 7, // 1 week
},
},
},
};
Трыя значэння адпаведнаюць разным запытам. stale — гэта час, пры якім кліент можа выкарыстоўваць свой копію без пераканальвання сервера, revalidate — гэта частота, з якою сервер апштучвае ентры на фоне, а expire — гэта момент, пасля якога ентры адбраковуюцца і наступны запыт павінен чакаць на свежыя даны. Тое, чы рэгламент cacheLife належыць да категоріі experimental, залежыць ад вашай версіі. Чэрз бакаўкаванне на адпаведных тагах, якое патрэбнае, калі змянююцца даны пад час запісу, адзірніце наша інструкцыю па выкарыстоўванні кэшу і бакаўкавання на адпаведных тагах.
6. Функцыі стрімавання AI з AI SDK
Vercel AI SDK інтэгруецца з Route Handlers і React hooks, таму стрімаванне чату, пошук за дапамогою AI і стваранае UI стаюць звычным кодам прыкладнай програмы.
На сервере працюе обробнік маршрута, який імпортуе streamText і падрэбнік модэля:
// app/api/chat/route.ts
import { streamText } from "ai";
import { openai } from "@ai-sdk/openai";
Обробнік POST чытае спілкуванне з тэла запиту, пачынае стрімаванне і вяртае яго як стрімованы адказ (заканчоўка клявіцы функцыі вырвана ў адлінку):
export async function POST(req: Request) {
const { messages } = await req.json(); const result = streamText({
model: openai("gpt-4o"),
messages,
}); return result.toDataStreamResponse();
На кліянцы сторанка чату ёсць Кліентскім компонентам, таму што ён зберагае стан вводу:
// app/chat/page.tsx
"use client";
Хук useChat керуе спісам паведамленняў, значэннем вводу і ўсылкай даных, а таксама перзначае відображэнне, калі прыходзяць новыя токены:
import { useChat } from "ai/react";export default function ChatPage() {
const { messages, input, handleInputChange, handleSubmit } = useChat(); return (
<div>
<div>
{messages.map((m) => (
<div key={m.id}>
<strong>{m.role}:</strong> {m.content}
</div>
))}
</div>
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} placeholder="Ask anything..." />
<button type="submit">Send</button>
</form>
</div>
);
}
Для стрімінгаваг чату трэба прыблізна 30 ліній коду: ёсць Route Handler у бэкендзе і useChat у фронтэндзе. Зважайце, што API AI SDK быстра зміняецца: у новыях мэйновых версіях хук імпортуецца з @ai-sdk/react, стан вводу керуецца самім разработчыкам, а памагальнік для адпаведзей мае іншую назву. Зафіксавайце версіі і пераканаўцеся ў дасведчэннях SDK пры копіюванні гэтага коду. Па інфармацыям пра інтэрфейсы у стылі агента з інструментамі та калькамі спаглядзень, адгледзіце як ствараць UI для багатакальковых AI-агентаў з Next.js і AI SDK.
7. Шаблоны App Router для сложных лейаутаў
App Router, які быў адкрыты ў Next.js 13, зараз ёсць стандартным спосабам стварэння дапраўкі Next.js. Два з ягоя функцыяй заменяюць тое, што раней казалося неабходнае для самастайнага керування станам.
Паралельныя маршруты для незалежных панелей дашборда
Паралельныя маршруты адразу прадстаўляюць калькі сторанак у ўзеўме лейауте. Кожны папака, прызначаная з @, визначае імёваны слот:
app/
dashboard/
@analytics/
page.tsx
@recent/
page.tsx
layout.tsx
page.tsx
Лейаут прыме кожны слот як параметр разам з children і размешчае іх у сеткі:
// app/dashboard/layout.tsx
export default function DashboardLayout({
children,
analytics,
recent,
}: {
children: React.ReactNode;
analytics: React.ReactNode;
recent: React.ReactNode;
}) {
return (
<div className="grid grid-cols-3 gap-4">
<div className="col-span-2">{children}</div>
<aside>
{analytics}
{recent}
</aside>
</div>
);
}
Паколькі кожны слот ёсць самастоятельным сегментам маршруту, ён завантажвае свае сабе вялікі даны і можа мець свае сабе станы завантажэння і адказу. Медленны запит да аналітыкі не спрачывае панель няўзабавных дзейнасцей. Аднаковая проблема: калі вы перайдзеце на падмаршрут, які слот не визначае, Next.js патрэбуе файл default.tsx у тым слоте, каб знать, што прадстаўляць пад час перзавантажэння.
Перехопленне маршрутаў для модалных вікнаў з рэальнымі URL
Звычны патэрн інтарфейса ачыяе элемент у модальным вікні, паказваючы адпаведную URL, тады яго можна будзе выкорыстоўваць для аднароднай дзялення. Рэгулюванне маршрутаў адбываецца за дапамою правіл папак:
app/
photos/
[id]/
page.tsx // Full page view at /photos/123
(..)[id]/
page.tsx // Intercepted modal view
page.tsx
Калі корыстнік клікае з сеткі, папка-перехоплювач ловіць навігацыю з боку кліента і атрыбутуеяе модальную версію. Калі хтось ачынае URL безпосередня або адновае стораніцу, атрыбутуеяецца звычная цэлая стораніца, без якіх-лебе ручных трох. Маркеры (.), (..) і (...) адносуюцца да сегментаў маршрута, а не да папак файловай системы, і модальна версія зазвычай атрыбутуеяецца через паралельны слот @modal; таму пераканайцеся, што у документах па маршрутуванні є інфармацыя пра точную структуру, якая вам патрэбна.
8. Аднойчыны SEO: метаданы і з’явы
API для метадаў ператварае SEO на звычны код, які знаходзится праза сторанай, яку ён описвае. Пасля імпорту типу Metadata:
// app/blog/[slug]/page.tsx
import type { Metadata } from "next";
сторана выклікае generateMetadata, який завантажвае пасоў і вяртае заглавле, апісанне, даны Open Graph і карточку Twitter:
export async function generateMetadata({
params,
}: {
params: { slug: string };
}): Promise<Metadata> {
const post = await getPost(params.slug); return {
title: post.title,
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
images: [{ url: post.coverImage }],
type: "article",
},
twitter: {
card: "summary_large_image",
title: post.title,
description: post.excerpt,
images: [post.coverImage],
},
};
}
Прыклады сторанак у соціальных сетях, канонічныя URL-адрэсы і структураваныя даны беруцца з тых сабеў дадзенняў, якія адрасавае сторана. Якщо компонент стораны таксама выклікае getPost, трэба усунуць дуплікацыю запитоў (напрыклад, за дапамогою cache у React), каб база дадзеных не была запытана два разы.
Для адобразавання аўтарафактаў слічна выкорыстоваць next/image:
import Image from "next/image";
По замовчэнню ён адпрацоўвае з запазджэнням, выдае варіянты правильных размараў і перакладае зображэння у формат WebP або AVIF, калі браузер іх падтрымляе. Актыўнае заданне значэння width і height таксама звільняе прастор і запобегае змянам у макете:
export function ProductCard({ product }: { product: Product }) {
return (
<div>
<Image
src={product.imageUrl}
alt={product.name}
width={400}
height={300}
priority={false} // set true for above-the-fold images
/>
<h2>{product.name}</h2>
</div>
);
}
Значэнне priority трэба задаць як true толькі для зображэння, якае відразу видна на экране, зазвычай галоўнага зображэння або зображэння главнага продукту, ў такі спосаб браузер зможа яго завантажыць раней.
Розумны порядак навучэння
Кожны наступны крок будуе на попераднім:
- Стандарты іменавання файлаў у App Router:
layout.tsx,page.tsx,loading.tsxіerror.tsx. - Server Components і месца, дзе знаходзіцца межа кліента.
- Server Actions з атрыбутам Zod для верыфікацыі кожных змян.
- Suspense і стрімінг для задання статуса завантажэння.
Галоўныя выводы
- Спрытывайце сервер як стандартны механізм выконання і прыкладвайце
"use client"да самых маленькіх інтэрактыўных элементаў. - Дзеяння сервера ёсць канцэнтры выконання: пераканаўваеце вхідныя даны і пераглядаеце правыя ў кожнам з яных.
- Адрэсавайце статычныя і дынамічныя межы за дапамойкай
Suspense; PPR і кэшаванне будуць ствараныя на ўсходзе яных. - Валідзіруйце кэшаванне за дапамойкай
use cacheі апранаваных профіляўcacheLifeзамест таго, каб паслужыцца стандартамі. - Большая частка гэтых API зменілася межы недзеўнімымі выданнямі, таму парабяльвайце флагі і падпісы ў спаўнасці з версіяй, якая насправды вы карыстаецеся.
Незалежна ад таго, чы вы пачынайце з нуля, чы мігруйце большую аплікацыю да App Router, прыемка гэтых элементаў по аднаму ёсць спосабом з мінімальным рызыкам.
Спадні матэрыялы
- 20 прыглыдных шаблонаў Next.js 16 для архітэктуры прыстаноўак высокага рангу — Апіс падходаў, заснованых на сервере, кэшаванні, стрімінгу, PPR, паралельных і перехопляючых маршрутах, а таксама іншых шаблонаў для стварэння масштабавальных прыстаноўак на Next.js 16.
- Розумеўце кэшовыя компаненты і частковае прадзействаванне ў Next.js 16.3 — Паспяшнае поясненне таго, як функцыя Instant Navigations у Next.js 16.3 выкарыстоўвае спяльныя шэлі маршрутаў і чысткія рашэння ўзгалджвання дадзеных, каб прыстаноўкі, выкарыстоўваюць сервер для адрасавання, работалі мгновенна.