Пошук уроків, статей та іншого контенту
Перевірите конфігурацію, безпеку, спостережуваність і надійність застосунку перед релізом.
Перед production-релізом потрібно переконатися, що застосунок:
збирається в режимі production;
не розкриває секрети та зайву технічну інформацію;
правильно захищає HTTP-відповіді;
має зрозумілі логи й сигнали помилок;
коректно працює після перезапуску або часткового збою;
має план відкату та перевірені змінні середовища.
Чекліст не замінює автоматизовані тести, code review і перевірку інфраструктури. Його мета — не пропустити типові проблеми, які проявляються лише після деплою.
Запустіть локально ті самі команди, які використовує CI або сервер:
npm ci
npm run build
npm run startАбо відповідні команди для pnpm чи yarn.
Під час перевірки зверніть увагу на:
помилки TypeScript;
помилки ESLint, якщо вони блокують збірку;
невірні імпорти або шляхи до файлів;
використання змінних середовища, яких немає в production;
помилки під час prerendering статичних сторінок;
попередження про застарілі або некоректні налаштування Next.js.
next dev не є достатньою перевіркою. У production Next.js використовує інший процес збірки, кешування та виконання серверного коду.
Розділяйте змінні на серверні та публічні:
DATABASE_URL=postgres://...
SESSION_SECRET=...
NEXT_PUBLIC_API_URL=https://example.comЗмінні з префіксом NEXT_PUBLIC_ можуть потрапити до JavaScript-коду в браузері. Тому в них не можна зберігати:
паролі;
токени доступу;
секретні ключі;
рядки підключення до бази даних;
приватні URL внутрішніх сервісів.
Серверні секрети використовуйте лише у серверному коді. Не імпортуйте модулі з такими значеннями в Client Components.
Перевірте окремо:
чи всі необхідні змінні задані в production;
чи немає пробілів або лапок, які випадково стали частиною значення;
чи використовує середовище правильну базу даних;
чи не потрапив файл .env до репозиторію;
чи не виводяться значення змінних у логах або повідомленнях про помилки.
next.configУ конфігурації варто вимкнути зайву інформацію про технологію та додати базові HTTP-заголовки.
// next.config.mjs
const isProduction = process.env.NODE_ENV === "production";
/** @type {import("next").NextConfig} */
const nextConfig = {
// Не додаємо заголовок X-Powered-By: Next.js
poweredByHeader: false,
async headers() {
const headers = [
{
key: "X-Content-Type-Options",
value: "nosniff",
},
{
key: "Referrer-Policy",
value: "strict-origin-when-cross-origin",
},
{
key: "X-Frame-Options",
value: "DENY",
},
{
key: "Permissions-Policy",
value: "camera=(), microphone=(), geolocation=()",
},
];
// HSTS слід вмикати лише тоді, коли весь сайт працює через HTTPS
if (isProduction) {
headers.push({
key: "Strict-Transport-Security",
value: "max-age=31536000; includeSubDomains",
});
}
return [
{
source: "/(.*)",
headers,
},
];
},
};
export default nextConfig;Strict-Transport-Security повідомляє браузеру, що сайт потрібно відкривати лише через HTTPS. Не вмикайте його для домену, якщо HTTPS ще не налаштований для всіх потрібних піддоменів.
Політика Content-Security-Policy також важлива, але її не варто додавати навмання. Надто сувора політика може заблокувати скрипти Next.js, аналітику або зовнішні ресурси. Її потрібно формувати під конкретний застосунок і перевіряти в браузері перед увімкненням у production.
Перевірка доступу має виконуватися на сервері. Не покладайтеся лише на:
приховування кнопки в інтерфейсі;
перевірку ролі в Client Component;
значення, отримане з localStorage;
параметри URL, які користувач може змінити.
Для кожної операції, що змінює дані, перевіряйте:
хто виконує запит;
чи має користувач необхідну роль;
чи має він доступ саме до цього ресурсу;
чи валідні вхідні дані;
чи дозволена операція в поточному стані ресурсу.
Наприклад, користувач не повинен отримувати або змінювати замовлення лише тому, що змінив orderId у URL.
Валідація повинна виконуватися на сервері, навіть якщо форма вже перевіряється в браузері. Клієнтську перевірку можна обійти вручну сформованим HTTP-запитом.
Перевіряйте:
типи значень;
обов’язкові поля;
довжину рядків;
допустимий формат;
числові межі;
ідентифікатори ресурсів;
розмір і тип завантажених файлів.
Не передавайте довільні поля безпосередньо в запит до бази даних або ORM. Явно визначайте поля, які дозволено змінювати.
Для authentication cookies зазвичай потрібні такі властивості:
HttpOnly — JavaScript у браузері не може прочитати cookie;
Secure — cookie передається лише через HTTPS;
SameSite=Lax або суворіше значення, якщо це сумісно з логікою застосунку;
обмежений Path;
термін дії, що відповідає політиці сесій.
Також перевірте:
чи інвалідується сесія після виходу;
чи можна відкликати сесію після зміни пароля;
чи не містить cookie зайвих персональних даних;
чи не зберігаються токени в localStorage, якщо для них достатньо захищеної cookie.
Користувачеві показуйте загальне повідомлення:
Не вдалося виконати операцію. Спробуйте ще раз.
Не показуйте в production:
stack trace;
SQL-запити;
внутрішні шляхи файлової системи;
значення змінних середовища;
токени;
повні відповіді сторонніх сервісів.
Деталі повинні потрапляти до захищеної системи моніторингу, а не до браузера.
Production-логи мають допомагати відповісти на такі запитання:
коли сталася помилка;
у якому маршруті або операції;
який тип запиту виконувався;
який був результат;
чи можна пов’язати кілька записів з одним запитом.
Не записуйте в логи:
паролі;
cookies;
токени;
повні номери платіжних карток;
секрети;
зайві персональні дані.
Використовуйте структурований формат, наприклад JSON, якщо це підтримує середовище розгортання. Тексти на кшталт Something went wrong без контексту майже не допомагають під час діагностики.
Перевірте, що помилки:
не губляться без повідомлення;
мають достатній контекст;
групуються за типом;
містять URL або назву операції;
не дублюються десятками однакових записів;
не розкривають секрети.
Потрібно окремо перевірити:
помилки Server Components;
помилки Route Handlers;
помилки Server Actions, якщо вони використовуються;
помилки під час звернення до бази даних;
помилки сторонніх API;
помилки завантаження файлів.
Користувач повинен отримати зрозумілий стан помилки, а не нескінченне завантаження або порожню сторінку.
Для оркестратора або балансувальника корисний простий endpoint, який показує, що процес застосунку відповідає.
Для App Router файл може мати такий вигляд:
// app/api/health/route.ts
export async function GET() {
return Response.json(
{
status: "ok",
service: "web",
},
{
status: 200,
headers: {
"Cache-Control": "no-store",
},
},
);
}Такий endpoint перевіряє доступність процесу, але не обов’язково підтверджує, що база даних або всі зовнішні сервіси доступні. Глибші перевірки потрібно додавати обережно: health check не повинен створювати значне навантаження або змінювати дані.
Розділяйте:
liveness — процес працює;
readiness — застосунок готовий приймати трафік і залежності доступні.
Конкретна поведінка залежить від платформи розгортання.
Перевірте поведінку при:
тайм-ауті бази даних;
недоступності стороннього API;
повільній відповіді сервісу;
тимчасовій помилці мережі;
перевищенні ліміту запитів;
некоректній відповіді зовнішнього сервісу.
Не залишайте запит без тайм-ауту. Інакше один повільний сервіс може зайняти серверні ресурси на невизначений час.
Повторні спроби доречні лише для тимчасових помилок і мають бути обмеженими. Не повторюйте автоматично операції, які можуть виконатися двічі, наприклад створення платежу або замовлення, якщо для них немає захисту від дублювання.
Для кожної сторінки та API-відповіді визначте:
чи можна кешувати результат;
скільки часу він може бути застарілим;
хто має право його бачити;
як кеш буде інвалідований після зміни даних.
Особливо обережно працюйте з персоналізованими відповідями. Дані одного користувача не повинні потрапити до кешу, з якого їх отримає інший користувач.
Не додавайте довгий Cache-Control для відповіді лише тому, що це покращує швидкість. Спочатку переконайтеся, що дані справді безпечні для кешування.
Перед релізом визначте порядок дій:
створити резервну копію, якщо це потрібно для вашої бази даних;
застосувати сумісні зміни схеми;
розгорнути нову версію;
перевірити health check і ключові сценарії;
перевірити логи та метрики;
за потреби виконати відкат.
Зміни бази даних мають бути сумісними з версіями застосунку, які можуть працювати одночасно під час розгортання. Небезпечно спочатку видаляти колонку, яку ще використовує стара версія застосунку.
Заздалегідь підготуйте:
попередню стабільну версію;
спосіб швидкого перемикання на неї;
процедуру відкату міграцій або відновлення резервної копії;
відповідального за рішення про rollback.
Перед релізом перевірте застосунок у production-подібному середовищі.
головна сторінка відкривається без помилок;
неавторизований користувач не бачить приватні сторінки;
вхід і вихід працюють;
сесія не зникає після звичайної навігації;
користувач не може отримати чужі дані;
форми показують помилки валідації;
успішні зміни відображають актуальні дані;
помилка сервера має зрозумілий вигляд;
завантаження сторінок не зависає назавжди;
мобільний і десктопний сценарії працюють.
У DevTools перевірте:
відсутність помилок у Console;
відсутність невдалих запитів у Network;
коректні статус-коди;
cookies з потрібними атрибутами;
відсутність секретів у відповідях;
наявність security headers;
відсутність mixed content;
коректне завантаження шрифтів, зображень і скриптів.
Одразу після релізу перевірте:
health check;
основний маршрут;
вхід користувача;
одну операцію читання;
одну операцію зміни даних;
логи;
помилки та latency;
використання CPU, пам’яті й мережі;
підключення до бази даних.
Не вважайте деплой завершеним лише тому, що платформа повідомила про успішну збірку.
NEXT_PUBLIC_Якщо секретна змінна має префікс NEXT_PUBLIC_, вона може стати доступною клієнтському коду. Перейменування змінної в конфігурації недостатньо — потрібно також перевірити вже зібраний JavaScript.
Прихована кнопка не захищає операцію. Користувач може викликати endpoint безпосередньо. Авторизацію потрібно перевіряти в серверному коді, який виконує операцію.
Після ввімкнення HSTS браузер запам’ятовує вимогу HTTPS. Не використовуйте цей заголовок на домені, де HTTPS ще не працює стабільно.
Stack trace у відповіді полегшує зловмиснику пошук слабких місць і часто містить внутрішні дані. Клієнту повертайте безпечне повідомлення, а деталі зберігайте в системі моніторингу.
Запит до зовнішнього сервісу без тайм-ауту може довго займати ресурси сервера. Для кожної мережевої залежності перевірте максимальний час очікування та поведінку після нього.
Кешування персоналізованої сторінки або API-відповіді може призвести до витоку даних між користувачами. Спочатку класифікуйте відповідь, а вже потім налаштовуйте кеш.
Зміна схеми бази даних може бути незворотною. Перед релізом перевірте, як повернути попередню версію застосунку і що робити з уже зміненими даними.
Перед production-релізом Next.js-застосунку:
виконайте production-збірку та запустіть її локально;
перевірте змінні середовища й не публікуйте секрети;
налаштуйте базові security headers;
перевіряйте авторизацію та вхідні дані на сервері;
захистіть cookies і сесії;
не розкривайте внутрішні помилки користувачам;
налаштуйте логи, моніторинг і health check;
перевірте тайм-аути та поведінку зовнішніх залежностей;
переконайтеся, що кеш не розкриває приватні дані;
підготуйте сумісні міграції та план відкату;
після деплою перевірте ключові сценарії, а не лише статус збірки.