مسیرهای API در Next.js را کاوش کنید و قابلیتهای توسعه فول-استک را در اپلیکیشنهای React خود فعال کنید. الگوها، بهترین شیوهها و استراتژیهای استقرار را بیاموزید.
مسیرهای API در Next.js: الگوهای توسعه فول-استک
Next.js با فراهم آوردن یک فریمورک قدرتمند برای ساخت اپلیکیشنهای وب با کارایی و مقیاسپذیری بالا، انقلابی در توسعه React ایجاد کرده است. یکی از ویژگیهای کلیدی آن، مسیرهای API (API Routes) است که به توسعهدهندگان امکان میدهد تا قابلیتهای بکاند را مستقیماً در پروژههای Next.js خود ایجاد کنند. این رویکرد، توسعه را سادهتر کرده، استقرار را آسانتر میسازد و قابلیتهای قدرتمند فول-استک را در اختیار قرار میدهد.
مسیرهای API در Next.js چه هستند؟
مسیرهای API در Next.js توابع بدون سروری (serverless) هستند که مستقیماً در دایرکتوری /pages/api
شما نوشته میشوند. هر فایل در این دایرکتوری به یک نقطه پایانی API (endpoint) تبدیل میشود و به طور خودکار درخواستهای HTTP را به تابع مربوطه مسیریابی میکند. این کار نیاز به یک سرور بکاند جداگانه را از بین میبرد، معماری اپلیکیشن شما را ساده کرده و هزینههای عملیاتی را کاهش میدهد.
آنها را مانند توابع بدون سرور کوچکی در نظر بگیرید که درون اپلیکیشن Next.js شما زندگی میکنند. آنها به درخواستهای HTTP مانند GET، POST، PUT، DELETE پاسخ میدهند و میتوانند با پایگاههای داده، APIهای خارجی و سایر منابع سمت سرور تعامل داشته باشند. نکته حیاتی این است که آنها فقط روی سرور اجرا میشوند، نه در مرورگر کاربر، و این امر امنیت دادههای حساس مانند کلیدهای API را تضمین میکند.
مزایای کلیدی مسیرهای API
- توسعه ساده: کد فرانتاند و بکاند را در یک پروژه بنویسید.
- معماری بدون سرور: از توابع بدون سرور برای مقیاسپذیری و بهرهوری هزینه استفاده کنید.
- استقرار آسان: فرانتاند و بکاند خود را با یک دستور واحد با هم مستقر کنید.
- عملکرد بهبود یافته: قابلیتهای رندر سمت سرور و واکشی داده، سرعت اپلیکیشن را افزایش میدهد.
- امنیت تقویتشده: دادههای حساس روی سرور باقی میمانند و از دسترسی در سمت کلاینت محافظت میشوند.
شروع کار با مسیرهای API
ایجاد یک مسیر API در Next.js بسیار ساده است. کافی است یک فایل جدید در دایرکتوری /pages/api
ایجاد کنید. نام فایل، مسیر route را تعیین میکند. برای مثال، ایجاد فایلی به نام /pages/api/hello.js
یک نقطه پایانی API قابل دسترس در /api/hello
ایجاد میکند.
مثال: یک API ساده برای خوشامدگویی
در اینجا یک مثال ساده از یک مسیر API آورده شده است که یک پاسخ JSON برمیگرداند:
// pages/api/hello.js
export default function handler(req, res) {
res.status(200).json({ message: 'سلام از مسیر API در Next.js!' });
}
این کد یک تابع ناهمزمان به نام handler
تعریف میکند که دو آرگومان دریافت میکند:
req
: یک نمونه ازhttp.IncomingMessage
به علاوه چند میانافزار از پیش ساخته شده.res
: یک نمونه ازhttp.ServerResponse
به علاوه چند تابع کمکی.
این تابع کد وضعیت HTTP را روی 200 (OK) تنظیم میکند و یک پاسخ JSON با یک پیام برمیگرداند.
مدیریت متدهای مختلف HTTP
شما میتوانید متدهای مختلف HTTP (GET, POST, PUT, DELETE, و غیره) را در مسیر API خود با بررسی ویژگی req.method
مدیریت کنید. این به شما امکان میدهد تا به راحتی APIهای RESTful ایجاد کنید.
// pages/api/todos.js
export default async function handler(req, res) {
if (req.method === 'GET') {
// واکشی تمام کارها از پایگاه داده
const todos = await fetchTodos();
res.status(200).json(todos);
} else if (req.method === 'POST') {
// ایجاد یک کار جدید
const newTodo = await createTodo(req.body);
res.status(201).json(newTodo);
} else {
// مدیریت متدهای پشتیبانی نشده
res.status(405).json({ message: 'متد مجاز نیست' });
}
}
این مثال نشان میدهد چگونه درخواستهای GET و POST را برای یک نقطه پایانی فرضی /api/todos
مدیریت کنید. همچنین شامل مدیریت خطا برای متدهای پشتیبانی نشده است.
الگوهای توسعه فول-استک با مسیرهای API
مسیرهای API در Next.js الگوهای مختلف توسعه فول-استک را ممکن میسازند. در اینجا برخی از موارد استفاده رایج آورده شده است:
۱. واکشی و دستکاری دادهها
مسیرهای API میتوانند برای واکشی دادهها از پایگاههای داده، APIهای خارجی یا سایر منابع داده استفاده شوند. همچنین میتوان از آنها برای دستکاری دادهها، مانند ایجاد، بهروزرسانی یا حذف رکوردها استفاده کرد.
مثال: واکشی دادههای کاربر از پایگاه داده
// pages/api/users/[id].js
import { query } from '../../../lib/db';
export default async function handler(req, res) {
const { id } = req.query;
try {
const results = await query(
'SELECT * FROM users WHERE id = ?',
[id]
);
if (results.length === 0) {
return res.status(404).json({ message: 'کاربر یافت نشد' });
}
res.status(200).json(results[0]);
} catch (error) {
console.error(error);
res.status(500).json({ message: 'خطای داخلی سرور' });
}
}
این مثال دادههای کاربر را بر اساس شناسه کاربری ارائه شده در URL از پایگاه داده واکشی میکند. از یک کتابخانه کوئری پایگاه داده (فرض میشود در lib/db
قرار دارد) برای تعامل با پایگاه داده استفاده میکند. به استفاده از کوئریهای پارامتردار برای جلوگیری از آسیبپذیریهای تزریق SQL توجه کنید.
۲. احراز هویت و مجوزدهی
مسیرهای API میتوانند برای پیادهسازی منطق احراز هویت و مجوزدهی استفاده شوند. میتوانید از آنها برای تأیید اعتبارنامههای کاربر، تولید توکنهای JWT و محافظت از منابع حساس استفاده کنید.
مثال: احراز هویت کاربر
// pages/api/login.js
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { query } from '../../lib/db';
export default async function handler(req, res) {
if (req.method === 'POST') {
const { email, password } = req.body;
try {
const results = await query(
'SELECT * FROM users WHERE email = ?',
[email]
);
if (results.length === 0) {
return res.status(401).json({ message: 'اطلاعات کاربری نامعتبر است' });
}
const user = results[0];
const passwordMatch = await bcrypt.compare(password, user.password);
if (!passwordMatch) {
return res.status(401).json({ message: 'اطلاعات کاربری نامعتبر است' });
}
const token = jwt.sign(
{ userId: user.id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
);
res.status(200).json({ token });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'خطای داخلی سرور' });
}
} else {
res.status(405).json({ message: 'متد مجاز نیست' });
}
}
این مثال کاربران را با مقایسه رمز عبور ارائه شده با رمز عبور هش شده ذخیره شده در پایگاه داده احراز هویت میکند. اگر اعتبارنامهها معتبر باشند، یک توکن JWT تولید کرده و آن را به کلاینت برمیگرداند. سپس کلاینت میتواند از این توکن برای احراز هویت در درخواستهای بعدی استفاده کند.
۳. مدیریت فرم و ارسال داده
مسیرهای API میتوانند برای مدیریت ارسال فرمها و پردازش دادههای ارسال شده از کلاینت استفاده شوند. این برای ایجاد فرمهای تماس، فرمهای ثبتنام و سایر عناصر تعاملی مفید است.
مثال: ارسال فرم تماس
// pages/api/contact.js
import { sendEmail } from '../../lib/email';
export default async function handler(req, res) {
if (req.method === 'POST') {
const { name, email, message } = req.body;
try {
await sendEmail({
to: 'admin@example.com',
subject: 'ارسال جدید از فرم تماس',
text: `نام: ${name}\nایمیل: ${email}\nپیام: ${message}`,
});
res.status(200).json({ message: 'ایمیل با موفقیت ارسال شد' });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'ارسال ایمیل ناموفق بود' });
}
} else {
res.status(405).json({ message: 'متد مجاز نیست' });
}
}
این مثال با ارسال یک ایمیل به مدیر، ارسال یک فرم تماس را مدیریت میکند. از یک کتابخانه ارسال ایمیل (فرض میشود در lib/email
قرار دارد) برای ارسال ایمیل استفاده میکند. شما باید admin@example.com
را با آدرس ایمیل واقعی گیرنده جایگزین کنید.
۴. وبهوکها و مدیریت رویدادها
مسیرهای API میتوانند برای مدیریت وبهوکها و پاسخ به رویدادها از سرویسهای خارجی استفاده شوند. این به شما امکان میدهد تا اپلیکیشن Next.js خود را با پلتفرمهای دیگر ادغام کرده و وظایف را خودکار کنید.
مثال: مدیریت یک وبهوک Stripe
// pages/api/stripe-webhook.js
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
export const config = {
api: {
bodyParser: false, // غیرفعال کردن تجزیه بدنه پیشفرض
},
};
async function buffer(req) {
const chunks = [];
for await (const chunk of req) {
chunks.push(chunk);
}
return Buffer.concat(chunks).toString();
}
export default async function handler(req, res) {
if (req.method === 'POST') {
const sig = req.headers['stripe-signature'];
let event;
try {
const buf = await buffer(req);
event = stripe.webhooks.constructEvent(buf, sig, process.env.STRIPE_WEBHOOK_SECRET);
} catch (err) {
console.log(`خطای وبهوک: ${err.message}`);
res.status(400).send(`خطای وبهوک: ${err.message}`);
return;
}
// رویداد را مدیریت کنید
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
console.log(`PaymentIntent برای ${paymentIntent.amount} موفقیتآمیز بود!`);
// سپس یک متد برای مدیریت پرداخت موفق تعریف و فراخوانی کنید.
// handlePaymentIntentSucceeded(paymentIntent);
break;
case 'payment_method.attached':
const paymentMethod = event.data.object;
// سپس یک متد برای مدیریت پیوست موفق یک PaymentMethod تعریف و فراخوانی کنید.
// handlePaymentMethodAttached(paymentMethod);
break;
default:
// نوع رویداد غیرمنتظره
console.log(`نوع رویداد مدیریت نشده ${event.type}.`);
}
// برای تأیید دریافت رویداد، یک پاسخ 200 برگردانید
res.status(200).json({ received: true });
} else {
res.setHeader('Allow', 'POST');
res.status(405).end('متد مجاز نیست');
}
}
این مثال یک وبهوک Stripe را با تأیید امضا و پردازش دادههای رویداد مدیریت میکند. این کد تجزیهکننده بدنه پیشفرض را غیرفعال کرده و از یک تابع بافر سفارشی برای خواندن بدنه خام درخواست استفاده میکند. غیرفعال کردن تجزیهکننده بدنه پیشفرض بسیار مهم است زیرا Stripe برای تأیید امضا به بدنه خام نیاز دارد. به یاد داشته باشید که نقطه پایانی وبهوک Stripe خود را در داشبورد Stripe پیکربندی کرده و متغیر محیطی STRIPE_WEBHOOK_SECRET
را تنظیم کنید.
بهترین شیوهها برای مسیرهای API
برای اطمینان از کیفیت و قابلیت نگهداری مسیرهای API خود، این بهترین شیوهها را دنبال کنید:
۱. کد خود را ماژولار کنید
از نوشتن مسیرهای API بزرگ و یکپارچه خودداری کنید. به جای آن، کد خود را به ماژولهای کوچکتر و قابل استفاده مجدد تقسیم کنید. این کار باعث میشود کد شما برای درک، تست و نگهداری آسانتر شود.
۲. مدیریت خطا را پیادهسازی کنید
خطاها را در مسیرهای API خود به درستی مدیریت کنید. از بلوکهای try...catch
برای گرفتن استثناها و برگرداندن پاسخهای خطای مناسب به کلاینت استفاده کنید. خطاها را برای کمک به اشکالزدایی و نظارت لاگ کنید.
۳. دادههای ورودی را اعتبارسنجی کنید
همیشه دادههای ورودی از کلاینت را برای جلوگیری از آسیبپذیریهای امنیتی و اطمینان از یکپارچگی دادهها اعتبارسنجی کنید. از کتابخانههای اعتبارسنجی مانند Joi یا Yup برای تعریف اسکیمای اعتبارسنجی و اعمال محدودیتهای داده استفاده کنید.
۴. از دادههای حساس محافظت کنید
دادههای حساس، مانند کلیدهای API و اطلاعات اتصال به پایگاه داده، را در متغیرهای محیطی ذخیره کنید. هرگز دادههای حساس را به مخزن کد خود کامیت نکنید.
۵. محدودیت نرخ (Rate Limiting) را پیادهسازی کنید
با پیادهسازی محدودیت نرخ، از مسیرهای API خود در برابر سوء استفاده محافظت کنید. این کار تعداد درخواستهایی را که یک کلاینت میتواند در یک بازه زمانی معین ارسال کند، محدود میکند. از کتابخانههای محدودکننده نرخ مانند express-rate-limit
یا limiter
استفاده کنید.
۶. کلیدهای API را امن نگه دارید
کلیدهای API را مستقیماً در کد سمت کلاینت قرار ندهید. همیشه درخواستها را از طریق مسیرهای API خود پروکسی کنید تا از کلیدهای API خود در برابر دسترسی غیرمجاز محافظت کنید. کلیدهای API را به صورت امن در متغیرهای محیطی روی سرور خود ذخیره کنید.
۷. از متغیرهای محیطی استفاده کنید
از هاردکد کردن مقادیر پیکربندی در کد خود خودداری کنید. به جای آن، از متغیرهای محیطی برای ذخیره تنظیمات پیکربندی استفاده کنید. این کار مدیریت اپلیکیشن شما را در محیطهای مختلف (توسعه، آزمایشی، تولید) آسانتر میکند.
۸. لاگگیری و نظارت
لاگگیری و نظارت را برای ردیابی عملکرد مسیرهای API خود پیادهسازی کنید. رویدادهای مهم، مانند خطاها، هشدارها و درخواستهای موفق را لاگ کنید. از ابزارهای نظارتی برای ردیابی معیارهایی مانند تأخیر درخواست، نرخ خطا و استفاده از منابع استفاده کنید. سرویسهایی مانند Sentry، Datadog یا New Relic میتوانند مفید باشند.
ملاحظات استقرار
مسیرهای API در Next.js برای استقرار بر روی پلتفرمهای بدون سرور طراحی شدهاند. گزینههای محبوب استقرار عبارتند از:
- Vercel: Vercel پلتفرم توصیه شده برای استقرار اپلیکیشنهای Next.js است. این پلتفرم ادغام یکپارچهای با Next.js فراهم کرده و به طور خودکار اپلیکیشن شما را برای بهترین عملکرد بهینهسازی میکند.
- Netlify: Netlify یکی دیگر از پلتفرمهای محبوب بدون سرور است که از استقرار Next.js پشتیبانی میکند. این پلتفرم ویژگیهای مشابهی با Vercel ارائه میدهد، مانند استقرار خودکار و ادغام با CDN.
- AWS Lambda: AWS Lambda یک سرویس محاسباتی بدون سرور است که به شما امکان میدهد کد را بدون تأمین یا مدیریت سرورها اجرا کنید. شما میتوانید مسیرهای API Next.js خود را به عنوان توابع Lambda با استفاده از ابزارهایی مانند Serverless Framework یا AWS SAM مستقر کنید.
- Google Cloud Functions: Google Cloud Functions یک محیط اجرایی بدون سرور است که به شما امکان میدهد سرویسهای ابری را ایجاد و متصل کنید. شما میتوانید مسیرهای API Next.js خود را به عنوان Cloud Functions با استفاده از ابزارهایی مانند Firebase CLI یا Google Cloud SDK مستقر کنید.
- Azure Functions: Azure Functions یک سرویس محاسباتی بدون سرور است که به شما امکان میدهد کد را بر حسب تقاضا و بدون مدیریت زیرساخت اجرا کنید. شما میتوانید مسیرهای API Next.js خود را به عنوان Azure Functions با استفاده از ابزارهایی مانند Azure Functions Core Tools یا Azure CLI مستقر کنید.
هنگام استقرار اپلیکیشن Next.js خود با مسیرهای API، اطمینان حاصل کنید که متغیرهای محیطی شما به درستی در پلتفرم استقرار پیکربندی شدهاند. همچنین، زمان شروع سرد (cold start) توابع بدون سرور را در نظر بگیرید که میتواند بر زمان پاسخ اولیه مسیرهای API شما تأثیر بگذارد. بهینهسازی کد و استفاده از تکنیکهایی مانند provisioned concurrency میتواند به کاهش مشکلات شروع سرد کمک کند.
نتیجهگیری
مسیرهای API در Next.js یک راه قدرتمند و راحت برای ساخت اپلیکیشنهای فول-استک با React فراهم میکنند. با بهرهگیری از توابع بدون سرور، میتوانید توسعه را ساده کرده، هزینههای عملیاتی را کاهش داده و عملکرد اپلیکیشن را بهبود بخشید. با پیروی از بهترین شیوههای ذکر شده در این مقاله، میتوانید مسیرهای API قوی و قابل نگهداری ایجاد کنید که به اپلیکیشنهای Next.js شما قدرت میبخشند.
چه در حال ساخت یک فرم تماس ساده باشید و چه یک پلتفرم تجارت الکترونیک پیچیده، مسیرهای API در Next.js میتوانند به شما در سادهسازی فرآیند توسعه و ارائه تجربیات کاربری استثنایی کمک کنند.