عندما قمت بإنشاء أول واجهة برمجة تطبيقات (API) إنتاجية لي، استخدمت Express.js واستغرق الإعداد حوالي ساعتين: القوالب الجاهزة (boilerplate)، والبرمجيات الوسيطة (middleware)، ومُعالِجات المسارات (route handlers)، وإعدادات TypeScript، وسكريبتات النشر. في الآونة الأخيرة، قمت بشحن واجهة برمجة تطبيقات REST كاملة في 20 دقيقة فقط باستخدام NitroJs. لا توجد سلاسل app.use()، ولا توجيه يدوي، ولا صداع نشر.
يوضح لك هذا الدليل كيف يلغي NitroJs الحاجة إلى القوالب الجاهزة مع منحك واجهة خلفية جاهزة للإنتاج تعمل في أي مكان، سواء Node أو Bun أو Deno أو بدون خادم (serverless) أو على الحافة (edge).
ما هو NitroJs ولماذا نستخدمه لواجهات برمجة التطبيقات الخلفية (Backend APIs)؟
NitroJs هي مجموعة أدوات خادم من نظام UnJS البيئي يتعامل مع واجهتك الخلفية كمنتج بناء (build artifact). بدلاً من كتابة خادم يرتبط بوقت تشغيل معين، تقوم بكتابة مُعالِجات المسارات (route handlers) ويقوم Nitro بتجميعها في حزمة محمولة. انشر نفس الكود على Node.js أو Cloudflare Workers أو Vercel أو حاوية Docker دون تغيير سطر واحد.

النموذج الذهني الأساسي: اكتب المسارات، وليس الخوادم. أنت تركز على منطق واجهة برمجة التطبيقات (API logic)؛ ويتولى Nitro التعامل مع HTTP، والبرمجيات الوسيطة (middleware)، والربط بالمنصات.
المزايا الرئيسية لواجهات برمجة التطبيقات الخلفية:
- بدون إعدادات: لا توجد قوالب جاهزة لـ
server.js - توجيه بنظام الملفات:
routes/users.get.tsيصبحGET /users - يدعم TypeScript بشكل طبيعي: أنواع مُستنتجة تلقائيًا من المُعالِجات
- نشر عالمي: بناء واحد، أهداف متعددة
- تخزين مؤقت مدمج: تخزين استجابات API في الذاكرة أو Redis أو Cloudflare KV
- طبقة تخزين: نظام ملفات مجرد للبيانات المؤقتة
بالنسبة لمطوري واجهة برمجة التطبيقات، هذا يعني أنك تقوم بالشحن بشكل أسرع وإعادة الهيكلة بشكل أقل عند تغيير البنية التحتية.
البدء: تثبيت NitroJs في 5 دقائق
الخطوة 1: تهيئة مشروع
# استخدام pnpm (موصى به)
pnpm dlx giget@latest nitro nitro-api-backend
# أو npm
npm create nitro@latest nitro-api-backend
# أو bun
bunx giget@latest nitro nitro-api-backend
يقوم هذا بنسخ قالب البداية الرسمي إلى nitro-api-backend.
الخطوة 2: استكشاف الهيكل
cd nitro-api-backend
tree -L 2
المخرجات:
├── server
│ ├── api
│ ├── routes
│ ├── tasks
│ └── middleware
├── nitro.config.ts
├── package.json
└── tsconfig.json
الدلائل الهامة:
server/api/: مسارات API (بدون واجهة مستخدم)server/routes/: مسارات كاملة المكدس (لـ SSR)server/middleware/: برمجيات وسيطة عامة (Global middleware)server/tasks/: وظائف خلفية (Background jobs)
بالنسبة لواجهة برمجة تطبيقات خلفية بحتة، تجاهل routes وضع كل شيء في api.
الخطوة 3: تشغيل خادم التطوير
pnpm install
pnpm dev
يبدأ Nitro على http://localhost:3000 مع إعادة التحميل السريع (hot reload). قم بتعديل ملف، ويعاد تشغيل الخادم في أقل من 200 مللي ثانية.

بناء أول نقطة نهاية API خاصة بك
مُعالِج GET بسيط
أنشئ server/api/users.get.ts:
// server/api/users.get.ts
export default defineEventHandler(() => {
return [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" }
];
});
يقوم Nitro تلقائيًا بتقديم هذا على GET /api/users. يوفر غلاف defineEventHandler السلامة النوعية (type safety) والوصول إلى سياق الطلب (request context).
مسار ديناميكي مع معاملات
أنشئ server/api/users/[id].get.ts:
// server/api/users/[id].get.ts
export default defineEventHandler((event) => {
const id = getRouterParam(event, 'id');
if (!id) {
throw createError({
statusCode: 400,
statusMessage: 'User ID is required'
});
}
return {
id: Number(id),
name: `User ${id}`,
email: `user${id}@example.com`
};
});
ادخل إلى GET /api/users/42 لترى { id: 42, name: "User 42", ... }.
POST مع نص JSON
أنشئ server/api/users.post.ts:
// server/api/users.post.ts
export default defineEventHandler(async (event) => {
const body = await readBody(event);
// Nitro parses JSON automatically
const { name, email } = body;
if (!name || !email) {
throw createError({
statusCode: 422,
statusMessage: 'Name and email are required'
});
}
// محاكاة إدراج قاعدة البيانات
const newUser = {
id: Math.floor(Math.random() * 1000),
name,
email,
createdAt: new Date().toISOString()
};
return newUser;
});
اختبرها:
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name":"Charlie","email":"charlie@example.com"}'
استجابات آمنة من حيث النوع (Type-Safe Responses)
يستنتج Nitro أنواع الاستجابات من قيم الإرجاع الخاصة بك. للعقود الصارمة، استخدم أنواعًا صريحة:
// server/api/products.get.ts
interface Product {
id: number;
name: string;
price: number;
inStock: boolean;
}
export default defineEventHandler<Product[]>(() => {
return [
{ id: 1, name: "Laptop", price: 1299.99, inStock: true },
{ id: 2, name: "Mouse", price: 29.99, inStock: false }
];
});
الآن تحصل العملاء الذين يستوردون نقطة النهاية هذه على IntelliSense كامل.
أنماط API المتقدمة
برمجيات وسيطة للمصادقة (Auth Middleware)
أنشئ server/middleware/auth.ts:
// server/middleware/auth.ts
export default defineEventHandler(async (event) => {
const protectedRoutes = ['/api/admin', '/api/users/me'];
if (protectedRoutes.some(route => event.path.startsWith(route))) {
const token = getHeader(event, 'authorization')?.replace('Bearer ', '');
if (!token || token !== process.env.API_SECRET) {
throw createError({
statusCode: 401,
statusMessage: 'Unauthorized'
});
}
}
});
تعمل البرمجيات الوسيطة قبل كل مسار. أضفها إلى nitro.config.ts:
// nitro.config.ts
export default defineNitroConfig({
srcDir: 'server',
runtimeConfig: {
apiSecret: process.env.API_SECRET
}
});
تخزين استجابات API مؤقتًا (Caching API Responses)
تخزين العمليات الحسابية المكلفة مؤقتًا لمدة 60 ثانية:
// server/api/stats.get.ts
export default defineCachedEventHandler(async () => {
const db = useStorage('data');
const users = await db.getItem('users') || [];
return {
totalUsers: users.length,
activeUsers: users.filter(u => u.lastSeen > Date.now() - 86400000).length
};
}, {
maxAge: 60, // ثانية
name: 'stats',
getKey: () => 'global-stats'
});
يتعامل Nitro مع إلغاء صلاحية التخزين المؤقت والتخزين (الذاكرة، Redis، أو Cloudflare KV بناءً على هدف النشر).
التعامل مع رفع الملفات
// server/api/upload.post.ts
export default defineEventHandler(async (event) => {
const files = await readMultipartFormData(event);
if (!files?.length) {
throw createError({ statusCode: 400, statusMessage: 'No files uploaded' });
}
const storage = useStorage('uploads');
const file = files[0];
await storage.setItem(file.filename, file.data);
return { success: true, filename: file.filename };
});
اختبر باستخدام:
curl -X POST http://localhost:3000/api/upload \
-F "file=@/path/to/image.jpg"
النشر: من التطوير المحلي إلى الإنتاج
البناء للإنتاج
pnpm build
يقوم Nitro بإنشاء دليل .output بنقاط دخول خاصة بالمنصة.
التشغيل على Node.js
node .output/server/index.mjs
لا يلزم وجود node_modules—النسخة المُبناة (build) تدمج كل شيء.
النشر إلى Cloudflare Workers
# تثبيت الإعداد المسبق (preset)
pnpm add -D nitro-preset-cloudflare-workers
# البناء مع الإعداد المسبق
NITRO_PRESET=cloudflare-workers pnpm build
# النشر
wrangler deploy .output
النشر إلى Vercel (بدون خادم - Serverless)
# Vercel يكتشف Nitro تلقائيًا
vercel
أو قم بتكوين nitro.config.ts:
export default defineNitroConfig({
preset: 'vercel-edge'
});
متغيرات البيئة
أنشئ .env محليًا، ثم استخدم لوحات تحكم المنصة في الإنتاج:
# .env
API_SECRET=dev-secret-key
DATABASE_URL=file:./dev.db
الوصول في المُعالِجات:
const config = useRuntimeConfig();
const secret = config.apiSecret;
حالات الاستخدام المتقدمة
WebSockets وأحداث إرسال الخادم (Server-Sent Events)
يدعم Nitro تقنية WebSockets عبر defineWebSocketHandler:
// server/api/ws.ts
export default defineWebSocketHandler({
open(peer) {
console.log('WebSocket connected:', peer);
},
message(peer, message) {
peer.send(`Echo: ${message.text()}`);
},
close(peer, details) {
console.log('WebSocket closed:', details);
}
});
يمكن الوصول إليه على ws://localhost:3000/api/ws.
المهام الخلفية
أنشئ server/tasks/cleanup.ts:
// server/tasks/cleanup.ts
export default defineCronHandler('0 2 * * *', async () => {
const db = useStorage('temp');
const keys = await db.getKeys();
for (const key of keys) {
const metadata = await db.getMeta(key);
if (metadata.expiresAt < Date.now()) {
await db.removeItem(key);
}
}
console.log('Cleanup completed');
});
يتم تشغيل هذا يوميًا في الساعة 2 صباحًا. انشره على منصة تدعم Cron (مثل Vercel، Netlify).
محركات سير العمل (Workflow Engines)
تكامل مع useWorkflow.dev للتنسيق المعقد:
// server/api/workflows/process.ts
import { createWorkflow } from '@useworkflow/sdk';
export default defineEventHandler(async (event) => {
const workflow = createWorkflow('data-pipeline', {
steps: [
{ id: 'fetch', run: 'https://api.example.com/data' },
{ id: 'transform', run: 'transform.js' },
{ id: 'store', run: async (data) => {
const storage = useStorage('results');
await storage.setItem('latest', data);
}}
]
});
await workflow.start();
return { status: 'started' };
});
سيناريوهات المطورين الواقعية
السيناريو 1: واجهة خلفية لموقع ثابت
انشر Nitro API على Cloudflare Workers يخدم بيانات JSON لموقع JAMstack ثابت. الطبقة المجانية تتعامل مع 100 ألف طلب/يوم.
السيناريو 2: API لتطبيق الجوال
أنشئ نقاط نهاية REST لتطبيق React Native. استخدم معالجة CORS المدمجة في Nitro:
// nitro.config.ts
export default defineNitroConfig({
routeRules: {
'/api/**': { cors: true }
}
});
السيناريو 3: بوابة الخدمات المصغرة (Microservices Gateway)
قم بتشغيل Nitro كبوابة API تجمع الخدمات المصغرة. استخدم $fetch لطلب الوكيل (proxy requests):
// server/api/aggregate.get.ts
export default defineEventHandler(async (event) => {
const [users, posts] = await Promise.all([
$fetch('https://users-service.internal/users'),
$fetch('https://posts-service.internal/posts')
]);
return { users, posts };
});
اختبر واجهات برمجة تطبيقات NitroJs الخاصة بك باستخدام Apidog
يقوم Nitro بإنشاء واجهات خلفية بسرعة، ولكن السرعة لا تعني شيئًا إذا تعطلت نقاط النهاية الخاصة بك. عندما تقوم بشحن POST /api/users جديد، قم باستيراد تعريف المسار إلى Apidog. يقوم بعكس هندسة نوع الإرجاع الخاص بمعالجك ويُنشئ اختبارات العقود تلقائيًا.

قم بتشغيلها في CI لاكتشاف التغييرات التي قد تؤدي إلى كسر (breaking changes) قبل أن يصاب فريق الواجهة الأمامية بالإحباط. البدء مجاني، وهو الحاجز الوقائي الذي يحتاجه تطوير Nitro السريع الخاص بك.
الأسئلة الشائعة
1. هل يمكن لـ Nitro أن يحل محل Express.js بالكامل؟
نعم. يتعامل Nitro مع التوجيه والبرمجيات الوسيطة والنشر بشكل أفضل. قم بالترحيل عن طريق نقل برمجيات Express الوسيطة إلى مكونات Nitro الإضافية والمسارات إلى server/api/.
2. كيف يتعامل Nitro مع اتصالات قاعدة البيانات؟
استخدم مكونات Nitro الإضافية لتهيئة تجمعات الاتصال عند بدء التشغيل. تقوم طبقة التخزين بتجريد التخزين المؤقت، ولكن بالنسبة لـ SQL، استخدم ORM الخاص بك (مثل Prisma، Drizzle).
3. هل Nitro جاهز للإنتاج؟
بالتأكيد. يستخدم Nuxt Nitro لملايين المواقع الإنتاجية. لقد تم اختباره بشكل مكثف ليتناسب مع التوسع.
4. هل يمكنني استخدام Nitro مع GraphQL؟
نعم. أضف معالج GraphQL في server/api/graphql.post.ts. استخدم أي مكتبة GraphQL لـ Node—فـ Nitro لا يقيدك.
5. ما الفرق بين Nitro و Hono؟
Hono هو موجه خفيف الوزن. Nitro هو مجموعة أدوات خادم كاملة مع بناء، وإعدادات مسبقة، وتخزين. استخدم Hono للخدمات المصغرة، و Nitro للواجهات الخلفية الكاملة.
الخلاصة
NitroJs يعيد التفكير في تطوير الواجهة الخلفية عن طريق تجميع واجهة برمجة التطبيقات الخاصة بك في قطعة أثرية محمولة. تحصل على توجيه بنظام الملفات، وسلامة TypeScript، ونشر عالمي بدون الحاجة إلى القوالب الجاهزة. قم ببناء واجهة برمجة تطبيقات REST التالية باستخدام Nitro، وتحقق منها باستخدام Apidog. سيشكرك مستقبلك عندما تقوم بالترحيل من Node إلى الحافة (edge) بسطر واحد من التكوين.
