feat: add decision guide for Server Actions vs API Routes
- Introduced a new guide in `server-actions.mdc` to clarify when to use Server Actions versus API Routes in Next.js. - Included examples, implementation patterns, migration strategies, and anti-patterns to avoid for better developer understanding.
This commit is contained in:
113
.cursor/rules/server-actions.mdc
Normal file
113
.cursor/rules/server-actions.mdc
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: true
|
||||||
|
description: Guide for when to use Server Actions vs API Routes in Next.js App Router
|
||||||
|
---
|
||||||
|
|
||||||
|
# Server Actions vs API Routes - Decision Guide
|
||||||
|
|
||||||
|
## ✅ USE SERVER ACTIONS for:
|
||||||
|
|
||||||
|
### Quick Actions & Mutations
|
||||||
|
- **TaskCard actions**: `updateTaskStatus()`, `updateTaskTitle()`, `deleteTask()`
|
||||||
|
- **Daily checkboxes**: `toggleCheckbox()`, `addCheckbox()`, `updateCheckbox()`
|
||||||
|
- **User preferences**: `updateTheme()`, `updateViewPreferences()`, `updateFilters()`
|
||||||
|
- **Simple CRUD**: `createTag()`, `updateTag()`, `deleteTag()`
|
||||||
|
|
||||||
|
### Characteristics of Server Action candidates:
|
||||||
|
- Simple, frequent mutations
|
||||||
|
- No complex business logic
|
||||||
|
- Used in interactive components (forms, buttons, toggles)
|
||||||
|
- Need immediate UI feedback with `useTransition`
|
||||||
|
- Benefit from automatic cache revalidation
|
||||||
|
|
||||||
|
## ❌ KEEP API ROUTES for:
|
||||||
|
|
||||||
|
### Complex Endpoints
|
||||||
|
- **Initial data fetching**: `GET /api/tasks` with complex filters
|
||||||
|
- **External integrations**: `POST /api/jira/sync` with complex logic
|
||||||
|
- **Analytics & reports**: Complex data aggregation
|
||||||
|
- **Public API**: Endpoints that might be called from mobile/external
|
||||||
|
|
||||||
|
### Characteristics that require API Routes:
|
||||||
|
- Complex business logic or data processing
|
||||||
|
- Multiple service orchestration
|
||||||
|
- Need for HTTP monitoring/logging
|
||||||
|
- External consumption (mobile apps, webhooks)
|
||||||
|
- Real-time features (WebSockets, SSE)
|
||||||
|
- File uploads or special content types
|
||||||
|
|
||||||
|
## 🔄 Implementation Pattern
|
||||||
|
|
||||||
|
### Server Actions Structure
|
||||||
|
```typescript
|
||||||
|
// actions/tasks.ts
|
||||||
|
'use server'
|
||||||
|
|
||||||
|
import { tasksService } from '@/services/tasks';
|
||||||
|
import { revalidatePath } from 'next/cache';
|
||||||
|
|
||||||
|
export async function updateTaskStatus(taskId: string, status: TaskStatus) {
|
||||||
|
try {
|
||||||
|
const task = await tasksService.updateTask(taskId, { status });
|
||||||
|
revalidatePath('/'); // Auto cache invalidation
|
||||||
|
return { success: true, data: task };
|
||||||
|
} catch (error) {
|
||||||
|
return { success: false, error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Component Usage with useTransition
|
||||||
|
```typescript
|
||||||
|
// components/TaskCard.tsx
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { updateTaskStatus } from '@/actions/tasks';
|
||||||
|
import { useTransition } from 'react';
|
||||||
|
|
||||||
|
export function TaskCard({ task }) {
|
||||||
|
const [isPending, startTransition] = useTransition();
|
||||||
|
|
||||||
|
const handleStatusChange = (status) => {
|
||||||
|
startTransition(async () => {
|
||||||
|
const result = await updateTaskStatus(task.id, status);
|
||||||
|
if (!result.success) {
|
||||||
|
// Handle error
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={isPending ? 'opacity-50' : ''}>
|
||||||
|
{/* UI with loading state */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🏗️ Migration Strategy
|
||||||
|
|
||||||
|
When migrating from API Routes to Server Actions:
|
||||||
|
|
||||||
|
1. **Create server action** in `actions/` directory
|
||||||
|
2. **Update component** to use server action directly
|
||||||
|
3. **Remove API route** (PATCH, POST, DELETE for mutations)
|
||||||
|
4. **Simplify client** (remove mutation methods, keep GET only)
|
||||||
|
5. **Update hooks** to use server actions instead of HTTP calls
|
||||||
|
|
||||||
|
## 🎯 Benefits of Server Actions
|
||||||
|
|
||||||
|
- **🚀 Performance**: No HTTP serialization overhead
|
||||||
|
- **🔄 Cache intelligence**: Automatic revalidation with `revalidatePath()`
|
||||||
|
- **📦 Bundle reduction**: Less client-side HTTP code
|
||||||
|
- **⚡ UX**: Native loading states with `useTransition`
|
||||||
|
- **🎯 Simplicity**: Direct service calls, less boilerplate
|
||||||
|
|
||||||
|
## 🚨 Anti-patterns to Avoid
|
||||||
|
|
||||||
|
- Don't use server actions for complex data fetching
|
||||||
|
- Don't use server actions for endpoints that need HTTP monitoring
|
||||||
|
- Don't use server actions for public API endpoints
|
||||||
|
- Don't mix server actions with client-side state management for the same data
|
||||||
|
|
||||||
|
Remember: Server Actions are for **direct mutations**, API Routes are for **complex operations** and **public interfaces**.
|
||||||
Reference in New Issue
Block a user