كيف يعالج Node.js وسائط سطر الأوامر: من process.argv إلى المصادر
\n\nتخيل: لقد كتبت نصًا رائعًا على Node.js يقوم بتحويل الصور. لكن تعديل الكود في كل مرة لتحديد اسم الملف هو أمر غير لائق. من الأفضل بكثير تشغيل: node convert.js --input photo.jpg --format webp والحصول على النتيجة. كيف نحقق هذا السحر؟ هذا هو السؤال الذي سنخصص له الوقت اليوم، وهو أحد أكثر الأسئلة شيوعًا على Stack Overflow.
قد يبدو الأمر بسيطًا؟ لكن تحت غطاء Node.js (و V8 نفسه) تختبئ عدة طبقات من المفيد لكل مطور معرفتها. لن نعرض فقط كيفية الحصول على process.argv — بل سننظر في كود Node.js المصدر لمعرفة كيف تنتقل الوسائط من جهازك الطرفي إلى متغيرات بيئة العملية. هيا بنا!
لماذا نحتاج وسائط سطر الأوامر؟
\nوسائط سطر الأوامر (CLI arguments) هي الطريقة الأساسية لجعل برنامجك مرنًا وقابلًا لإعادة الاستخدام دون تغيير الكود. بدلاً من الترميز الثابت، تقوم بتمرير البيانات كمدخلات. هذا هو أساس جميع أدوات DevOps تقريبًا، وأدوات التجميع (Webpack، Vite)، والأدوات المساعدة. القدرة على التعامل معها هي مهارة أساسية لمطور JavaScript يريد تجاوز حدود المتصفح.
\n\nالمستوى 1: الأساسيات — process.argv
\nأبسط طريقة أصلية للحصول على الوسائط في Node.js هي الوصول إلى الكائن العام process.argv. إنها مصفوفة من السلاسل النصية. دعنا نرى مثالًا فوريًا.
الملف: args-demo.js
\n// args-demo.js\nconsole.log(process.argv);\n\nلنقم بتشغيله مع وسائط:
\nnode args-demo.js hello --name=World 42\n\nالإخراج في وحدة التحكم:
\n[\n '/usr/local/bin/node', // 0: مسار ملف Node.js القابل للتنفيذ\n '/home/user/args-demo.js', // 1: مسار النص البرمجي الخاص بك\n 'hello', // 2: أول وسيطة مستخدم\n '--name=World', // 3: الوسيطة الثانية\n '42' // 4: الوسيطة الثالثة\n]\n\nهذا هو كل السحر. process.argv هو مجرد مقتطف مما نقله نظام التشغيل إلى العملية. العنصران الأولان هما معلومات خدمية. كل ما يأتي بعد الفهرس 2 هو وسائطك. مهم: جميعها سلاسل نصية. الرقم 42 جاء كسلسلة "42".
كيف نتجاهل أول عنصرين؟
\nلسهولة الاستخدام، غالبًا ما نستخدم التفكيك:
\n// الحصول على وسائط المستخدم فقط\nconst [, , ...userArgs] = process.argv;\nconsole.log(userArgs); // ['hello', '--name=World', '42']\nأو ببساطة process.argv.slice(2).
المستوى 2: التحليل يدويًا — اختراع العجلة بنفسك
\nالعمل مع مصفوفة سلاسل نصية خام غير مريح. نحتاج إلى التمييز بين الأعلام (--name) والقيم (World). دعنا نكتب محللًا بسيطًا لفهم المنطق.
// simple-parser.js\nconst args = process.argv.slice(2);\nconst parsed = {};\n\nfor (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg.startsWith('--')) {\n // إزالة '--' والبحث عن القيمة\n const key = arg.slice(2);\n const next = args[i + 1];\n // إذا كانت الوسيطة التالية لا تبدأ بـ '--'، فهي القيمة\n if (next && !next.startsWith('--')) {\n parsed[key] = next;\n i++; // تخطي الخطوة التالية من التكرار\n } else {\n parsed[key] = true; // علم منطقي\n }\n } else if (arg.startsWith('-')) {\n // الأعلام القصيرة، مثل -v\n const key = arg.slice(1);\n parsed[key] = true;\n } else {\n // وسيطة موضعية ببساطة\n if (!parsed._) {\n parsed._ = [];\n }\n parsed._.push(arg);\n }\n}\n\nconsole.log(parsed);\n// node simple-parser.js --name World -v hello\n// { name: 'World', v: true, _: ['hello'] }\n\nهذا الكود هو أساس مكتبات مثل minimist. كما ترى، لا شيء معقد. لكن في المشاريع الحقيقية، من الأفضل استخدام مكتبات جاهزة