Next.js 14 सर्वर एक्शन के लिए एक विस्तृत गाइड, जिसमें फॉर्म हैंडलिंग की सर्वोत्तम प्रथाओं, डेटा वैलिडेशन, सुरक्षा और उन्नत तकनीकों को शामिल किया गया है।
Next.js 14 सर्वर एक्शन: फॉर्म हैंडलिंग की सर्वोत्तम प्रथाओं में महारत हासिल करना
Next.js 14 प्रदर्शनशील और उपयोगकर्ता-अनुकूल वेब एप्लीकेशन बनाने के लिए शक्तिशाली सुविधाएँ प्रस्तुत करता है। इनमें से, सर्वर एक्शन फॉर्म सबमिशन और डेटा म्यूटेशन को सीधे सर्वर पर संभालने के एक परिवर्तनकारी तरीके के रूप में सामने आते हैं। यह गाइड Next.js 14 में सर्वर एक्शन का एक व्यापक अवलोकन प्रदान करता है, जिसमें फॉर्म हैंडलिंग, डेटा वैलिडेशन, सुरक्षा और उन्नत तकनीकों के लिए सर्वोत्तम प्रथाओं पर ध्यान केंद्रित किया गया है। हम व्यावहारिक उदाहरणों का पता लगाएंगे और आपको मजबूत और स्केलेबल वेब एप्लीकेशन बनाने में मदद करने के लिए कार्रवाई योग्य अंतर्दृष्टि प्रदान करेंगे।
Next.js सर्वर एक्शन क्या हैं?
सर्वर एक्शन एसिंक्रोनस फ़ंक्शन हैं जो सर्वर पर चलते हैं और सीधे रिएक्ट कंपोनेंट्स से बुलाए जा सकते हैं। वे फॉर्म सबमिशन और डेटा म्यूटेशन को संभालने के लिए पारंपरिक एपीआई रूट्स की आवश्यकता को समाप्त करते हैं, जिसके परिणामस्वरूप सरलीकृत कोड, बेहतर सुरक्षा और बढ़ी हुई परफॉर्मेंस मिलती है। सर्वर एक्शन रिएक्ट सर्वर कंपोनेंट्स (RSCs) हैं, जिसका अर्थ है कि वे सर्वर पर निष्पादित होते हैं, जिससे तेज प्रारंभिक पेज लोड और बेहतर SEO होता है।
सर्वर एक्शन के मुख्य लाभ:
- सरलीकृत कोड: अलग एपीआई रूट्स की आवश्यकता को समाप्त करके बॉयलरप्लेट कोड को कम करें।
- बेहतर सुरक्षा: सर्वर-साइड निष्पादन क्लाइंट-साइड कमजोरियों को कम करता है।
- बढ़ी हुई परफॉर्मेंस: तेज प्रतिक्रिया समय के लिए सीधे सर्वर पर डेटा म्यूटेशन निष्पादित करें।
- अनुकूलित SEO: बेहतर सर्च इंजन इंडेक्सिंग के लिए सर्वर-साइड रेंडरिंग का लाभ उठाएं।
- टाइप सेफ्टी: टाइपस्क्रिप्ट के साथ एंड-टू-एंड टाइप सेफ्टी से लाभ उठाएं।
अपना Next.js 14 प्रोजेक्ट सेट अप करना
सर्वर एक्शन में गोता लगाने से पहले, सुनिश्चित करें कि आपके पास Next.js 14 प्रोजेक्ट सेट अप है। यदि आप शुरुआत से शुरू कर रहे हैं, तो निम्न कमांड का उपयोग करके एक नया प्रोजेक्ट बनाएं:
npx create-next-app@latest my-next-app
सुनिश्चित करें कि आपका प्रोजेक्ट सर्वर कंपोनेंट्स और एक्शन का पूरा लाभ उठाने के लिए app
डायरेक्टरी संरचना का उपयोग कर रहा है।
सर्वर एक्शन के साथ बेसिक फॉर्म हैंडलिंग
आइए एक सरल उदाहरण से शुरू करें: एक फॉर्म जो डेटाबेस में एक नया आइटम बनाने के लिए डेटा सबमिट करता है। हम एक इनपुट फ़ील्ड और एक सबमिट बटन के साथ एक सरल फॉर्म का उपयोग करेंगे।
उदाहरण: एक नया आइटम बनाना
सबसे पहले, अपने रिएक्ट कंपोनेंट के भीतर एक सर्वर एक्शन फ़ंक्शन को परिभाषित करें। यह फ़ंक्शन सर्वर पर फॉर्म सबमिशन लॉजिक को संभालेगा।
// app/components/CreateItemForm.tsx
'use client';
import { useState } from 'react';
async function createItem(formData: FormData) {
'use server'
const name = formData.get('name') as string;
// डेटाबेस इंटरैक्शन का अनुकरण करें
console.log('Creating item:', name);
await new Promise((resolve) => setTimeout(resolve, 1000)); // लेटेंसी का अनुकरण करें
console.log('Item created successfully!');
}
export default function CreateItemForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
await createItem(formData);
setIsSubmitting(false);
}
return (
);
}
स्पष्टीकरण:
'use client'
डायरेक्टिव इंगित करता है कि यह एक क्लाइंट कंपोनेंट है।createItem
फ़ंक्शन को'use server'
डायरेक्टिव के साथ चिह्नित किया गया है, जो यह दर्शाता है कि यह एक सर्वर एक्शन है।handleSubmit
फ़ंक्शन एक क्लाइंट-साइड फ़ंक्शन है जो सर्वर एक्शन को कॉल करता है। यह यूआई स्थिति को भी संभालता है जैसे सबमिशन के दौरान बटन को अक्षम करना।<form>
एलिमेंट काaction
प्रॉपhandleSubmit
फ़ंक्शन पर सेट है।formData.get('name')
विधि 'name' इनपुट फ़ील्ड का मान प्राप्त करती है।await new Promise
एक डेटाबेस ऑपरेशन का अनुकरण करता है और लेटेंसी जोड़ता है।
डेटा वैलिडेशन
डेटा की अखंडता सुनिश्चित करने और सुरक्षा कमजोरियों को रोकने के लिए डेटा वैलिडेशन महत्वपूर्ण है। सर्वर एक्शन सर्वर-साइड वैलिडेशन करने का एक उत्कृष्ट अवसर प्रदान करते हैं। यह दृष्टिकोण अकेले क्लाइंट-साइड वैलिडेशन से जुड़े जोखिमों को कम करने में मदद करता है।
उदाहरण: इनपुट डेटा को मान्य करना
वैलिडेशन लॉजिक को शामिल करने के लिए createItem
सर्वर एक्शन को संशोधित करें।
// app/components/CreateItemForm.tsx
'use client';
import { useState } from 'react';
async function createItem(formData: FormData) {
'use server'
const name = formData.get('name') as string;
if (!name || name.length < 3) {
throw new Error('Item name must be at least 3 characters long.');
}
// डेटाबेस इंटरैक्शन का अनुकरण करें
console.log('Creating item:', name);
await new Promise((resolve) => setTimeout(resolve, 1000)); // लेटेंसी का अनुकरण करें
console.log('Item created successfully!');
}
export default function CreateItemForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
setErrorMessage(null);
try {
await createItem(formData);
} catch (error: any) {
setErrorMessage(error.message || 'An error occurred.');
} finally {
setIsSubmitting(false);
}
}
return (
{errorMessage && {errorMessage}
}
);
}
स्पष्टीकरण:
createItem
फ़ंक्शन अब जांचता है किname
मान्य है (कम से कम 3 अक्षर लंबा)।- यदि वैलिडेशन विफल रहता है, तो एक त्रुटि फेंकी जाती है।
handleSubmit
फ़ंक्शन को सर्वर एक्शन द्वारा फेंकी गई किसी भी त्रुटि को पकड़ने और उपयोगकर्ता को एक त्रुटि संदेश प्रदर्शित करने के लिए अपडेट किया गया है।
वैलिडेशन लाइब्रेरी का उपयोग करना
अधिक जटिल वैलिडेशन परिदृश्यों के लिए, निम्न जैसी वैलिडेशन लाइब्रेरी का उपयोग करने पर विचार करें:
- Zod: एक टाइपस्क्रिप्ट-फर्स्ट स्कीमा डिक्लेरेशन और वैलिडेशन लाइब्रेरी।
- Yup: मानों को पार्स करने, मान्य करने और बदलने के लिए एक जावास्क्रिप्ट स्कीमा बिल्डर।
यहाँ Zod का उपयोग करके एक उदाहरण दिया गया है:
// app/utils/validation.ts
import { z } from 'zod';
export const CreateItemSchema = z.object({
name: z.string().min(3, 'Item name must be at least 3 characters long.'),
});
// app/components/CreateItemForm.tsx
'use client';
import { useState } from 'react';
import { CreateItemSchema } from '../utils/validation';
async function createItem(formData: FormData) {
'use server'
const name = formData.get('name') as string;
const validatedFields = CreateItemSchema.safeParse({ name });
if (!validatedFields.success) {
return { errors: validatedFields.error.flatten().fieldErrors };
}
// डेटाबेस इंटरैक्शन का अनुकरण करें
console.log('Creating item:', name);
await new Promise((resolve) => setTimeout(resolve, 1000)); // लेटेंसी का अनुकरण करें
console.log('Item created successfully!');
}
export default function CreateItemForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
setErrorMessage(null);
try {
await createItem(formData);
} catch (error: any) {
setErrorMessage(error.message || 'An error occurred.');
} finally {
setIsSubmitting(false);
}
}
return (
{errorMessage && {errorMessage}
}
);
}
स्पष्टीकरण:
CreateItemSchema
Zod का उपयोग करकेname
फ़ील्ड के लिए वैलिडेशन नियम परिभाषित करता है।safeParse
विधि इनपुट डेटा को मान्य करने का प्रयास करती है। यदि वैलिडेशन विफल रहता है, तो यह त्रुटियों के साथ एक ऑब्जेक्ट लौटाता है।errors
ऑब्जेक्ट में वैलिडेशन विफलताओं के बारे में विस्तृत जानकारी होती है।
सुरक्षा संबंधी विचार
सर्वर एक्शन सर्वर पर कोड निष्पादित करके सुरक्षा बढ़ाते हैं, लेकिन आपके एप्लीकेशन को सामान्य खतरों से बचाने के लिए सुरक्षा सर्वोत्तम प्रथाओं का पालन करना अभी भी महत्वपूर्ण है।
क्रॉस-साइट रिक्वेस्ट फोर्जरी (CSRF) को रोकना
CSRF हमले उस भरोसे का फायदा उठाते हैं जो एक वेबसाइट उपयोगकर्ता के ब्राउज़र में रखती है। CSRF हमलों को रोकने के लिए, CSRF सुरक्षा तंत्र लागू करें।
Next.js सर्वर एक्शन का उपयोग करते समय स्वचालित रूप से CSRF सुरक्षा को संभालता है। फ्रेमवर्क प्रत्येक फॉर्म सबमिशन के लिए एक CSRF टोकन उत्पन्न और मान्य करता है, यह सुनिश्चित करता है कि अनुरोध आपके एप्लीकेशन से उत्पन्न हुआ है।
उपयोगकर्ता प्रमाणीकरण और प्राधिकरण को संभालना
सुनिश्चित करें कि केवल अधिकृत उपयोगकर्ता ही कुछ क्रियाएं कर सकते हैं। संवेदनशील डेटा और कार्यक्षमता की सुरक्षा के लिए प्रमाणीकरण और प्राधिकरण तंत्र लागू करें।
यहाँ NextAuth.js का उपयोग करके एक सर्वर एक्शन को सुरक्षित करने का एक उदाहरण है:
// app/components/CreateItemForm.tsx
'use client';
import { useState } from 'react';
import { getServerSession } from 'next-auth';
import { authOptions } from '../../app/api/auth/[...nextauth]/route';
async function createItem(formData: FormData) {
'use server'
const session = await getServerSession(authOptions);
if (!session) {
throw new Error('Unauthorized');
}
const name = formData.get('name') as string;
// डेटाबेस इंटरैक्शन का अनुकरण करें
console.log('Creating item:', name, 'by user:', session.user?.email);
await new Promise((resolve) => setTimeout(resolve, 1000)); // लेटेंसी का अनुकरण करें
console.log('Item created successfully!');
}
export default function CreateItemForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
setErrorMessage(null);
try {
await createItem(formData);
} catch (error: any) {
setErrorMessage(error.message || 'An error occurred.');
} finally {
setIsSubmitting(false);
}
}
return (
{errorMessage && {errorMessage}
}
);
}
स्पष्टीकरण:
getServerSession
फ़ंक्शन उपयोगकर्ता की सत्र जानकारी प्राप्त करता है।- यदि उपयोगकर्ता प्रमाणित नहीं है (कोई सत्र नहीं), तो एक त्रुटि फेंकी जाती है, जिससे सर्वर एक्शन को निष्पादित होने से रोका जा सकता है।
इनपुट डेटा को सैनिटाइज़ करना
क्रॉस-साइट स्क्रिप्टिंग (XSS) हमलों को रोकने के लिए इनपुट डेटा को सैनिटाइज़ करें। XSS हमले तब होते हैं जब दुर्भावनापूर्ण कोड एक वेबसाइट में इंजेक्ट किया जाता है, जिससे संभावित रूप से उपयोगकर्ता डेटा या एप्लीकेशन की कार्यक्षमता से समझौता हो सकता है।
अपने सर्वर एक्शन में उपयोगकर्ता द्वारा प्रदान किए गए इनपुट को संसाधित करने से पहले उसे सैनिटाइज़ करने के लिए DOMPurify
या sanitize-html
जैसी लाइब्रेरी का उपयोग करें।
उन्नत तकनीकें
अब जब हमने मूल बातें कवर कर ली हैं, तो आइए सर्वर एक्शन का प्रभावी ढंग से उपयोग करने के लिए कुछ उन्नत तकनीकों का पता लगाएं।
ऑप्टिमिस्टिक अपडेट्स
ऑप्टिमिस्टिक अपडेट्स यूआई को तुरंत अपडेट करके एक बेहतर उपयोगकर्ता अनुभव प्रदान करते हैं, जैसे कि क्रिया सफल होगी, भले ही सर्वर इसकी पुष्टि न करे। यदि क्रिया सर्वर पर विफल हो जाती है, तो यूआई अपनी पिछली स्थिति में वापस आ जाता है।
// app/components/UpdateItemForm.tsx
'use client';
import { useState } from 'react';
async function updateItem(id: string, formData: FormData) {
'use server'
const name = formData.get('name') as string;
// डेटाबेस इंटरैक्शन का अनुकरण करें
console.log('Updating item:', id, 'with name:', name);
await new Promise((resolve) => setTimeout(resolve, 1000)); // लेटेंसी का अनुकरण करें
// विफलता का अनुकरण करें (प्रदर्शन उद्देश्यों के लिए)
const shouldFail = Math.random() < 0.5;
if (shouldFail) {
throw new Error('Failed to update item.');
}
console.log('Item updated successfully!');
return { name }; // अपडेट किया गया नाम लौटाएं
}
export default function UpdateItemForm({ id, initialName }: { id: string; initialName: string }) {
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
const [itemName, setItemName] = useState(initialName);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
setErrorMessage(null);
// ऑप्टिमिस्टिक रूप से यूआई को अपडेट करें
const newName = formData.get('name') as string;
setItemName(newName);
try {
const result = await updateItem(id, formData);
// यदि सफल होता है, तो अपडेट पहले से ही setItemName के माध्यम से यूआई में प्रतिबिंबित होता है
} catch (error: any) {
setErrorMessage(error.message || 'An error occurred.');
// त्रुटि पर यूआई को वापस लाएं
setItemName(initialName);
} finally {
setIsSubmitting(false);
}
}
return (
Current Name: {itemName}
{errorMessage && {errorMessage}
}
);
}
स्पष्टीकरण:
- सर्वर एक्शन को कॉल करने से पहले, यूआई को
setItemName
का उपयोग करके तुरंत नए आइटम नाम के साथ अपडेट किया जाता है। - यदि सर्वर एक्शन विफल हो जाता है, तो यूआई को मूल आइटम नाम पर वापस कर दिया जाता है।
डेटा को पुनः मान्य करना
सर्वर एक्शन द्वारा डेटा को संशोधित करने के बाद, आपको यह सुनिश्चित करने के लिए कैश्ड डेटा को फिर से मान्य करने की आवश्यकता हो सकती है कि यूआई नवीनतम परिवर्तनों को दर्शाता है। Next.js डेटा को फिर से मान्य करने के कई तरीके प्रदान करता है:
- पाथ को पुनः मान्य करें: किसी विशिष्ट पाथ के लिए कैश को पुनः मान्य करें।
- टैग को पुनः मान्य करें: किसी विशिष्ट टैग से जुड़े डेटा के लिए कैश को पुनः मान्य करें।
यहाँ एक नया आइटम बनाने के बाद एक पाथ को फिर से मान्य करने का एक उदाहरण है:
// app/components/CreateItemForm.tsx
'use client';
import { useState } from 'react';
import { revalidatePath } from 'next/cache';
async function createItem(formData: FormData) {
'use server'
const name = formData.get('name') as string;
// डेटाबेस इंटरैक्शन का अनुकरण करें
console.log('Creating item:', name);
await new Promise((resolve) => setTimeout(resolve, 1000)); // लेटेंसी का अनुकरण करें
console.log('Item created successfully!');
revalidatePath('/items'); // /items पाथ को पुनः मान्य करें
}
export default function CreateItemForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
setErrorMessage(null);
try {
await createItem(formData);
} catch (error: any) {
setErrorMessage(error.message || 'An error occurred.');
} finally {
setIsSubmitting(false);
}
}
return (
{errorMessage && {errorMessage}
}
);
}
स्पष्टीकरण:
revalidatePath('/items')
फ़ंक्शन/items
पाथ के लिए कैश को अमान्य कर देता है, यह सुनिश्चित करता है कि उस पाथ पर अगला अनुरोध नवीनतम डेटा प्राप्त करे।
सर्वर एक्शन के लिए सर्वोत्तम प्रथाएं
सर्वर एक्शन के लाभों को अधिकतम करने के लिए, निम्नलिखित सर्वोत्तम प्रथाओं पर विचार करें:
- सर्वर एक्शन को छोटा और केंद्रित रखें: सर्वर एक्शन को एक एकल, अच्छी तरह से परिभाषित कार्य करना चाहिए। पठनीयता और परीक्षण क्षमता बनाए रखने के लिए सर्वर एक्शन के भीतर जटिल तर्क से बचें।
- वर्णनात्मक नामों का उपयोग करें: अपने सर्वर एक्शन को वर्णनात्मक नाम दें जो स्पष्ट रूप से उनके उद्देश्य को इंगित करते हैं।
- त्रुटियों को शालीनता से संभालें: उपयोगकर्ता को सूचनात्मक प्रतिक्रिया प्रदान करने और एप्लीकेशन क्रैश को रोकने के लिए मजबूत त्रुटि हैंडलिंग लागू करें।
- डेटा को अच्छी तरह से मान्य करें: डेटा की अखंडता सुनिश्चित करने और सुरक्षा कमजोरियों को रोकने के लिए व्यापक डेटा वैलिडेशन करें।
- अपने सर्वर एक्शन को सुरक्षित करें: संवेदनशील डेटा और कार्यक्षमता की सुरक्षा के लिए प्रमाणीकरण और प्राधिकरण तंत्र लागू करें।
- प्रदर्शन का अनुकूलन करें: अपने सर्वर एक्शन के प्रदर्शन की निगरानी करें और तेज प्रतिक्रिया समय सुनिश्चित करने के लिए आवश्यकतानुसार उन्हें अनुकूलित करें।
- कैशिंग का प्रभावी ढंग से उपयोग करें: प्रदर्शन में सुधार और डेटाबेस लोड को कम करने के लिए Next.js के कैशिंग तंत्र का लाभ उठाएं।
सामान्य गलतियाँ और उनसे कैसे बचें
हालांकि सर्वर एक्शन कई फायदे प्रदान करते हैं, कुछ सामान्य गलतियाँ हैं जिनसे अवगत होना चाहिए:
- अत्यधिक जटिल सर्वर एक्शन: एक ही सर्वर एक्शन के अंदर बहुत अधिक तर्क रखने से बचें। जटिल कार्यों को छोटे, अधिक प्रबंधनीय कार्यों में तोड़ें।
- त्रुटि हैंडलिंग की उपेक्षा करना: अप्रत्याशित त्रुटियों को पकड़ने और उपयोगकर्ता को उपयोगी प्रतिक्रिया प्रदान करने के लिए हमेशा त्रुटि हैंडलिंग शामिल करें।
- सुरक्षा सर्वोत्तम प्रथाओं को अनदेखा करना: अपने एप्लीकेशन को XSS और CSRF जैसे सामान्य खतरों से बचाने के लिए सुरक्षा सर्वोत्तम प्रथाओं का पालन करें।
- डेटा को पुनः मान्य करना भूल जाना: सुनिश्चित करें कि आप यूआई को अद्यतित रखने के लिए डेटा को संशोधित करने वाले सर्वर एक्शन के बाद कैश्ड डेटा को फिर से मान्य करते हैं।
निष्कर्ष
Next.js 14 सर्वर एक्शन सीधे सर्वर पर फॉर्म सबमिशन और डेटा म्यूटेशन को संभालने का एक शक्तिशाली और कुशल तरीका प्रदान करते हैं। इस गाइड में उल्लिखित सर्वोत्तम प्रथाओं का पालन करके, आप मजबूत, सुरक्षित और प्रदर्शनशील वेब एप्लीकेशन बना सकते हैं। अपने कोड को सरल बनाने, सुरक्षा बढ़ाने और समग्र उपयोगकर्ता अनुभव में सुधार करने के लिए सर्वर एक्शन को अपनाएं। जैसे ही आप इन सिद्धांतों को एकीकृत करते हैं, अपने विकास विकल्पों के वैश्विक प्रभाव पर विचार करें। सुनिश्चित करें कि आपके फॉर्म और डेटा हैंडलिंग प्रक्रियाएं विविध अंतरराष्ट्रीय दर्शकों के लिए सुलभ, सुरक्षित और उपयोगकर्ता-अनुकूल हैं। समावेशिता के प्रति यह प्रतिबद्धता न केवल आपके एप्लीकेशन की उपयोगिता में सुधार करेगी बल्कि वैश्विक स्तर पर इसकी पहुंच और प्रभावशीलता को भी बढ़ाएगी।