یاد بگیرید چگونه از مسیرهای API در Next.js برای ساخت بکاندهای بدون سرور (serverless) مستقیماً در اپلیکیشن Next.js خود استفاده کنید. این راهنما همه چیز را، از راهاندازی اولیه تا تکنیکهای پیشرفته برای مدیریت احراز هویت، پایداری دادهها و موارد دیگر، پوشش میدهد.
مسیرهای API در Next.js: ساخت آسان بکاند شما
Next.js با ویژگیهای قدرتمند و ساختار شهودی خود، توسعه فرانتاند را متحول کرده است. اما آیا میدانستید که میتواند توسعه بکاند را نیز به طور قابل توجهی ساده کند؟ مسیرهای API در Next.js به شما این امکان را میدهند که اندپوینتهای API بدون سرور را مستقیماً در اپلیکیشن Next.js خود ایجاد کنید و در بسیاری از موارد نیاز به یک سرور بکاند مجزا را از بین ببرید. این راهنمای جامع شما را در فرآیند ساخت یک بکاند قوی و مقیاسپذیر با استفاده از مسیرهای API در Next.js راهنمایی میکند.
مسیرهای API در Next.js چه هستند؟
مسیرهای API توابع بدون سروری هستند که شما در دایرکتوری /pages/api
در پروژه Next.js خود ایجاد میکنید. این توابع درخواستهای HTTP ورودی را مدیریت کرده و پاسخها را برمیگردانند، دقیقاً مانند یک API بکاند سنتی. تفاوت اصلی این است که آنها به عنوان توابع بدون سرور (serverless functions) مستقر میشوند، به این معنی که نیازی به مدیریت سرورها یا زیرساخت ندارید.
آنها را به عنوان توابع بکاند سبک و بر حسب تقاضا در نظر بگیرید که به طور یکپارچه با فرانتاند Next.js شما ادغام شدهاند.
مزایای استفاده از مسیرهای API در Next.js
- توسعه سادهشده: کد فرانتاند و بکاند خود را در یک پروژه واحد و با استفاده از جاوااسکریپت یا تایپاسکریپت بنویسید. دیگر نیازی به جابجایی بین پروژهها و تکنولوژیهای مختلف نیست.
- معماری بدون سرور: از مقیاسپذیری، قابلیت اطمینان و صرفهجویی در هزینههای محاسبات بدون سرور بهرهمند شوید. فقط برای منابعی که مصرف میکنید هزینه پرداخت کنید.
- استقرار آسان: کل اپلیکیشن خود (فرانتاند و بکاند) را با یک دستور واحد با استفاده از پلتفرمهایی مانند Vercel یا Netlify مستقر کنید.
- امنیت داخلی: Next.js و پلتفرمهای بدون سرور ویژگیهای امنیتی داخلی برای محافظت از اندپوینتهای API شما فراهم میکنند.
- عملکرد بهبودیافته: مسیرهای API میتوانند نزدیکتر به کاربران شما مستقر شوند، که باعث کاهش تأخیر و بهبود عملکرد میشود، به ویژه برای کاربران در سراسر جهان.
- قابلیت استفاده مجدد از کد: کد را بین فرانتاند و بکاند خود به اشتراک بگذارید، که باعث کاهش تکرار کد و بهبود قابلیت نگهداری میشود.
شروع کار با مسیرهای API در Next.js
بیایید یک مسیر API ساده ایجاد کنیم که یک پاسخ JSON برمیگرداند. ابتدا، مطمئن شوید که یک پروژه Next.js راهاندازی کردهاید. اگر نه، یکی با استفاده از دستور زیر ایجاد کنید:
npx create-next-app my-app
cd my-app
اکنون، فایلی به نام hello.js
در داخل دایرکتوری /pages/api
ایجاد کنید:
// pages/api/hello.js
export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' })
}
این کد یک مسیر API ساده را تعریف میکند که با یک شیء JSON حاوی نام "John Doe" پاسخ میدهد. برای دسترسی به این مسیر API، سرور توسعه Next.js خود را شروع کنید:
npm run dev
سپس، مرورگر خود را باز کرده و به آدرس http://localhost:3000/api/hello
بروید. شما باید پاسخ JSON زیر را ببینید:
{"name": "John Doe"}
درک کنترلکننده (Handler) مسیر API
تابع handler
در مسیر API شما دو آرگومان دریافت میکند:
req
: نمونهای ازhttp.IncomingMessage
است که شامل اطلاعاتی در مورد درخواست ورودی مانند متد درخواست، هدرها و بدنه است.res
: نمونهای ازhttp.ServerResponse
است که به شما امکان میدهد پاسخی را به کلاینت ارسال کنید.
شما میتوانید از این اشیاء برای مدیریت انواع مختلف درخواستها، خواندن دادهها از بدنه درخواست، تنظیم هدرهای پاسخ و ارسال انواع مختلف پاسخها استفاده کنید.
مدیریت متدهای مختلف HTTP
شما میتوانید از ویژگی req.method
برای تعیین متد HTTP درخواست ورودی استفاده کنید و متدهای مختلف را بر این اساس مدیریت کنید. برای مثال:
// pages/api/method.js
export default function handler(req, res) {
if (req.method === 'GET') {
// رسیدگی به درخواست GET
res.status(200).json({ message: 'این یک درخواست GET است' })
} else if (req.method === 'POST') {
// رسیدگی به درخواست POST
res.status(200).json({ message: 'این یک درخواست POST است' })
} else {
// رسیدگی به متدهای دیگر
res.status(405).json({ message: 'متد مجاز نیست' })
}
}
در این مثال، مسیر API هم درخواستهای GET و هم POST را مدیریت میکند. اگر متد درخواست GET باشد، با یک شیء JSON حاوی پیام "این یک درخواست GET است" پاسخ میدهد. اگر متد درخواست POST باشد، با یک شیء JSON حاوی پیام "این یک درخواست POST است" پاسخ میدهد. اگر متد درخواست هر چیز دیگری باشد، با خطای 405 Method Not Allowed پاسخ میدهد.
خواندن دادهها از بدنه درخواست
برای درخواستهای POST، PUT و PATCH، شما اغلب نیاز به خواندن دادهها از بدنه درخواست دارید. Next.js پشتیبانی داخلی برای تجزیه بدنههای درخواست JSON و URL-encoded فراهم میکند. برای تجزیه بدنه درخواست JSON، میتوانید از ویژگی req.body
استفاده کنید. برای مثال:
// pages/api/post.js
export default async function handler(req, res) {
if (req.method === 'POST') {
const { name, email } = req.body
// پردازش دادهها
console.log('Name:', name)
console.log('Email:', email)
res.status(200).json({ message: 'دادهها با موفقیت دریافت شدند' })
} else {
res.status(405).json({ message: 'متد مجاز نیست' })
}
}
برای آزمایش این مسیر API، میتوانید از ابزاری مانند Postman یا curl برای ارسال یک درخواست POST با بدنه JSON استفاده کنید:
curl -X POST -H "Content-Type: application/json" -d '{"name": "Jane Doe", "email": "jane.doe@example.com"}' http://localhost:3000/api/post
تنظیم هدرهای پاسخ
شما میتوانید از متد res.setHeader()
برای تنظیم هدرهای پاسخ استفاده کنید. این برای تنظیم نوع محتوا، کنترل کش و سایر اطلاعات مهم مفید است. برای مثال:
// pages/api/headers.js
export default function handler(req, res) {
res.setHeader('Content-Type', 'application/json')
res.setHeader('Cache-Control', 's-maxage=3600')
res.status(200).json({ message: 'Hello, world!' })
}
در این مثال، مسیر API هدر Content-Type
را به application/json
تنظیم میکند، که نشان میدهد پاسخ یک شیء JSON است. همچنین هدر Cache-Control
را به s-maxage=3600
تنظیم میکند، که به مرورگر و CDN میگوید پاسخ را تا 1 ساعت کش کند.
مدیریت خطا
مدیریت صحیح خطاها در مسیرهای API شما مهم است. میتوانید از بلوکهای try-catch برای گرفتن استثناها و ارسال پاسخهای خطای مناسب به کلاینت استفاده کنید. برای مثال:
// pages/api/error.js
export default async function handler(req, res) {
try {
// شبیهسازی یک خطا
throw new Error('مشکلی پیش آمد')
} catch (error) {
console.error(error)
res.status(500).json({ message: 'خطای داخلی سرور' })
}
}
در این مثال، مسیر API با پرتاب یک شیء Error
جدید، یک خطا را شبیهسازی میکند. بلوک catch خطا را گرفته، آن را در کنسول ثبت میکند و یک پاسخ 500 Internal Server Error به کلاینت ارسال میکند. برای محیطهای تولیدی، استفاده از یک سیستم لاگگیری قوی مانند Sentry یا Datadog را در نظر بگیرید.
اتصال به پایگاه داده
یکی از رایجترین موارد استفاده برای مسیرهای API، اتصال به پایگاه داده است. مسیرهای API در Next.js به طور یکپارچه با پایگاههای داده مختلف، از جمله موارد زیر، ادغام میشوند:
- MongoDB: یک پایگاه داده NoSQL محبوب که برای دادههای انعطافپذیر و بدون ساختار مناسب است.
- PostgreSQL: یک پایگاه داده رابطهای قدرتمند و منبعباز که به دلیل قابلیت اطمینان و یکپارچگی دادهها شناخته شده است.
- MySQL: یکی دیگر از پایگاههای داده رابطهای منبعباز محبوب که به طور گسترده برای برنامههای وب استفاده میشود.
- Firebase: یک پلتفرم مبتنی بر ابر که یک پایگاه داده بیدرنگ و خدمات دیگر را ارائه میدهد.
- FaunaDB: یک پایگاه داده بدون سرور که برای برنامههای جهانی طراحی شده است.
در اینجا مثالی از نحوه اتصال به پایگاه داده MongoDB در یک مسیر API در Next.js آورده شده است:
// pages/api/mongodb.js
import { MongoClient } from 'mongodb'
const uri = process.env.MONGODB_URI
const options = {}
let client
let clientPromise
if (!process.env.MONGODB_URI) {
throw new Error('لطفاً Mongo URI خود را به .env.local اضافه کنید')
}
if (process.env.NODE_ENV === 'development') {
// در حالت توسعه، از یک متغیر سراسری استفاده کنید تا مقدار
// در بارگذاریهای مجدد ماژول ناشی از HMR (Hot Module Replacement) حفظ شود.
if (!global._mongoClientPromise) {
client = new MongoClient(uri, options)
global._mongoClientPromise = client.connect()
}
clientPromise = global._mongoClientPromise
} else {
// در حالت تولید، بهتر است از یک متغیر سراسری استفاده نشود.
client = new MongoClient(uri, options)
clientPromise = client.connect()
}
// یک promise از MongoClient با حوزه ماژول صادر کنید. با انجام این کار در یک
// ماژول جداگانه، کلاینت میتواند به طور ایمن در چندین
// تابع استفاده مجدد شود. ببینید: https://github.com/vercel/next.js/blob/canary/examples/with-mongodb/lib/mongodb.js
export default async function handler(req, res) {
try {
const client = await clientPromise
const db = client.db(process.env.MONGODB_DB)
const collection = db.collection('users')
const users = await collection.find({}).toArray()
res.status(200).json({ users })
} catch (e) {
console.error(e)
res.status(500).json({ message: 'واکشی کاربران ناموفق بود' })
}
}
قبل از اجرای این کد، مطمئن شوید که بسته mongodb
را نصب کردهاید:
npm install mongodb
شما همچنین باید متغیرهای محیطی MONGODB_URI
و MONGODB_DB
را تنظیم کنید. این متغیرها باید در فایل .env.local
شما (یا در تنظیمات متغیر محیطی ارائهدهنده میزبانی شما برای تولید) تعریف شوند. MONGODB_URI
شامل رشته اتصال به پایگاه داده MongoDB شما است و MONGODB_DB
نام پایگاه داده را مشخص میکند.
احراز هویت و مجوزدهی
محافظت از مسیرهای API شما برای امنیت بسیار مهم است. مسیرهای API در Next.js را میتوان با استفاده از تکنیکهای مختلف احراز هویت و مجوزدهی، از جمله موارد زیر، امن کرد:
- توکنهای وب JSON (JWT): استانداردی برای انتقال امن اطلاعات بین طرفین به عنوان یک شیء JSON.
- کلیدهای API: روشی ساده برای محدود کردن دسترسی به اندپوینتهای API شما.
- OAuth: یک پروتکل تفویض اختیار که به کاربران اجازه میدهد به برنامههای شخص ثالث اجازه دسترسی به منابع خود را بدون به اشتراک گذاشتن اعتبارنامههایشان بدهند.
- NextAuth.js: یک راهحل احراز هویت کامل و منبعباز برای برنامههای Next.js.
در اینجا مثالی از نحوه محافظت از یک مسیر API با استفاده از احراز هویت JWT آورده شده است:
// pages/api/protected.js
import jwt from 'jsonwebtoken'
const secret = process.env.JWT_SECRET
export default function handler(req, res) {
const token = req.headers.authorization?.split(' ')[1]
if (!token) {
return res.status(401).json({ message: 'غیرمجاز' })
}
try {
const decoded = jwt.verify(token, secret)
// شیء "decoded" حاوی اطلاعات کاربری است که در توکن گنجانده شده است
// برای مثال: const userId = decoded.userId;
// ادامه پردازش درخواست
res.status(200).json({ message: 'دسترسی به منبع محافظتشده موفقیتآمیز بود' })
} catch (error) {
return res.status(401).json({ message: 'توکن نامعتبر است' })
}
}
قبل از اجرای این کد، مطمئن شوید که بسته jsonwebtoken
را نصب کردهاید:
npm install jsonwebtoken
شما همچنین باید متغیر محیطی JWT_SECRET
را تنظیم کنید. این باید یک کلید مخفی قوی و تولید شده به صورت تصادفی باشد که برای امضا و تأیید JWTها استفاده میشود. این کلید را به صورت امن ذخیره کنید و هرگز آن را در کد سمت کلاینت خود فاش نکنید.
میانافزار (Middleware)
در حالی که Next.js میانافزار سنتی برای مسیرهای API را به همان روش Express.js ارائه نمیدهد، میتوانید با بستهبندی کنترلکنندههای مسیر API خود با توابع قابل استفاده مجدد، به عملکرد مشابهی دست پیدا کنید. این به شما امکان میدهد کارهایی مانند موارد زیر را انجام دهید:
- احراز هویت: تأیید اعتبارنامههای کاربر قبل از اجازه دسترسی به اندپوینتهای API.
- مجوزدهی: بررسی اینکه آیا یک کاربر مجوزهای لازم برای انجام یک عمل خاص را دارد یا خیر.
- لاگگیری: ثبت درخواستهای ورودی و پاسخهای خروجی برای اهداف حسابرسی و اشکالزدایی.
- اعتبارسنجی: اعتبارسنجی دادههای درخواست برای اطمینان از مطابقت آنها با معیارهای خاص.
- محدودیت نرخ درخواست (Rate Limiting): محافظت از API شما در برابر سوءاستفاده با محدود کردن تعداد درخواستهایی که یک کاربر میتواند در یک دوره زمانی معین انجام دهد.
در اینجا مثالی از نحوه ایجاد یک میانافزار لاگگیری ساده آورده شده است:
// utils/middleware.js
export function withLogging(handler) {
return async function(req, res) {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`)
return handler(req, res)
}
}
برای استفاده از این میانافزار، به سادگی کنترلکننده مسیر API خود را با تابع withLogging
بستهبندی کنید:
// pages/api/logged.js
import { withLogging } from '../../utils/middleware'
async function handler(req, res) {
res.status(200).json({ message: 'این درخواست لاگ شد' })
}
export default withLogging(handler)
بهترین شیوهها برای ساخت مسیرهای API در Next.js
- مسیرهای API خود را کوچک و متمرکز نگه دارید. هر مسیر API باید یک وظیفه یا منبع خاص را مدیریت کند.
- از متغیرهای محیطی برای دادههای حساس استفاده کنید. هرگز اسرار یا کلیدهای API را در کد خود هاردکد نکنید.
- دادههای درخواست را برای جلوگیری از آسیبپذیریهای امنیتی اعتبارسنجی کنید. از کتابخانهای مانند Joi یا Yup برای اعتبارسنجی بدنههای درخواست استفاده کنید.
- خطاها را به درستی مدیریت کرده و پیامهای خطای آموزنده ارائه دهید. از بلوکهای try-catch استفاده کنید و خطاها را در یک مکان مرکزی ثبت کنید.
- از کش برای بهبود عملکرد استفاده کنید. دادههایی که به طور مکرر به آنها دسترسی پیدا میشود را برای کاهش بار پایگاه داده کش کنید.
- مسیرهای API خود را برای عملکرد و خطاها نظارت کنید. از ابزار نظارتی مانند Sentry یا Datadog برای پیگیری سلامت API خود استفاده کنید.
- مسیرهای API خود را با استفاده از ابزاری مانند Swagger یا OpenAPI مستند کنید. این کار استفاده از API شما را برای سایر توسعهدهندگان آسانتر میکند.
- استفاده از TypeScript برای ایمنی نوع (type safety) را در نظر بگیرید. TypeScript میتواند به شما کمک کند تا خطاها را زودتر تشخیص دهید و قابلیت نگهداری کد خود را بهبود بخشید.
- از ابتدا به بینالمللیسازی (i18n) فکر کنید. اگر برنامه شما توسط کاربران کشورهای مختلف استفاده خواهد شد، مسیرهای API خود را برای پشتیبانی از چندین زبان و ارز طراحی کنید. به عنوان مثال، اندپوینتهای API برای تجارت الکترونیک ممکن است نیاز به مدیریت نرخهای مالیاتی و هزینههای حمل و نقل مختلف بر اساس مکان کاربر داشته باشند.
- پیکربندی مناسب CORS (Cross-Origin Resource Sharing) را پیادهسازی کنید. این امر زمانی که API شما از دامنهای متفاوت از برنامه Next.js شما قابل دسترسی است، حیاتی است. CORS را با دقت پیکربندی کنید تا فقط به مبداهای مجاز اجازه دسترسی به منابع API شما را بدهد.
تکنیکهای پیشرفته
کارهای پسزمینه (Background Jobs)
برای کارهای طولانیمدت که نباید پاسخ API را مسدود کنند، استفاده از کارهای پسزمینه را در نظر بگیرید. میتوانید از کتابخانههایی مانند BullMQ یا Bree برای مدیریت کارهای پسزمینه و پردازش آنها به صورت ناهمزمان استفاده کنید.
وبسوکتها (WebSockets)
برای برنامههای بیدرنگ، میتوانید از وبسوکتها در مسیرهای API Next.js خود استفاده کنید. کتابخانههایی مانند Socket.IO و ws ایجاد اتصالات پایدار بین کلاینت و سرور را آسان میکنند.
GraphQL
اگر به روشی انعطافپذیرتر و کارآمدتر برای واکشی دادهها نیاز دارید، استفاده از GraphQL را در نظر بگیرید. میتوانید از کتابخانههایی مانند Apollo Server یا Yoga برای ایجاد یک اندپوینت API GraphQL در برنامه Next.js خود استفاده کنید.
نتیجهگیری
مسیرهای API در Next.js روشی قدرتمند و راحت برای ساخت بکاندهای بدون سرور مستقیماً در برنامه Next.js شما فراهم میکنند. با بهرهگیری از مزایای معماری بدون سرور، میتوانید توسعه را ساده کرده، عملکرد را بهبود بخشید و هزینهها را کاهش دهید. چه در حال ساخت یک فرم تماس ساده باشید و چه یک پلتفرم تجارت الکترونیک پیچیده، مسیرهای API در Next.js میتوانند به شما در ایجاد یک بکاند قوی و مقیاسپذیر با سهولت کمک کنند. با درک قوی از اصول اولیه و به کارگیری بهترین شیوهها، میتوانید از این ابزار قدرتمند برای ایجاد برنامههای کارآمد، امن و قابل دسترس در سطح جهانی استفاده کنید.