Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds

Przegląd opcji baz danych dla Next.js (SQL, NoSQL)

Wybór odpowiedniej bazy danych jest jedną z kluczowych decyzji przy tworzeniu aplikacji w Next.js. W tym module poznamy najpopularniejsze opcje baz danych oraz ich zalety i wady w kontekście aplikacji Next.js.

Rodzaje baz danych

Bazy danych możemy podzielić na dwie główne kategorie: SQL (relacyjne) i NoSQL (nierelacyjne). Każda z nich ma swoje charakterystyczne cechy, które wpływają na to, do jakich projektów najlepiej się nadają.

Bazy danych SQL (relacyjne)

Bazy relacyjne organizują dane w tabelach z predefiniowaną strukturą i relacjami między nimi. Przykładami popularnych baz SQL są:

  1. PostgreSQL

    • Darmowa, open-source
    • Zaawansowane funkcje (np. typy JSON, full-text search)
    • Świetna wydajność i skalowalność
    • Doskonała integralność danych
  2. MySQL/MariaDB

    • Szeroko stosowana, darmowa baza danych
    • Dobra wydajność dla operacji odczytu
    • Mniejsze wymagania zasobów niż PostgreSQL
  3. SQLite

    • Lekka baza danych (plik) bez osobnego serwera
    • Idealna do prototypowania i testów
    • Nie nadaje się do produkcyjnych aplikacji z dużym ruchem

Bazy danych NoSQL (nierelacyjne)

Bazy NoSQL oferują większą elastyczność struktury danych i zazwyczaj lepszą skalowalność poziomą. Główne typy to:

  1. Dokumentowe (MongoDB, Firebase Firestore)

    • Przechowują dane jako dokumenty (obiekty JSON/BSON)
    • Elastyczna struktura bez sztywnego schematu
    • Świetne do szybkiego prototypowania i danych nieustrukturyzowanych
  2. Key-Value (Redis, DynamoDB)

    • Przechowują proste pary klucz-wartość
    • Ekstremalnie szybkie operacje odczytu/zapisu
    • Często używane jako cache
  3. Wide-Column (Cassandra, HBase)

    • Przechowują dane w kolumnach zamiast wierszach
    • Wysoka skalowalność i wydajność dla ogromnych zbiorów danych
  4. Grafowe (Neo4j, Amazon Neptune)

    • Specjalizują się w relacjach między danymi
    • Idealne do złożonych relacji i analizy połączeń

Popularne opcje baz danych dla Next.js

1. PostgreSQL + Prisma

PostgreSQL w połączeniu z ORM Prisma to jedna z najpopularniejszych opcji dla aplikacji Next.js:

1// Przykład modelu Prisma dla PostgreSQL
2model User {
3  id        Int      @id @default(autoincrement())
4  email     String   @unique
5  name      String?
6  posts     Post[]
7  profile   Profile?
8  createdAt DateTime @default(now())
9  updatedAt DateTime @updatedAt
10}
11
12model Post {
13  id        Int      @id @default(autoincrement())
14  title     String
15  content   String?
16  published Boolean  @default(false)
17  author    User     @relation(fields: [authorId], references: [id])
18  authorId  Int
19  createdAt DateTime @default(now())
20  updatedAt DateTime @updatedAt
21}
22
23model Profile {
24  id     Int    @id @default(autoincrement())
25  bio    String
26  user   User   @relation(fields: [userId], references: [id])
27  userId Int    @unique
28}

Zalety:

  • Silna integralność danych dzięki relacjom
  • Wysoka wydajność i niezawodność
  • Dobra skalowalność
  • Świetne wsparcie TypeScript dzięki Prisma

Wady:

  • Wymaga serwera bazy danych
  • Sztywna struktura danych (schema)

2. MongoDB + Mongoose

MongoDB to popularna nierelacyjna baza dokumentowa, często używana z Next.js:

1// Przykładowy model Mongoose dla MongoDB
2import mongoose from 'mongoose';
3
4const UserSchema = new mongoose.Schema({
5  name: {
6    type: String,
7    required: [true, 'Proszę podać imię'],
8    maxlength: [50, 'Imię nie może być dłuższe niż 50 znaków']
9  },
10  email: {
11    type: String,
12    required: [true, 'Proszę podać email'],
13    unique: true,
14    match: [
15      /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/,
16      'Proszę podać poprawny adres email'
17    ]
18  },
19  posts: [
20    {
21      type: mongoose.Schema.Types.ObjectId,
22      ref: 'Post'
23    }
24  ],
25  createdAt: {
26    type: Date,
27    default: Date.now
28  }
29});
30
31export default mongoose.models.User || mongoose.model('User', UserSchema);

Zalety:

  • Elastyczna struktura danych
  • Łatwa skalowalność pozioma
  • Format danych podobny do JSON
  • Dobre wsparcie dla TypeScript

Wady:

  • Słabsza integralność danych niż w bazach SQL
  • Trudniejsze złożone zapytania

3. Serverless Databases (PlanetScale, Neon, Supabase)

Serverless databases to nowy trend idealnie pasujący do architektury Next.js:

1// Przykład użycia PlanetScale z Next.js
2import { PrismaClient } from '@prisma/client';
3
4const prisma = new PrismaClient();
5
6// W API route lub Server Component
7export async function getUsers() {
8  try {
9    const users = await prisma.user.findMany({
10      include: { posts: true }
11    });
12    return users;
13  } catch (error) {
14    console.error('Database error:', error);
15    throw new Error('Nie udało się pobrać użytkowników');
16  }
17}

Popularne opcje:

  • PlanetScale - MySQL-kompatybilna baza danych serverless
  • Neon - PostgreSQL w modelu serverless
  • Supabase - platforma backend-as-a-service z PostgreSQL
  • Firebase - kompleksowe rozwiązanie z Firestore jako bazą dokumentową

Zalety:

  • Brak konieczności zarządzania infrastrukturą
  • Pay-per-use (płacisz tylko za to, co wykorzystasz)
  • Automatyczne skalowanie
  • Często darmowy plan dla małych projektów

Wady:

  • Potencjalnie wyższe koszty przy dużej skali
  • Mniejsza kontrola nad infrastrukturą
  • Zależność od zewnętrznego dostawcy

4. Edge Databases (Cloudflare D1, Fauna)

Nowością w ekosystemie Next.js są bazy danych działające na edge:

1// Przykład użycia Cloudflare D1 z Next.js
2// W API Route (Pages Router) lub Route Handler (App Router)
3import { D1Database } from '@cloudflare/workers-types';
4
5export const runtime = 'edge';
6
7export async function GET() {
8  const db = process.env.DB as unknown as D1Database;
9  
10  const { results } = await db
11    .prepare('SELECT * FROM users WHERE status = ?')
12    .bind('active')
13    .all();
14    
15  return Response.json({ users: results });
16}

Zalety:

  • Minimalne opóźnienia dla użytkowników globalnych
  • Integracja z funkcjami edge
  • Często niższe koszty

Wady:

  • Ograniczone możliwości w porównaniu z tradycyjnymi bazami danych
  • Relatywnie nowa technologia

Wybór bazy danych dla Next.js - czynniki do rozważenia

1. Struktura danych

  • Jeśli masz jasno zdefiniowaną strukturę danych z relacjami → PostgreSQL lub MySQL
  • Jeśli struktura danych jest płynna i może się zmieniać → MongoDB lub Firestore

2. Skalowalność

  • Dla aplikacji, które muszą obsłużyć miliony użytkowników → Serverless options (PlanetScale, Neon)
  • Dla aplikacji o przewidywalnym ruchu → Tradycyjne rozwiązania jak PostgreSQL

3. Zespół i doświadczenie

  • Jeśli zespół ma doświadczenie z SQL → PostgreSQL/MySQL
  • Jeśli zespół preferuje podejście JavaScript-first → MongoDB

4. Hosting i deployment

  • Jeśli używasz Vercel do hostingu Next.js → Dobrze integruje się z PlanetScale, Neon, Supabase
  • Jeśli używasz Cloudflare Pages → Cloudflare D1 lub Cloudflare KV

Przykłady integracji w Next.js

Przykład 1: PostgreSQL + Prisma w Next.js

1// lib/prisma.ts
2import { PrismaClient } from '@prisma/client';
3
4let prisma: PrismaClient;
5
6if (process.env.NODE_ENV === 'production') {
7  prisma = new PrismaClient();
8} else {
9  // Zapobieganie wielu instancjom w trybie dev
10  if (!global.prisma) {
11    global.prisma = new PrismaClient();
12  }
13  prisma = global.prisma;
14}
15
16export default prisma;
17
18// W Server Component (App Router)
19// app/users/page.tsx
20import prisma from '@/lib/prisma';
21
22export default async function UsersPage() {
23  const users = await prisma.user.findMany({
24    include: {
25      posts: true,
26    },
27  });
28
29  return (
30    <div>
31      <h1>Użytkownicy</h1>
32      <ul>
33        {users.map((user) => (
34          <li key={user.id}>
35            {user.name} - {user.posts.length} postów
36          </li>
37        ))}
38      </ul>
39    </div>
40  );
41}

Przykład 2: MongoDB w Next.js (Pages Router)

1// lib/mongodb.js
2import { MongoClient } from 'mongodb';
3
4const MONGODB_URI = process.env.MONGODB_URI;
5const MONGODB_DB = process.env.MONGODB_DB;
6
7if (!MONGODB_URI) {
8  throw new Error('Zdefiniuj MONGODB_URI w pliku .env.local');
9}
10
11if (!MONGODB_DB) {
12  throw new Error('Zdefiniuj MONGODB_DB w pliku .env.local');
13}
14
15let cachedClient = null;
16let cachedDb = null;
17
18export async function connectToDatabase() {
19  if (cachedClient && cachedDb) {
20    return { client: cachedClient, db: cachedDb };
21  }
22
23  const client = await MongoClient.connect(MONGODB_URI, {
24    useNewUrlParser: true,
25    useUnifiedTopology: true,
26  });
27
28  const db = await client.db(MONGODB_DB);
29
30  cachedClient = client;
31  cachedDb = db;
32
33  return { client, db };
34}
35
36// W API Route
37// pages/api/users.js
38import { connectToDatabase } from '@/lib/mongodb';
39
40export default async function handler(req, res) {
41  const { db } = await connectToDatabase();
42  
43  const users = await db
44    .collection('users')
45    .find({})
46    .limit(20)
47    .toArray();
48    
49  res.status(200).json(users);
50}

Podsumowanie

Przy wyborze bazy danych dla Next.js warto kierować się następującymi zasadami:

  1. Aplikacje z jasno zdefiniowanymi relacjami: PostgreSQL + Prisma
  2. Szybkie prototypowanie i elastyczne struktury danych: MongoDB lub Firestore
  3. Aplikacje serverless: PlanetScale, Neon, lub Supabase
  4. Aplikacje globalne z niskim opóźnieniem: Edge Databases jak Cloudflare D1 lub FaunaDB

Niezależnie od wyboru, Next.js oferuje świetne mechanizmy integracji z wszystkimi popularnymi bazami danych. W kolejnym module dowiemy się, jak skonfigurować ORM dla wybranego rozwiązania, aby jeszcze bardziej usprawnić pracę z bazą danych.

Przejdź do CodeWorlds