Menu

process.env في Node.js: قراءة متغيرات البيئة

process.env كائن يحمل متغيرات البيئة التي بدأ بها برنامج Node.js. كل قيمة إما نص أو undefined، لذلك حوّل الأرقام والقيم المنطقية بنفسك وأعطِ كل متغير قيمة افتراضية.

تحتوي هذه الصفحة على محررات قابلة للتشغيل. حرّر، شغّل، وشاهد النتيجة فوراً.

process.env كائن فيه خاصية لكل متغير بيئة مرّرته الصدفة إلى برنامج Node.js: process.env.PORT وprocess.env.DATABASE_URL وهكذا. المتغير غير المضبوط يُقرأ على أنه undefined، والمتغير المضبوط هو نص دائمًا. اقرأه مرة واحدة عند بدء التشغيل، وأعطه قيمة افتراضية، وحوّله إلى النوع الذي تحتاجه.

طبع shop on port 8080 in eu-west (لم يُضبط REGION أبدًا، فحلّت قيمته الافتراضية محله)، ثم string number: المتغير نص إلى أن يحوّله Number(). احذف الإسنادين الأولين وشغّل من جديد لترى كل القيم الافتراضية.

ضبط متغيرات البيئة في الصدفة

تأتي المتغيرات من المكان الذي يُشغَّل منه Node.js. في الطرفية:

// macOS and Linux: for one command
PORT=8080 NODE_ENV=production node app.js

// macOS and Linux: for the rest of the terminal session
export PORT=8080

// Windows PowerShell
$env:PORT = "8080"; node app.js

// Windows cmd.exe
set PORT=8080
node app.js

لمنصات الاستضافة (Heroku وRender وVercel وDocker وKubernetes) صفحة إعدادات أو ملف للغرض نفسه؛ وتقرؤها شيفرتك بالطريقة ذاتها.

كل شيء نص

من هنا تأتي معظم أخطاء process.env. القيمتان 'false' و'0' نصان غير فارغين، لذلك تُعتبران صحيحتين (truthy):

طبع الفحص الساذج debug is ON لمتغير قيمته false، فقارن بالنص الدقيق الذي تتوقعه. أما الأرقام، فـ Number(process.env.X) يحوّل القيمة الغائبة إلى NaN، لذا طبّق القيمة الافتراضية قبل التحويل، كما فعل المثال الأول بـ ??.

NODE_ENV

NODE_ENV عُرف متّبع وليس ميزة في Node.js: لا يضبطه Node.js أبدًا. المكتبات هي التي تقرؤه. فمثلًا يخفي Express تتبّع المكدس (stack trace) من صفحات الأخطاء حين تكون قيمته production، وتتخطى أدوات كثيرة الفحوص الخاصة بالتطوير.

طبع mode: production وverbose logs: false؛ غيّر 'production' إلى 'development' فينقلب السطر الثاني. التزم بالقيم production وdevelopment وtest، لأن المكتبات تبحث عن هذه الكلمات بالضبط.

ملفات .env: الخيار --env-file وdotenv

كتابة كل متغير قبل node تصبح مملة. يحفظها ملف .env في مجلد مشروعك، متغيرًا في كل سطر:

// .env
PORT=8080
DATABASE_URL=postgres://localhost/shop
API_KEY=dev-key-123

يقرؤه Node.js 20.6 وما بعده بخيار واحد، دون أي حزمة:

node --env-file=.env app.js

في النسخ الأقدم، أو إن كنت تفضّل ذلك، ثبّت الحزمة dotenv (npm install dotenv) وحمّلها في أعلى ملف الدخول تمامًا، قبل أن تقرأ أي شيفرة process.env:

require('dotenv').config(); // copies .env into process.env

console.log(process.env.PORT); // 8080

لا يكتب أي منهما فوق متغير مضبوط مسبقًا في الصدفة، فتكون الأولوية لإعدادات الإنتاج على الملف.

توقّف مبكرًا عند غياب المتغيرات

غياب عنوان قاعدة البيانات يجب أن يوقف البرنامج عند بدء التشغيل برسالة واضحة، لا أن يتعطل عند أول طلب بعد ساعة:

طبع Missing environment variables: API_KEY؛ أضف process.env.API_KEY = 'test'; في الأعلى فيطبع Config OK. في برنامج حقيقي، أتبِع الرسالة بـ process.exit(1)، لأن رمز الخروج غير الصفري هو الطريقة التي يعرف بها سكربت النشر أو منصة الحاويات أن بدء التشغيل فشل.

لا ترفع الأسرار إلى المستودع أبدًا

أضف .env إلى .gitignore في اليوم الذي تنشئه فيه. وارفع بدلًا منه .env.example فيه أسماء المتغيرات وقيم وهمية، ليعرف الآخرون ما يجب ضبطه. أي مفتاح دُفع إلى مستودع ولو مرة يجب اعتباره مسرّبًا واستبداله، حتى لو حذفت الـ commit لاحقًا.

الأسئلة الشائعة

لماذا قيمة process.env.MY_VAR هي undefined؟

لم يُضبط المتغير في الصدفة التي شغّلت Node.js، أو ضُبط في طرفية أخرى. ولا يُقرأ ملف .env تلقائيًا أيضًا: شغّل Node.js مع --env-file=.env أو حمّله بـ dotenv قبل أن تقرأ القيمة.

هل يمكنني تغيير process.env أثناء عمل البرنامج؟

نعم. الإسناد process.env.X = 'value' يغيّره للعملية الحالية ولأي عملية فرعية تبدؤها لاحقًا، لكن لا يغيّره أبدًا للصدفة التي شغّلت Node.js. ويحوّل Node.js القيمة التي تسندها إلى نص.

هل أسماء متغيرات البيئة حساسة لحالة الأحرف؟

على Linux وmacOS نعم: PORT وport متغيران مختلفان. أما على Windows فلا. التزم بأسماء بأحرف كبيرة وشرطات سفلية ولن يُطرح السؤال أبدًا.

هل يستطيع المتصفح قراءة process.env؟

لا. لا توجد متغيرات بيئة في المتصفحات. تنسخ أدوات البناء مثل Vite وNext.js متغيرات مختارة إلى شيفرة الواجهة الأمامية وقت البناء، وهذا يعني أيضًا أن تلك القيم علنية.

رسم توضيحي للغات البرمجة في Coddy

تعلّم البرمجة مع Coddy

ابدأ الآن