Add blog posts, cleanup unused files, update components
- Add 100 blog posts covering AI, development, and tech topics - Add .env.example for environment configuration - Add accessibility and lighthouse audit scripts - Remove obsolete SEO reports and temporary files - Remove dev-dist build artifacts and backup files - Remove unused portrait images (moved/consolidated elsewhere) - Update contact form and component improvements Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,550 @@
|
||||
# Prisma 7: Der TypeScript-Native ORM für 2026
|
||||
|
||||
**Meta-Description:** Prisma 7 Deep Dive nach dem Rust-zu-TypeScript-Rewrite. 90% kleinere Bundles, 3x schnellere Queries und verbesserte Type-Safety.
|
||||
|
||||
**Keywords:** Prisma, ORM, TypeScript, Database, PostgreSQL, MySQL, SQLite, Query Builder, Type Safety, Prisma 7
|
||||
|
||||
---
|
||||
|
||||
## Einführung
|
||||
|
||||
Prisma 7 ist ein **Game-Changer**: Das Team hat die gesamte Query Engine von Rust nach TypeScript umgeschrieben. Das Ergebnis: 90% kleinere Bundles, 3x schnellere Queries und bessere Cold-Starts für Serverless.
|
||||
|
||||
---
|
||||
|
||||
## Die Revolution: Rust-Free Prisma
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ PRISMA 6 vs PRISMA 7 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Prisma 6 (Rust Engine): │
|
||||
│ ├── Bundle Size: ~14MB (7MB gzipped) │
|
||||
│ ├── Cold Start: ~300ms (Lambda) │
|
||||
│ └── Query Speed: Baseline │
|
||||
│ │
|
||||
│ Prisma 7 (TypeScript Engine): │
|
||||
│ ├── Bundle Size: ~1.6MB (600KB gzipped) → 90% kleiner │
|
||||
│ ├── Cold Start: ~50ms (Lambda) → 6x schneller │
|
||||
│ └── Query Speed: 3x schneller bei großen Result Sets │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Setup & Schema
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
npm install prisma @prisma/client
|
||||
npx prisma init
|
||||
```
|
||||
|
||||
### Schema Definition
|
||||
|
||||
```prisma
|
||||
// prisma/schema.prisma
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
name String?
|
||||
role Role @default(USER)
|
||||
posts Post[]
|
||||
profile Profile?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([email])
|
||||
}
|
||||
|
||||
model Profile {
|
||||
id String @id @default(cuid())
|
||||
bio String?
|
||||
avatar String?
|
||||
userId String @unique
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
model Post {
|
||||
id String @id @default(cuid())
|
||||
title String
|
||||
content String?
|
||||
published Boolean @default(false)
|
||||
author User @relation(fields: [authorId], references: [id])
|
||||
authorId String
|
||||
categories Category[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([authorId])
|
||||
@@index([published])
|
||||
}
|
||||
|
||||
model Category {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
posts Post[]
|
||||
}
|
||||
|
||||
enum Role {
|
||||
USER
|
||||
ADMIN
|
||||
MODERATOR
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CRUD Operations
|
||||
|
||||
### Create
|
||||
|
||||
```typescript
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
// Einzelner Datensatz
|
||||
const user = await prisma.user.create({
|
||||
data: {
|
||||
email: 'alice@example.com',
|
||||
name: 'Alice',
|
||||
// Nested Create
|
||||
profile: {
|
||||
create: {
|
||||
bio: 'Developer from Berlin'
|
||||
}
|
||||
},
|
||||
posts: {
|
||||
create: [
|
||||
{ title: 'First Post' },
|
||||
{ title: 'Second Post' }
|
||||
]
|
||||
}
|
||||
},
|
||||
include: {
|
||||
profile: true,
|
||||
posts: true
|
||||
}
|
||||
});
|
||||
|
||||
// Mehrere Datensätze
|
||||
const { count } = await prisma.user.createMany({
|
||||
data: [
|
||||
{ email: 'bob@example.com', name: 'Bob' },
|
||||
{ email: 'carol@example.com', name: 'Carol' }
|
||||
],
|
||||
skipDuplicates: true
|
||||
});
|
||||
```
|
||||
|
||||
### Read
|
||||
|
||||
```typescript
|
||||
// Einzelner Datensatz
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { email: 'alice@example.com' }
|
||||
});
|
||||
|
||||
// Mit Relations
|
||||
const userWithPosts = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
include: {
|
||||
posts: {
|
||||
where: { published: true },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 5
|
||||
},
|
||||
profile: true
|
||||
}
|
||||
});
|
||||
|
||||
// Nur bestimmte Felder
|
||||
const userBasic = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true
|
||||
}
|
||||
});
|
||||
|
||||
// Liste mit Filter
|
||||
const users = await prisma.user.findMany({
|
||||
where: {
|
||||
role: 'USER',
|
||||
email: {
|
||||
contains: '@example.com'
|
||||
},
|
||||
posts: {
|
||||
some: {
|
||||
published: true
|
||||
}
|
||||
}
|
||||
},
|
||||
orderBy: [
|
||||
{ role: 'asc' },
|
||||
{ name: 'asc' }
|
||||
],
|
||||
skip: 0,
|
||||
take: 10
|
||||
});
|
||||
```
|
||||
|
||||
### Update
|
||||
|
||||
```typescript
|
||||
// Einzelner Datensatz
|
||||
const updatedUser = await prisma.user.update({
|
||||
where: { id: userId },
|
||||
data: {
|
||||
name: 'Alice Updated',
|
||||
// Nested Update
|
||||
profile: {
|
||||
update: {
|
||||
bio: 'Senior Developer from Berlin'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Upsert (Create or Update)
|
||||
const user = await prisma.user.upsert({
|
||||
where: { email: 'alice@example.com' },
|
||||
update: { name: 'Alice' },
|
||||
create: {
|
||||
email: 'alice@example.com',
|
||||
name: 'Alice'
|
||||
}
|
||||
});
|
||||
|
||||
// Mehrere aktualisieren
|
||||
const { count } = await prisma.user.updateMany({
|
||||
where: {
|
||||
role: 'USER',
|
||||
createdAt: {
|
||||
lt: new Date('2024-01-01')
|
||||
}
|
||||
},
|
||||
data: {
|
||||
role: 'MODERATOR'
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Delete
|
||||
|
||||
```typescript
|
||||
// Einzelner Datensatz
|
||||
const deletedUser = await prisma.user.delete({
|
||||
where: { id: userId }
|
||||
});
|
||||
|
||||
// Mehrere Datensätze
|
||||
const { count } = await prisma.user.deleteMany({
|
||||
where: {
|
||||
posts: {
|
||||
none: {}
|
||||
},
|
||||
createdAt: {
|
||||
lt: new Date('2023-01-01')
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Erweiterte Queries
|
||||
|
||||
### Aggregations
|
||||
|
||||
```typescript
|
||||
// Count
|
||||
const userCount = await prisma.user.count({
|
||||
where: { role: 'USER' }
|
||||
});
|
||||
|
||||
// Aggregate
|
||||
const stats = await prisma.post.aggregate({
|
||||
_count: { id: true },
|
||||
_avg: { viewCount: true },
|
||||
_sum: { viewCount: true },
|
||||
_min: { createdAt: true },
|
||||
_max: { createdAt: true }
|
||||
});
|
||||
|
||||
// Group By
|
||||
const postsByAuthor = await prisma.post.groupBy({
|
||||
by: ['authorId'],
|
||||
_count: { id: true },
|
||||
_sum: { viewCount: true },
|
||||
having: {
|
||||
id: {
|
||||
_count: {
|
||||
gt: 5
|
||||
}
|
||||
}
|
||||
},
|
||||
orderBy: {
|
||||
_count: {
|
||||
id: 'desc'
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Raw SQL
|
||||
|
||||
```typescript
|
||||
// Raw Query
|
||||
const users = await prisma.$queryRaw<User[]>`
|
||||
SELECT * FROM "User"
|
||||
WHERE email LIKE ${'%@example.com'}
|
||||
ORDER BY "createdAt" DESC
|
||||
`;
|
||||
|
||||
// Raw Execute
|
||||
const result = await prisma.$executeRaw`
|
||||
UPDATE "User"
|
||||
SET "lastLogin" = NOW()
|
||||
WHERE id = ${userId}
|
||||
`;
|
||||
|
||||
// Mit TypedSQL (Prisma 7.1+)
|
||||
import { sql } from '@prisma/client/sql';
|
||||
|
||||
const activeUsers = await prisma.$queryRawTyped(
|
||||
sql`SELECT * FROM "User" WHERE "isActive" = true`
|
||||
);
|
||||
```
|
||||
|
||||
### Transactions
|
||||
|
||||
```typescript
|
||||
// Interactive Transaction
|
||||
const result = await prisma.$transaction(async (tx) => {
|
||||
// Guthaben abziehen
|
||||
const sender = await tx.account.update({
|
||||
where: { id: senderId },
|
||||
data: { balance: { decrement: amount } }
|
||||
});
|
||||
|
||||
if (sender.balance < 0) {
|
||||
throw new Error('Insufficient funds');
|
||||
}
|
||||
|
||||
// Guthaben hinzufügen
|
||||
const receiver = await tx.account.update({
|
||||
where: { id: receiverId },
|
||||
data: { balance: { increment: amount } }
|
||||
});
|
||||
|
||||
return { sender, receiver };
|
||||
}, {
|
||||
isolationLevel: 'Serializable',
|
||||
timeout: 10000
|
||||
});
|
||||
|
||||
// Sequential Operations (Batch)
|
||||
const [users, posts] = await prisma.$transaction([
|
||||
prisma.user.findMany(),
|
||||
prisma.post.findMany({ where: { published: true } })
|
||||
]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Type-Safety Features
|
||||
|
||||
### Prisma 7 Typed Improvements
|
||||
|
||||
```typescript
|
||||
// 98% weniger Types bei Schema-Evaluation
|
||||
// 45% weniger Types bei Query-Evaluation
|
||||
// 70% schnelleres Type-Checking
|
||||
|
||||
// Full Type Safety
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
include: { posts: true }
|
||||
});
|
||||
|
||||
// user ist typisiert als:
|
||||
// {
|
||||
// id: string;
|
||||
// email: string;
|
||||
// name: string | null;
|
||||
// role: Role;
|
||||
// posts: Post[];
|
||||
// ...
|
||||
// } | null
|
||||
|
||||
// Conditional Include Typing
|
||||
const userMaybeWithPosts = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
include: includePosts ? { posts: true } : undefined
|
||||
});
|
||||
// Typ reflektiert die Bedingung
|
||||
```
|
||||
|
||||
### Validierung mit Zod
|
||||
|
||||
```typescript
|
||||
import { z } from 'zod';
|
||||
import { Prisma } from '@prisma/client';
|
||||
|
||||
// Schema aus Prisma Types ableiten
|
||||
const CreateUserSchema = z.object({
|
||||
email: z.string().email(),
|
||||
name: z.string().min(2).optional(),
|
||||
role: z.enum(['USER', 'ADMIN', 'MODERATOR']).default('USER')
|
||||
}) satisfies z.Schema<Prisma.UserCreateInput>;
|
||||
|
||||
// Validierung vor DB-Operation
|
||||
async function createUser(input: unknown) {
|
||||
const data = CreateUserSchema.parse(input);
|
||||
return prisma.user.create({ data });
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SQL Comments (Prisma 7.1)
|
||||
|
||||
```typescript
|
||||
// Observability und Debugging
|
||||
const users = await prisma.user.findMany({
|
||||
// Diese Informationen erscheinen als SQL-Kommentar
|
||||
// für besseres Tracing
|
||||
}).$extends({
|
||||
query: {
|
||||
$allOperations({ operation, args, query }) {
|
||||
return query(args);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Generiertes SQL:
|
||||
// /* prisma:client,user.findMany,requestId:abc123 */
|
||||
// SELECT * FROM "User"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Serverless & Edge Optimierung
|
||||
|
||||
```typescript
|
||||
// Für Cloudflare Workers, Vercel Edge, etc.
|
||||
import { PrismaClient } from '@prisma/client/edge';
|
||||
import { withAccelerate } from '@prisma/extension-accelerate';
|
||||
|
||||
const prisma = new PrismaClient().$extends(withAccelerate());
|
||||
|
||||
// Connection Pooling via Prisma Accelerate
|
||||
const users = await prisma.user.findMany({
|
||||
cacheStrategy: {
|
||||
ttl: 60, // Cache für 60 Sekunden
|
||||
swr: 300 // Stale-While-Revalidate für 5 Minuten
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Migration & Deployment
|
||||
|
||||
```bash
|
||||
# Schema-Änderungen als Migration
|
||||
npx prisma migrate dev --name add_user_role
|
||||
|
||||
# Production Deployment
|
||||
npx prisma migrate deploy
|
||||
|
||||
# Client generieren
|
||||
npx prisma generate
|
||||
|
||||
# Datenbank seeden
|
||||
npx prisma db seed
|
||||
|
||||
# Studio (Daten-Browser)
|
||||
npx prisma studio
|
||||
```
|
||||
|
||||
### Seed Script
|
||||
|
||||
```typescript
|
||||
// prisma/seed.ts
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
// Admin User
|
||||
await prisma.user.upsert({
|
||||
where: { email: 'admin@example.com' },
|
||||
update: {},
|
||||
create: {
|
||||
email: 'admin@example.com',
|
||||
name: 'Admin',
|
||||
role: 'ADMIN'
|
||||
}
|
||||
});
|
||||
|
||||
// Categories
|
||||
const categories = ['Technology', 'Design', 'Business'];
|
||||
for (const name of categories) {
|
||||
await prisma.category.upsert({
|
||||
where: { name },
|
||||
update: {},
|
||||
create: { name }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.catch(console.error)
|
||||
.finally(() => prisma.$disconnect());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fazit
|
||||
|
||||
Prisma 7 bringt:
|
||||
|
||||
1. **90% kleinere Bundles**: Perfekt für Serverless
|
||||
2. **3x schnellere Queries**: Besonders bei großen Datasets
|
||||
3. **Bessere Type-Safety**: 70% schnelleres Type-Checking
|
||||
4. **SQL Comments**: Verbessertes Debugging
|
||||
|
||||
Der Rust-zu-TypeScript-Rewrite macht Prisma schneller, kleiner und besser wartbar.
|
||||
|
||||
---
|
||||
|
||||
## Bildprompts
|
||||
|
||||
1. "Database schema transforming into TypeScript types, code generation visualization"
|
||||
2. "Performance comparison chart showing bundle size reduction, before/after"
|
||||
3. "Prisma logo with speed lines, serverless deployment concept"
|
||||
|
||||
---
|
||||
|
||||
## Quellen
|
||||
|
||||
- [Prisma 7 Release Announcement](https://www.prisma.io/blog/announcing-prisma-orm-7-0-0)
|
||||
- [Prisma 7 Upgrade Guide](https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-7)
|
||||
- [Prisma Performance Benchmarks](https://www.prisma.io/blog/prisma-orm-without-rust-latest-performance-benchmarks)
|
||||
- [Prisma Documentation](https://www.prisma.io/docs)
|
||||
Reference in New Issue
Block a user