Strona główna / Artykuły / Next.js, Tailwind i Prisma z Dockerem i Postgresem

Next.js, Tailwind i Prisma z Dockerem i Postgresem

Krok po kroku: utwórz aplikację Next.js z TypeScript, uruchom Postgres w Dockerze, skonfiguruj Prisma migrate i seed, a następnie wyślij zapytania do użytkowników z komponentu serwerowego.

1108 słów

Wymagania wstępne

Zainstaluj te narzędzia przed przystąpieniem do kroków:

  • Docker (do lokalnego kontenera Postgres)
  • Node.js (zalecana wersja v16+)
  • npm (dołączony do Node)

1) Stwórz projekt Next.js

Użyj oficjalnego narzędzia inicjalizacyjnego i odpowiedz na pytania. W tym przewodniku zaleca się użycie App Router i TypeScript.

npx create-next-app@latest notes-taking
# choose your options in the interactive prompt (App Router, TypeScript recommended)
cd note-taking

Aby od razu użyć TypeScript w pierwszym poleceniu:

npx create-next-app@latest note-taking — ts

2) Dodaj Tailwind CSS (już jest włączony w NextJs)

Nowsze szablony create-next-app automatycznie integrują Tailwind, gdy jest on włączony w opcjach interaktywnych, więc nie ma potrzeby osobistej instalacji Tailwind dla nowego projektu, który go wybrał.

3) Uruchom Postgres za pomocą Dockera (lokalnie)

Zapocznij działanie Postgres w kontenerze:

docker run — name notes-postgres -e POSTGRES_PASSWORD=password -e POSTGRES_DB=notes_app -p 5432:5432 -d postgres:latest

Znaczenie flag:

  • docker run — tworzy i uruchamia kontener
  • --name notes-postgres — stała nazwa dla późniejszych poleceń
  • -e POSTGRES_PASSWORD=... / -e POSTGRES_DB=... — dane logowania i baza danych
  • -p 5432:5432 — udostępnianie portu na hostzie
  • -d postgres:latest — uruchomienie w tle z użyciem obrazu Postgres

Potwierdzenie działania:

docker ps

Filtrowanie według obrazu:

docker ps — filter “ancestor=postgres”

Wyświetlanie wszystkich kontenerów, włączając te zatrzymane:

docker ps -a

Filtrowanie według nazwy kontenera:

docker ps — filter “name=notes-postgres”

4) Instalacja Prisma i powiązanych pakietów

Z katalogu głównego projektu Next.js:

npm install prisma tsx — save-dev
npm install @prisma/extension-accelerate @prisma/client

Inicjalizacja Prisma oraz umieszczenie klienta w folderze app, aby importy App Router pozostały lokalne:

npx prisma init — db — output ../app/generated/prisma

To tworzy katalog prisma/ zawierający plik schema.prisma, plik .env z wartością DATABASE_URL, a także (przy użyciu opcji --output) wygenerowany klient w katalogu app/generated/prisma.

Czy wolisz domyślną lokalizację klienta? Zainicjuj projekt bez określania własnego miejsca zapisu:

npx prisma init — db and remove — output.

5) Konfiguracja pliku .env (DATABASE_URL)

Ustaw wartość DATABASE_URL na adres instancji Docker Postgres:

DATABASE_URL=”postgresql://postgres:password@localhost:5432/notes_app?schema=public”

Zmień hasło oraz nazwę bazy danych, jeśli wybrałeś inne wartości.

6) Edytowanie pliku prisma/schema.prisma

Użyj pary modeli User/Post, która będzie pasować do późniejszego skryptu siewnego:

generator client {
provider = "prisma-client-js"
output = "../app/generated/prisma"
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

model User {
id Int @id @default(autoincrement())
name String
email String @unique
posts Post[]
}

model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id])
}

Zapisz plik, gdy modele będą poprawne.

7) Uruchomienie migracji (tworzenie tabel)

Zastosuj pierwszą migrację w celu utworzenia tabel:

npx prisma migrate dev — name init

Prisma zapisuje SQL w katalogu prisma/migrations dla tej zmiany.

8) Wypełnij bazę danych przykładowymi danymi

Dzięki temu kroku dodawane są przykładowe wiersze, dzięki czemu Prisma Studio oraz aplikacja od razu mają dostęp do danych.

Stwórz plik prisma/seed.ts (zmień import, jeśli ścieżka wyjściowa klienta jest inna):

// prisma/seed.ts
import { PrismaClient, Prisma } from "../app/generated/prisma";

const prisma = new PrismaClient();

const userData: Prisma.UserCreateInput[] = [
  {
    name: "Alice",
    email: "alice@prisma.io",
    posts: {
      create: [
        {
          title: "Join the Prisma Discord",
          content: "https://pris.ly/discord",
          published: true,
        },
        {
          title: "Prisma on YouTube",
          content: "https://pris.ly/youtube",
        },
      ],
    },
  },
  {
    name: "Bob",
    email: "bob@prisma.io",
    posts: {
      create: [
        {
          title: "Follow Prisma on Twitter",
          content: "https://www.twitter.com/prisma",
          published: true,
        },
      ],
    },
  },
];

export async function main() {
  for (const u of userData) {
    await prisma.user.create({ data: u });
  }
}

main();ty

Zarejestruj skrypt wypełniania bazy w pliku package.json:

"prisma": {
"seed": "tsx prisma/seed.ts"
}

Zapuść go:

npx prisma db seed

Dzięki temu zostaną dodane Alice i Bob wraz z ich wpisami.

9) Otwórz Prisma Studio

Można wizualnie przeglądać i edytować wiersze:

npx prisma studio

Interfejs przeglądarki pokazuje modele oraz zapisy.

10) Stwórz otoczkę dla klienta Prisma (lib/prisma.ts)

Aby uniknąć tworzenia wielu instancji PrismaClient podczas rozwoju, użyj globalnego singletona oraz rozszerzenia accelerate. Stwórz plik lib/prisma.ts:

// lib/prisma.ts
import { PrismaClient } from "../app/generated/prisma"; // adjust path if needed
import { withAccelerate } from "@prisma/extension-accelerate";

declare global {
// allow global prisma across module reloads in dev
// eslint-disable-next-line no-var
var prisma: PrismaClient | undefined;
}

const prisma =
global.prisma ?? new PrismaClient().$extends(withAccelerate());
if (process.env.NODE_ENV !== "production") global.prisma = prisma;

export default prisma;

Wskazz import na utworzoną ścieżkę klienta lub użyj @prisma/client, jeśli pominąłeś parametr --output.

11) Testowanie połączenia z bazą danych w Next.js (komponent serwerowy)

Przykład pliku app/page.tsx, który ładuje użytkowników na serwerze:

import prisma from '@/lib/db'

export default async function Home() {
  const users = await prisma.user.findMany();
  return (
    <div className="min-h-screen bg-gray-50 flex flex-col items-center justify-center -mt-16">
      <h1 className="text-4xl font-bold mb-8 font-[family-name:var(--font-geist-sans)] text-[#333333]">
        Superblog
      </h1>
      <ol className="list-decimal list-inside font-[family-name:var(--font-geist-sans)]">
        {users.map((user) => (
          <li key={user.id} className="mb-2">
            {user.name}
          </li>
        ))}
      </ol>
    </div>
  );
}

Zainicjuj serwer rozwojowy Next.js:

npm run dev

Otwórz http://localhost:3000 i upewnij się, że wyświetlają się założone użytkownicy.

Pełna lista poleceń

utworzenie projektu

npx create-next-app@latest my-app
cd my-app

postgres docker

docker run — name notes-postgres -e POSTGRES_PASSWORD=password -e POSTGRES_DB=notes_app -p 5432:5432 -d postgres:latest

docker ps

docker exec -it notes-postgres psql -U postgres

prisma

npm install prisma tsx — save-dev
npm install @prisma/extension-accelerate @prisma/client
npx prisma init — db — output ../app/generated/prisma

edycja pliku prisma/schema.prisma

npx prisma migrate dev — name init

utworzenie pliku prisma/seed.ts

dodanie wpisu prisma.seed do package.json

npx prisma db seed
npx prisma studio
npm run dev

Rozwiązywanie problemów i wskazówki

  • Nie można połączyć się z Postgres: sprawdź kontener za pomocą docker ps, a następnie zweryfikuj host i port w DATABASE_URL. Spróbuj użyć psql z hosta lub innego klienta pod tym samym adresem URL.
  • Błędy migracji: przeczytaj SQL wygenerowany przez Prismę w katalogu prisma/migrations i upewnij się, że nazwa bazy danych jest zgodna z wartością w pliku .env.
  • Niewłaściwy import klienta: zregeneruj pliki po zmianie ustawienia output, albo przełącz się na import z @prisma/client, jeśli używasz domyślnego miejsca przechowywania.
  • Pusta interfejs użytkownika: uruchom ponownie procedurę seedowania i upewnij się, że w Prisma Studio widnieją postacie Alice/Bob, zanim rozpoczniesz debugowanie komponentu strony.

Literatura pokrewna