Deployment
Next.js Deployment — ракета на стартовому майданчику готова до запуску в ранковому світлі
Це фінальний урок не тільки блоку Next.js, але й всього курсу. Ми пройшли шлях від командного рядка до повноцінного фреймворку. Тепер навчимося робити останній, але найважливіший крок -- вивести проект у світ. Адже код, який ніхто не бачить -- це просто хобі. Код, який працює на сервері -- це продукт.
npm run build -- збірка проекту
Перш ніж деплоїти, потрібно зібрати проект:
npm run build — збірка Next.js з таблицею маршрутів
npm run build
Next.js покаже детальний звіт:
Route (app) Size First Load JS
┌ ○ / 5.2 kB 87.3 kB
├ ○ /about 1.8 kB 83.9 kB
├ ● /blog 3.1 kB 85.2 kB
├ ● /blog/[slug] 2.4 kB 84.5 kB
├ ○ /contact 4.1 kB 86.2 kB
└ λ /api/users 0 B 0 B
○ (Static) prerendered as static content
● (SSG) prerendered as static HTML (uses generateStaticParams)
λ (Dynamic) server-rendered on demand
Символи:
○Static -- повністю статична сторінка●SSG -- статична з даними (generateStaticParams)λDynamic -- серверний рендеринг при кожному запиті
Звертай увагу на First Load JS -- це розмір JavaScript, який завантажує браузер. Тримай його якомога менше. Якщо сторінка важить більше 200 КБ -- час оптимізувати.
Перевірка локально
npm run build && npm start
Це запустить production-сервер на http://localhost:3000. Перевір, що все працює перед деплоєм!
Environment Variables
Секретні ключі та налаштування зберігаються в змінних оточення:
Файли .env
# .env.local -- тільки локально (в .gitignore!)
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb
API_SECRET_KEY=super-secret-key
# Змінні з NEXT_PUBLIC_ доступні в браузері
NEXT_PUBLIC_API_URL=https://api.example.com
NEXT_PUBLIC_SITE_NAME=Мій сайт
Серверні vs клієнтські змінні
| Префікс | Доступність | Приклад |
|---|---|---|
| Без префікса | Тільки сервер | DATABASE_URL, API_SECRET |
NEXT_PUBLIC_ | Сервер + браузер | NEXT_PUBLIC_API_URL |
// Server Component або API route -- доступні ВСІ змінні
const dbUrl = process.env.DATABASE_URL; // ✅
// Client Component -- тільки NEXT_PUBLIC_
const apiUrl = process.env.NEXT_PUBLIC_API_URL; // ✅
const dbUrl = process.env.DATABASE_URL; // ❌ undefined
НІКОЛИ не додавай .env.local в Git! Секретні ключі повинні бути тільки на сервері. У .gitignore вже має бути рядок .env*.local.
Пріоритет файлів
.env -- базові значення (в Git)
.env.local -- локальні override (НЕ в Git)
.env.development -- тільки для npm run dev
.env.production -- тільки для npm run build/start
SEO та Metadata
generateMetadata для динамічних сторінок
// src/app/blog/[slug]/page.tsx
import type { Metadata } from "next";
interface Post {
title: string;
description: string;
image: string;
}
async function getPost(slug: string): Promise<Post> {
// Отримання даних
return { title: "Мій пост", description: "Опис", image: "/og.jpg" };
}
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>;
}): Promise<Metadata> {
const { slug } = await params;
const post = await getPost(slug);
return {
title: post.title,
description: post.description,
openGraph: {
title: post.title,
description: post.description,
images: [{ url: post.image, width: 1200, height: 630 }],
},
twitter: {
card: "summary_large_image",
title: post.title,
description: post.description,
},
};
}
robots.txt
// src/app/robots.ts
import type { MetadataRoute } from "next";
export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: "*",
allow: "/",
disallow: ["/api/", "/admin/"],
},
sitemap: "https://mysite.com/sitemap.xml",
};
}
sitemap.xml
// src/app/sitemap.ts
import type { MetadataRoute } from "next";
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const posts = await getAllPosts();
const postUrls = posts.map((post) => ({
url: `https://mysite.com/blog/${post.slug}`,
lastModified: post.updatedAt,
changeFrequency: "weekly" as const,
priority: 0.8,
}));
return [
{
url: "https://mysite.com",
lastModified: new Date(),
changeFrequency: "yearly",
priority: 1,
},
{
url: "https://mysite.com/about",
lastModified: new Date(),
changeFrequency: "monthly",
priority: 0.5,
},
...postUrls,
];
}
async function getAllPosts() {
return [
{ slug: "hello", updatedAt: new Date() },
{ slug: "nextjs", updatedAt: new Date() },
];
}
Деплой на Vercel
Vercel -- це платформа від творців Next.js. Деплой максимально простий:
1. Підключи GitHub репозиторій
- Зайди на vercel.com та створи акаунт (через GitHub)
- Натисни "New Project"
- Обери свій GitHub репозиторій
- Vercel автоматично визначить Next.js проект
2. Налаштуй environment variables
В налаштуваннях проекту на Vercel додай всі змінні з .env.local:
DATABASE_URL = postgresql://...
API_SECRET_KEY = ...
NEXT_PUBLIC_API_URL = https://api.example.com
3. Деплой!
Натисни "Deploy" -- і через хвилину твій сайт доступний за URL виду my-app.vercel.app.
Автоматичний деплой: кожен push в main автоматично деплоїть нову версію. Pull request'и отримують preview URL для тестування.
Деплой на Netlify
Netlify -- популярна альтернатива Vercel:
1. Створи netlify.toml
# netlify.toml
[build]
command = "npm run build"
publish = ".next"
[[plugins]]
package = "@netlify/plugin-nextjs"
2. Встанови плагін
npm install -D @netlify/plugin-nextjs
3. Підключи репозиторій
- Зайди на netlify.com
- "New site from Git" → обери репозиторій
- Додай environment variables в налаштуваннях
- Deploy!
Vercel має нативну підтримку Next.js (бо це їхній продукт), тому деякі фічі (Edge Functions, ISR) працюють "з коробки". На Netlify потрібен плагін @netlify/plugin-nextjs.
Checklist перед деплоєм
Перед тим як випускати проект у світ, перевір:
Функціональність
-
npm run buildпроходить без помилок - Всі сторінки працюють коректно
- Форми відправляються правильно
- API routes повертають очікувані дані
- Навігація працює між всіма сторінками
Оптимізація
- Зображення використовують
next/image - Шрифти підключені через
next/font - First Load JS менше 200 КБ на сторінку
- Немає зайвого
"use client"(тільки де потрібна інтерактивність)
SEO
- Кожна сторінка має
titleтаdescription - Open Graph метадані для соцмереж
-
robots.tsналаштований -
sitemap.tsгенерується
Безпека
-
.env.localНЕ в Git - Секретні ключі тільки без
NEXT_PUBLIC_префікса - API routes валідують вхідні дані
- Environment variables налаштовані на хостингу
Якість
- Немає помилок у консолі
- Responsive дизайн (перевірити на мобільних)
- Favicon додано
- 404 сторінка оформлена
Підсумок блоку Next.js
За 8 уроків ми пройшли повний цикл Next.js розробки:
- Routing -- file-based маршрутизація, Link, dynamic routes
- Data Fetching -- SSG, SSR, ISR, getStaticProps/getServerSideProps
- Dynamic Routes -- getStaticPaths, generateStaticParams, fallback
- API Routes -- серверні endpoints, CRUD, валідація
- App Router -- Server/Client Components, layouts, streaming
- Data Fetching в App Router -- async components, кешування, Server Actions
- Стилізація -- CSS Modules, Tailwind, next/font, next/image
- Deployment -- збірка, env variables, SEO, деплой
Підсумок всього курсу
Ти пройшов шлях від cd та ls до повноцінного Next.js додатку. Давай згадаємо:
- Block 1: Термінал, Git, GitHub -- інструменти розробника
- Block 2: HTML -- структура вебсторінок
- Block 3: CSS -- стилізація та responsive дизайн
- Block 4: JavaScript Basics -- змінні, функції, масиви, об'єкти
- Block 5: JavaScript & DOM -- інтерактивність у браузері
- Block 6: JavaScript Advanced -- async, fetch, модулі, класи
- Block 7: TypeScript -- типізація для надійного коду
- Block 8: React -- компоненти, стейт, хуки, SPA
- Block 9: Next.js -- SSR, SSG, API, деплой
Це фундамент, на якому будується кар'єра веб-розробника. Далі -- практика, власні проекти, і постійне навчання.
Найкращий спосіб закріпити знання -- створити власний проект. Портфоліо, блог, інтернет-магазин -- неважливо що, головне -- використай все, що вивчив.
Що вивчати далі:
- Next.js Documentation -- глибше вивчити можливості
- TypeScript Handbook -- поглибити знання TypeScript
- Testing: Vitest + Testing Library -- тестування
- State management: Zustand або Jotai
- БД: Prisma або Drizzle ORM
- roadmap.sh/frontend -- дорожня карта фронтенд-розробника