تكوين تطبيقات TypeScript: من البسيط إلى المعقد
أي تطبيق حديث يتطلب إعدادات مرنة وآمنة. سواء كانت مفاتيح API، معلمات الاتصال بقاعدة البيانات، منافذ الخادم أو أعلام الميزات - يجب فصل التكوين عن الكود، وأن يكون سهل القراءة والتحقق من صحته عند بدء التشغيل. في عالم TypeScript، لهذه المهمة خصائصها: كتابة التكوين توفر الإكمال التلقائي وتمنع أخطاء وقت التشغيل. في هذه المقالة، سنستعرض أفضل الممارسات والمكتبات والأدوات الشائعة لإدارة تكوين تطبيقات TypeScript.
لماذا لا يجب استخدام process.env مباشرة؟
للوهلة الأولى، تبدو قراءة متغيرات البيئة عبر process.env حلاً بسيطاً. ومع ذلك، فإن هذا النهج له عيوب كبيرة:
- غياب الكتابة: جميع القيم هي نصوص، حتى لو كانت منطقياً رقماً أو قيمة منطقية.
- خطر الأخطاء الإملائية: من السهل كتابة
process.env.DB_HOTSبدلاً منDB_HOSTوالحصول علىundefined. - غياب التحقق من الصحة: إذا لم يتم تعيين متغير إلزامي، سيتعطل التطبيق في أكثر لحظة غير متوقعة، وليس عند بدء التشغيل.
التكوين الجيد يحل كل هذه المشاكل.
مكتبة dotenv وأغلفتها الخاصة بـ TypeScript
المعيار الفعلي لتحميل ملفات .env هو مكتبة dotenv. بالنسبة لـ TypeScript، من المناسب استخدام dotenv-flow أو dotenv-expand، التي تدعم بيئات متعددة (development, staging, production).
// التثبيت// npm install dotenv dotenv-expand
// config/env.tsimport dotenv from 'dotenv';import dotenvExpand from 'dotenv-expand';
const myEnv = dotenv.config({ path: `.env.${process.env.NODE_ENV || 'development'}` });dotenvExpand.expand(myEnv);بعد استدعاء هذه الدالة، ستكون جميع المتغيرات من ملف .env متاحة عبر process.env، لكننا لا نزال لا نملك الأنواع.
التحقق من صحة المخطط باستخدام Zod
Zod هي مكتبة قوية للتحقق من صحة المخططات التصريحية مع دعم من الدرجة الأولى لـ TypeScript. إنها مثالية للتكوين:
// config/schema.tsimport { z } from 'zod';
const envSchema = z.object({ NODE_ENV: z.enum(['development', 'production', 'test']).default('development'), PORT: z.coerce.number().positive().default(3000), DATABASE_URL: z.string().url(), JWT_SECRET: z.string().min(32), REDIS_HOST: z.string().default('localhost'), REDIS_PORT: z.coerce.number().default(6379), FEATURE_NEW_UI: z .string() .transform((val) => val === 'true') .default('false'),});
export type EnvConfig = z.infer<typeof envSchema>;الآن يمكننا تحليل البيئة والتحقق منها بأمان عند بدء التشغيل:
// config/index.tsimport { envSchema, EnvConfig } from './schema';
let config: EnvConfig;
export function loadConfig(): EnvConfig { if (config) return config; // تخزين مؤقت
const result = envSchema.safeParse(process.env); if (!result.success) { console.error('❌ متغيرات بيئة غير صالحة:', result.error.flatten().fieldErrors); process.exit(1); } config = result.data; return config;}
export function getConfig(): EnvConfig { if (!config) throw new Error('لم يتم تحميل التكوين. قم باستدعاء loadConfig() أولاً.'); return config;}مكتبة Conf لإدارة تكوين التطبيق
إذا كان تطبيقك لا يتطلب قراءة التكوين فحسب، بل كتابته أيضاً (مثل إعدادات المستخدم، ذاكرة التخزين المؤقت)، فانتبه إلى conf من Sindre Sorhus. إنها تخزن البيانات في ملف JSON وهي مكتوبة بالكامل.
// التثبيت// npm install conf
import Conf from 'conf';
interface AppConfig { lastOp