Fastify لجافا سكريبت (Node.js): دليل شامل مع أمثلة عملية
1. ما هو Fastify ولماذا تستخدمه؟
Fastify هو إطار عمل ويب عالي الأداء لـ Node.js، مستوحى من Hapi و Express ولكنه يركز على السرعة واستهلاك منخفض للذاكرة. تم تطويره في عام 2016 بواسطة فريق NearForm، وأصبح منذ ذلك الحين أحد أسرع الحلول لبناء REST API والخدمات المصغرة وتطبيقات الويب باستخدام JavaScript/TypeScript.
السبب الرئيسي لاستخدام Fastify هو أداؤه المتميز. وفقًا للاختبارات، يمكنه معالجة طلبات أكثر بنسبة 30-40% في الثانية مقارنة بـ Express مع نفس استهلاك الموارد. يتم تحقيق ذلك من خلال البنية غير المتزامنة القائمة على Node.js streams، وتحليل JSON الفعال (عبر fast-json-stringify)، وموجه مسارات محسّن يعتمد على Radix Tree (شجرة بادئة مضغوطة).
بالإضافة إلى السرعة، يقدم Fastify التحقق المدمج من المخططات عبر JSON Schema، والتخزين المؤقت التلقائي للردود، ودعم TypeScript بشكل افتراضي، ونظام إضافات قابل للتوسع، ووثائق ممتازة. هذا يجعله الخيار الأمثل للمشاريع الإنتاجية التي تتطلب الاستقرار والأداء المتوقع تحت الضغط.
2. التثبيت
يتم تثبيت Fastify عبر npm (Node Package Manager). تأكد من تثبيت Node.js الإصدار 18 أو أحدث (يُوصى باستخدام الإصدار LTS).
# التثبيت الأساسي
npm install fastify
# لاستخدام TypeScript (اختياري)
npm install -D @types/node typescript
# للعمل مع ملفات تعريف الارتباط والجلسات وغيرها
npm install @fastify/cookie @fastify/session
إذا كنت تستخدم yarn أو pnpm:
yarn add fastify
# أو
pnpm add fastify
3. البداية السريعة — مثال عملي بسيط
أنشئ ملفًا باسم server.js وقم بتشغيله باستخدام الأمر node server.js.
// server.js
const fastify = require('fastify')({
logger: true // تفعيل المسجل المدمج (pino)
});
// تعريف مسار GET /
fastify.get('/', async (request, reply) => {
return { hello: 'world' };
});
// تشغيل الخادم
const start = async () => {
try {
await fastify.listen({ port: 3000 });
console.log('الخادم يعمل على http://localhost:3000');
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();
بعد التشغيل، افتح المتصفح أو نفّذ الأمر curl http://localhost:3000. ستحصل على استجابة JSON: {"hello":"world"}.
4. أهم الطرق/الدوال/الفئات
4.1. fastify.get(path, options, handler)
التوقيع: fastify.get(path: string, opts?: RouteShorthandOptions, handler: RequestHandler)
الوظيفة: تسجيل معالج لطلبات HTTP GET على المسار المحدد.
fastify.get('/user/:id', async (request, reply) => {
const { id } = request.params;
return { userId: id, name: 'John Doe' };
});
4.2. fastify.post(path, options, handler)
التوقيع: fastify.post(path: string, opts?: RouteShorthandOptions, handler: RequestHandler)
الوظيفة: تسجيل معالج لطلبات HTTP POST. يقوم تلقائيًا بتحليل جسم الطلب (JSON، form-data، إلخ).
fastify.post('/user', async (request, reply) => {
const { name, email } = request.body;
// حفظ المستخدم في قاعدة البيانات...
return { status: 'created', name, email };
});
4.3. fastify.register(plugin, opts)
التوقيع: fastify.register(plugin: FastifyPluginAsync | FastifyPluginCallback, opts?: object)
الوظيفة: تسجيل إضافة (plugin) في تطبيق Fastify. يُستخدم لتقسيم التطبيق إلى وحدات مستقلة.
// routes/user.js
async function userRoutes(fastify, options) {
fastify.get('/user', async (request, reply) => {
return { users: [] };
});
}
// server.js
fastify.register(userRoutes);
4.4. fastify.put(path, options, handler)
الوظيفة: تسجيل معالج لطلبات HTTP PUT (لتحديث الموارد).
fastify.put('/user/:id', async (request, reply) => {
const { id } = request.params;
const { name } = request.body;
// تحديث بيانات المستخدم...
return { status: 'updated', id, name };
});
4.5. fastify.delete(path, options, handler)
الوظيفة: تسجيل معالج لطلبات HTTP DELETE (لحذف الموارد).
fastify.delete('/user/:id', async (request, reply) => {
const { id } = request.params;
// حذف المستخدم من قاعدة البيانات...
return { status: 'deleted', id };
});
4.6. fastify.setNotFoundHandler(handler)
الوظيفة: تعريف معالج مخصص للصفحات غير الموجودة (404).
fastify.setNotFoundHandler(async (request, reply) => {
reply.code(404);
return { error: 'الصفحة غير موجودة' };
});
4.7. fastify.setErrorHandler(handler)
الوظيفة: تعريف معالج مخصص للأخطاء العامة.
fastify.setErrorHandler(async (error, request, reply) => {
reply.code(error.statusCode || 500);
return { error: error.message || 'حدث خطأ داخلي' };
});
5. مثال متكامل: REST API بسيط
في هذا المثال، سننشئ REST API بسيطًا لإدارة قائمة من العناصر باستخدام Fastify.
// app.js
const fastify = require('fastify')({ logger: true });
let items = [
{ id: 1, name: 'عنصر 1' },
{ id: 2, name: 'عنصر 2' }
];
// GET - جلب جميع العناصر
fastify.get('/items', async (request, reply) => {
return items;
});
// GET - جلب عنصر حسب المعرف
fastify.get('/items/:id', async (request, reply) => {
const { id } = request.params;
const item = items.find(i => i.id === parseInt(id));
if (!item) {
reply.code(404);
return { error: 'العنصر غير موجود' };
}
return item;
});
// POST - إضافة عنصر جديد
fastify.post('/items', async (request, reply) => {
const { name } = request.body;
const newItem = { id: items.length + 1, name };
items.push(newItem);
reply.code(201);
return newItem;
});
// PUT - تحديث عنصر
fastify.put('/items/:id', async (request, reply) => {
const { id } = request.params;
const { name } = request.body;
const item = items.find(i => i.id === parseInt(id));
if (!item) {
reply.code(404);
return { error: 'العنصر غير موجود' };
}
item.name = name;
return { status: 'updated', item };
});
// DELETE - حذف عنصر
fastify.delete('/items/:id', async (request, reply) => {
const { id } = request.params;
items = items.filter(i => i.id !== parseInt(id));
return { status: 'deleted' };
});
const start = async () => {
try {
await fastify.listen({ port: 3000 });
console.log('الخادم يعمل على http://localhost:3000');
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();
يمكنك اختبار هذا الـ API باستخدام curl أو أي أداة مثل Postman.
6. نصائح إضافية
- التحقق من صحة البيانات: استخدم JSON Schema للتحقق من صحة البيانات الواردة تلقائيًا.
- الإضافات: استفد من الإضافات الرسمية مثل
@fastify/corsلدعم CORS و@fastify/swaggerلتوثيق API. - الأداء: قم بتفعيل وضع الإنتاج (
NODE_ENV=production) لتحسين الأداء. - التوثيق: استخدم
@fastify/swagger-uiلإنشاء واجهة توثيق تفاعلية لـ API الخاص بك.