Next.js یکی از فریمورکهای محبوب و پیشرفته برای توسعه برنامههای وب با استفاده از React است. در این مقاله آموزشی Next.js، قصد داریم به بررسی ویژگیهای پیشرفته در Next.js بپردازیم و جنبههای مختلف آن را از سطح مبتدی تا پیشرفته توضیح دهیم. این راهنما شامل بینالمللیسازی، احراز هویت و امنیت، Middleware، API Middleware، و Rate Limiting خواهد بود. این مقاله با توضیحات شفاف و مثالهای عملی، یادگیری را برای شما آسان خواهد کرد.
بینالمللیسازی (Internationalization)
یکی از ویژگیهای پیشرفته در Next.js پشتیبانی از بینالمللیسازی (i18n) است که امکان توسعه برنامههای چندزبانه را فراهم میکند. این قابلیت به توسعهدهندگان اجازه میدهد که برنامههای خود را برای کاربران با زبانهای مختلف قابل استفاده کنند و تجربهای بهینه برای هر زبان ارائه دهند.
پیکربندی i18n در Next.js
Next.js از تنظیمات داخلی برای پیکربندی i18n پشتیبانی میکند. برای شروع، فایل next.config.js را باز کرده و تنظیمات زیر را اضافه کنید:
module.exports = {
i18n: {
locales: ['en', 'fr', 'de'],
defaultLocale: 'en',
},
};
locales: لیستی از زبانهایی که برنامه از آنها پشتیبانی میکند.
defaultLocale: زبانی که به صورت پیشفرض انتخاب میشود.
این کد مسیرهای چندزبانه را به صورت خودکار مدیریت کرده و تجربهای هماهنگ برای کاربران ارائه میدهد.
مدیریت ترجمهها و زبانها
برای مدیریت ترجمهها، باید فایلهایی حاوی رشتههای متنی هر زبان ایجاد کنید. به عنوان مثال:
locales/en/common.json
{
"welcome": "Welcome to our website!"
}
locales/fr/common.json
{
"welcome": "Bienvenue sur notre site web!"
}
ساختار JSON ساده و قابل گسترش بوده و امکان افزودن سریع زبانهای جدید را فراهم میکند. همچنین میتوانید فایلهای جداگانهای برای بخشهای مختلف برنامه ایجاد کنید تا مدیریت ترجمهها آسانتر شود.
استفاده از کتابخانههای بینالمللیسازی مانند next-i18next
کتابخانه next-i18next فرآیند بینالمللیسازی را بهینه میکند. این ابزار سازگاری با SSR و SSG را فراهم کرده و امکان مدیریت دقیق ترجمهها را ارائه میدهد.
نصب و پیکربندی
کتابخانه را نصب کنید:
npm install next-i18next
فایل پیکربندی next-i18next.config.js را تنظیم کنید:
module.exports = {
i18n: {
locales: ['en', 'fr', 'de'],
defaultLocale: 'en',
},
};
در کامپوننتها از ترجمهها استفاده کنید:
import { useTranslation } from 'next-i18next';
const Home = () => {
const { t } = useTranslation('common');
return <h1>{t('welcome')}</h1>;
};
export default Home;
در این مثال، t(‘welcome’) با متن ترجمه شده جایگزین میشود.
مزایای next-i18next
سادگی: مدیریت ترجمهها در فایلهای JSON.
اتصال یکپارچه به Next.js: پشتیبانی کامل از ویژگیهای داخلی.
پشتیبانی از زبانهای متعدد: امکان مدیریت مسیرهای چندزبانه.
سازگاری کامل با SSR و SSG: ترجمهها با سرعت بالا بارگذاری میشوند.
بهینهسازی بینالمللیسازی
لود پویا: بارگذاری ترجمهها فقط در زمان نیاز برای بهبود عملکرد.
فشردهسازی فایلها: استفاده از gzip یا Brotli برای کاهش اندازه فایلها.
SEO چندزبانه: تنظیم مسیرها و متا دیتا برای زبانهای مختلف.
بهبود تجربه کاربری: ارائه زبان بر اساس تنظیمات مرورگر یا مکان جغرافیایی کاربر.
این تکنیکها امکان ارائه تجربهای بهینه برای کاربران در مناطق مختلف جهان را فراهم میکنند.
احراز هویت و امنیت
احراز هویت و امنیت یکی از مهمترین و پیشرفتهترین جنبههای توسعه برنامههای کاربردی وب است و Next.js ابزارها و قابلیتهای مختلفی برای اجرای آن ارائه میدهد. در این بخش، نحوه پیادهسازی احراز هویت و تضمین امنیت در برنامههای ساختهشده با Next.js را بررسی میکنیم. این فرایند شامل استفاده از JWT، OAuth، و سرویسهای احراز هویت خارجی است.
پیادهسازی احراز هویت با استفاده از JWT
JWT (JSON Web Token) یکی از روشهای محبوب برای مدیریت احراز هویت و تبادل اطلاعات امن بین کلاینت و سرور است. این روش به شما امکان میدهد اطلاعات کاربر را به صورت رمزنگاریشده و با امضای دیجیتال ارسال کنید.
ایجاد و مدیریت JWT در سرور
نصب کتابخانه JWT: ابتدا کتابخانه jsonwebtoken را نصب کنید.
npm install jsonwebtoken
ایجاد توکن در سرور: از این توکن برای شناسایی کاربران استفاده میشود.
const jwt = require('jsonwebtoken');
const token = jwt.sign({ userId: 123 }, 'your-secret-key', { expiresIn: '1h' });
console.log(token);
userId: اطلاعاتی که میخواهید در توکن ذخیره کنید.
your-secret-key: کلید محرمانه برای امضای توکن.
expiresIn: مدت اعتبار توکن (در اینجا ۱ ساعت).
احراز هویت توکن در سرور: هنگام دریافت درخواست از کلاینت، توکن را بررسی کنید.
const decoded = jwt.verify(token, 'your-secret-key'); console.log(decoded.userId);
ذخیره و ارسال JWT در کلاینت
ذخیرهسازی امن: ترجیحاً از کوکیهای HttpOnly برای ذخیره توکن استفاده کنید، زیرا این روش از حملات XSS جلوگیری میکند. اگر از LocalStorage استفاده میکنید، حتماً دادهها را رمزنگاری کنید.
ارسال توکن در درخواستها: توکن را در هدر Authorization ارسال کنید.
fetch('/api/data', {
headers: {
Authorization: `Bearer ${token}`,
},
});
استفاده از OAuth و سرویسهای احراز هویت
برای سادهسازی احراز هویت، میتوانید از ابزارهایی مانند Auth0، Firebase Authentication، یا Google OAuth استفاده کنید. این سرویسها راهحلهای آمادهای برای مدیریت ورود و خروج کاربران و همچنین محافظت از اطلاعات آنها ارائه میدهند.
نصب Auth0 SDK:
npm install @auth0/nextjs-auth0
تنظیم فایل .env:
AUTH0_SECRET=your-secret AUTH0_BASE_URL=http://localhost:3000 AUTH0_ISSUER_BASE_URL=https://your-domain.auth0.com AUTH0_CLIENT_ID=your-client-id AUTH0_CLIENT_SECRET=your-client-secret
تعریف API برای مدیریت ورود و خروج:
import { handleAuth } from '@auth0/nextjs-auth0';
export default handleAuth();
بهترین شیوههای امنیتی در Next.js
CORS: محدود کردن منابع به دامنههای مجاز با استفاده از هدرهای CORS.
CSRF Protection: استفاده از توکنهای CSRF برای جلوگیری از حملات CSRF.
XSS Protection: پاکسازی دادههای ورودی و استفاده از ابزارهایی مانند DOMPurify برای جلوگیری از حملات XSS.
HTTPS: اطمینان حاصل کنید که تمام ترافیک بین کلاینت و سرور از طریق HTTPS رمزنگاری شده است.
Helmet.js: از این ابزار برای تنظیم هدرهای امنیتی مناسب استفاده کنید.
مدیریت نشستهای کاربری
مدیریت نشستهای کاربران یکی از جنبههای کلیدی امنیت است. برای این منظور، از کوکیهای امن با گزینههای زیر استفاده کنید:
HttpOnly: جلوگیری از دسترسی جاوااسکریپت به کوکی.
Secure: فقط ارسال کوکیها در درخواستهای HTTPS.
SameSite: محدود کردن کوکیها به درخواستهای همان سایت برای جلوگیری از CSRF.
همچنین، حتماً نشستهای منقضیشده را به طور منظم پاکسازی کنید.
مانیتورینگ و بهبود امنیت
برای نظارت بر فعالیتها و شناسایی تهدیدات:
از ابزارهایی مانند Sentry برای گزارشدهی خطاها استفاده کنید.
از Datadog یا New Relic برای مانیتورینگ و شناسایی مشکلات عملکردی و امنیتی بهره بگیرید.
توصیههای نهایی
کلیدهای محرمانه را در فایلهای محیطی امن نگهداری کنید و هرگز آنها را در کد منتشر نکنید.
وابستگیهای پروژه را بهصورت منظم بهروزرسانی و برای آسیبپذیریها بررسی کنید.
تستهای امنیتی مداوم انجام دهید و از ابزارهایی مانند OWASP ZAP برای اسکن برنامه خود استفاده کنید.
با رعایت این شیوهها و ابزارها، میتوانید برنامهای امن، قابل اعتماد، و مطابق با استانداردهای روز در Next.js ایجاد کنید.
Middleware در Next.js
معرفی Middleware و کاربردهای آن
Middleware در Next.js یک لایه میانی بین درخواست و پاسخ است که به شما اجازه میدهد منطق دلخواهی را قبل از رسیدن درخواست به صفحه یا API Route اجرا کنید. این قابلیت در نسخه 12 به بعد Next.js معرفی شده است و امکان پردازش درخواستها را بدون نیاز به رندر کامل صفحه فراهم میکند. به عبارت دیگر، Middleware به شما امکان مدیریت سطح بالا بر روی درخواستها و پاسخها را میدهد.
کاربردهای رایج Middleware عبارتاند از:
احراز هویت: بررسی توکنهای JWT یا کوکیهای موجود در درخواستها.
ریدایرکتها و بازنویسی: هدایت کاربران به مسیرهای مناسب یا تغییر مسیرهای درخواست به URLهای دیگر.
فیلتر کردن درخواستها: محدود کردن دسترسی به منابع خاص براساس نوع درخواست یا نقش کاربر.
شمارشگر درخواستها: ردیابی تعداد درخواستها برای اهداف آنالیتیک یا محدودسازی نرخ دسترسی.
استفاده از Middleware برای مدیریت درخواستها
Middlewareها در Next.js در پوشهای به نام middleware یا فایل middleware.js تعریف میشوند و در سطح روت پروژه قابل اجرا هستند. این فایل باید در ریشه پروژه یا نزدیکترین دایرکتوری مرتبط با مسیری که نیاز به Middleware دارد قرار گیرد.
Middleware به صورت پیشفرض بر روی تمامی درخواستهایی که از سرور عبور میکنند اعمال میشود. همچنین، میتوانید از الگوهای مسیریابی استفاده کنید تا آن را به درخواستهای خاص محدود کنید.
مثال ساختاری برای Middleware:
import { NextResponse } from 'next/server';
export function middleware(req) {
const url = req.nextUrl.clone();
// مثال: ریدایرکت کاربرانی که لاگین نکردهاند
if (!req.cookies.has('token') && url.pathname !== '/login') {
url.pathname = '/login';
return NextResponse.redirect(url);
}
// ادامه درخواست
return NextResponse.next();
}
پیادهسازی قابلیتهای مانند احراز هویت و ریدایرکتها با Middleware
یکی از کاربردهای کلیدی Middleware، احراز هویت و مدیریت دسترسی کاربران است. میتوانید با بررسی کوکیها یا هدرهای ارسالی در درخواست، سطح دسترسی کاربران را ارزیابی کرده و آنها را به مسیرهای مناسب هدایت کنید.
مثال 1:احراز هویت فرض کنید قصد دارید تنها کاربران لاگین شده به یک مسیر خاص دسترسی داشته باشند:
import { NextResponse } from 'next/server';
export function middleware(req) {
const url = req.nextUrl.clone();
const token = req.cookies.get('authToken');
if (!token && url.pathname.startsWith('/dashboard')) {
url.pathname = '/login';
return NextResponse.redirect(url);
}
return NextResponse.next();
}
مثال 2: ریدایرکت شرطی ریدایرکت کاربران به زیر دامنهای خاص براساس زبان مرورگر:
export function middleware(req) {
const lang = req.headers.get('accept-language')?.split(',')[0];
const url = req.nextUrl.clone();
if (lang === 'fa') {
url.hostname = 'fa.example.com';
return NextResponse.redirect(url);
}
return NextResponse.next();
}
Middleware در Next.js انعطافپذیری بالایی دارد و میتواند بخشی از استراتژی معماری شما برای مدیریت موثرتر درخواستها و بهبود تجربه کاربر باشد.
API Middleware و Rate Limiting
پیادهسازی Rate Limiting در API Routes
Rate Limiting یک استراتژی برای کنترل تعداد درخواستهایی است که یک کاربر یا کلاینت میتواند در بازه زمانی مشخص به یک سرور ارسال کند. این تکنیک برای جلوگیری از سوءاستفاده، حملات DDoS، یا کاهش فشار بر سرور استفاده میشود.
در Next.js، شما میتوانید با استفاده از Middleware یا توابع سفارشی، Rate Limiting را در API Routes پیادهسازی کنید.
روش پیادهسازی ساده: یک پیادهسازی پایه برای محدود کردن درخواستها میتواند شامل استفاده از یک حافظه درونبرنامه (مثل یک Map یا Cache) باشد:
let requests = new Map();
export default function handler(req, res) {
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
const currentTime = Date.now();
if (!requests.has(ip)) {
requests.set(ip, []);
}
const timestamps = requests.get(ip);
const oneMinuteAgo = currentTime - 60000; // یک دقیقه قبل
// حذف درخواستهای قدیمی
while (timestamps.length && timestamps[0] < oneMinuteAgo) {
timestamps.shift();
}
// بررسی محدودیت
if (timestamps.length >= 10) { // حداکثر 10 درخواست در دقیقه
return res.status(429).json({ message: "Too many requests. Please try again later." });
}
// ثبت درخواست جدید
timestamps.push(currentTime);
requests.set(ip, timestamps);
return res.status(200).json({ message: "Request successful" });
}
روش پیشرفتهتر با Redis یا Rate Limiting Libraries: برای برنامههای مقیاسپذیر، میتوانید از ابزارهایی مانند Redis برای ذخیره اطلاعات درخواستها استفاده کنید یا از کتابخانههای آماده مثل rate-limiter-flexible بهره ببرید.
مثال با Redis:
import { RateLimiterRedis } from 'rate-limiter-flexible';
import Redis from 'ioredis';
const redisClient = new Redis();
const rateLimiter = new RateLimiterRedis({
storeClient: redisClient,
keyPrefix: 'rate-limit',
points: 10, // تعداد درخواستهای مجاز
duration: 60, // در بازه 60 ثانیه
});
export default async function handler(req, res) {
try {
await rateLimiter.consume(req.headers['x-forwarded-for'] || req.connection.remoteAddress);
res.status(200).json({ message: "Request successful" });
} catch {
res.status(429).json({ message: "Too many requests. Please try again later." });
}
}
مدیریت لاگها و مانیتورینگ API
برای اطمینان از عملکرد صحیح APIها و تحلیل مشکلات، مدیریت لاگها و مانیتورینگ ضروری است. این فرآیند شامل ثبت اطلاعات مربوط به درخواستها، خطاها، و معیارهای عملکردی میشود.
ثبت لاگها
میتوانید از کتابخانههایی مانند winston یا pino برای ثبت لاگهای قابل خواندن و ساختاریافته استفاده کنید.
مثال با winston:
import winston from 'winston';
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
],
});
export default function handler(req, res) {
logger.info(`Request received: ${req.method} ${req.url}`);
try {
// فرآیندهای API
res.status(200).json({ message: "Success" });
} catch (error) {
logger.error(`Error occurred: ${error.message}`);
res.status(500).json({ message: "Internal Server Error" });
}
}
مانیتورینگ API
برای مانیتورینگ درخواستها و عملکرد APIها، ابزارهای زیر میتوانند مفید باشند:
APM (Application Performance Monitoring):
ابزارهایی مانند Datadog, New Relic, و Elastic APM به شما امکان بررسی دقیق عملکرد API و تشخیص مشکلات را میدهند.
Prometheus و Grafana:
این ابزارها برای جمعآوری و نمایش معیارهای API مانند نرخ موفقیت، زمان پاسخدهی، و خطاها استفاده میشوند.
Sentry:
Sentry به شما کمک میکند تا ارورهای مربوط به API را ردیابی و تحلیل کنید.
نمونه مانیتورینگ ساده با Prometheus:
let requestCount = 0;
export default function handler(req, res) {
requestCount++;
console.log(`Request count: ${requestCount}`);
res.status(200).json({ message: "API monitored" });
}
ترکیب Rate Limiting و مدیریت لاگها با ابزارهای مانیتورینگ میتواند از استرس سرور جلوگیری کرده، امنیت API را افزایش داده و تجربه کاربری بهتری ارائه دهد. همچنین، استفاده از تکنیکهای مدرن و کتابخانههای بهینه، توسعه و مقیاسپذیری برنامه را تسهیل میکند.
نتیجهگیری
ویژگیهای پیشرفته در Next.js، از جمله بینالمللیسازی، احراز هویت و امنیت، Middleware و API Middleware، ابزارهای قدرتمندی را برای توسعهدهندگان فراهم میکنند تا برنامههای وب مدرن، امن و با کارایی بالا ایجاد کنند. این قابلیتها، به همراه امکاناتی مانند Rate Limiting و مدیریت لاگها، به شما کمک میکنند که تجربه کاربری بهتری ارائه دهید و در عین حال از منابع سرور خود به طور بهینه استفاده کنید. اگرچه یادگیری این ویژگیها نیازمند زمان و تمرین است، اما بهرهگیری از آنها به شما اجازه میدهد تا برنامههایی حرفهای و قابل اطمینان ایجاد کنید. برای یادگیری بیشتر، مستندات رسمی Next.js و منابع معرفی شده در این مقاله را بررسی کنید.
