متغیرهای محیطی بخشی اساسی برای توسعه و کار با Node.js یا هر زبان سمت سرور دیگری می باشد. آنها همیشه حاوی داده های بسیار حساس هستند اما با این تفاوت که نمی خواهند داده هایشان را با دنیای بیرون به اشتراک بگذارند. همان طور که می دانیم بسیاری از برنامه ها قبل از اعزام به محیط تولید در یک محیط توسعه مستقر هستند. پس ما باید داده های محیطی را به درستی در تمام محیط ها (توسعه و تولید و ...) تنظیم کنیم زیرا متغیرهای محیطی به ما این امکان را می دهند که پیکربندی برنامه های خود را جدا از مبنای کد خود مدیریت کنیم و هر اشتباهی در تنظیمات می تواند منجر به خرابی سرورمان شود.
به طور خلاصه می توان گفت: هر مکانی که در کد شما که براساس محیط تغییر می کند، نیاز به استفاده از متغیرهای محیطی دارد.
پس وقتی این موقعیت ها را مشاهده کردید، از هر متغیری که برای تغییر یا پیکربندی لازم است استفاده کنید. طبق کنوانسیون، این نام با حروف بزرگ تعریف می شود. به عنوان مثال SENDER_EMAIL=me@thisemail.com و مقادیر انتساب داده شده به این نام ها از نوع رشته می باشد.
اگر برنامه ترمینال یا خط فرمان را در Linux ، Mac OS یا Windows باز کنید و set را وارد کنید، لیستی از تمام متغیرهای محیطی را که برای آن ماشین تعریف کرده اید را مشاهده خواهید کرد.
حال بهتر است برخی از نمونه های رایج استفاده از متغیرهای محیطی را عنوان کنیم:
در ضمن داده های حساس مانند کلیدهای API، نام های کاربری و کلمات عبور و ... نباید در سورس کد موجود باشند تا برای افرادی که نیازی به دسترسی به آن سرویس های خارجی یا اطلاعات حساس را ندارند، قابل مشاهده باشد.
ساده ترین راه برای انتقال متغیرهای محیطی به کد شما، استفاده از خط فرمان است. نام متغیر را مشخص کنید، به دنبال آن علامت مساوی، و سپس مقدار مورد نظر را ثبت نمایید. سپس برنامه Node.js خود را فراخوانی کنید. این الگو قابل تکرار می باشد.
PORT=8626 node server.js PORT=8626 NODE_ENV=development node server.js
در نگاه اول شاید این روش ساده و به کارگیری آن راحتتر، نسبت به سایر روش ها باشد اما مشکلاتی هم در این نوع تعریف وجود دارد:
شما می توانید جفت key = value را مستقیماً در اسکریپت های npm در package.json منتقل کنید. این مکان معتبری برای قرار دادن متغیر محیطی می باشد اما مکانی مطمئن و امن نیست.
{ ... "scripts": { "start": "NODE_ENV=production node bin/www.js" } ... }
این روش علاوه بر سادگی و قابل دسترس بودن در تعریف متغیرهای محیطی معایبی نیز دارد به طور نمونه:
با استفاده از این روش عملا خودمان را گول میزنیم و از ترفند های برنامه نویسی خودمان بیشتر بهره می بریم. اما خوب این حالت هم می تواند یک روش برای تعریف و پیاده سازی متغیرهای محیطی باشد.
بدین گونه که ما دو فایل مجزا به نام های keys.dev.js و keys.prod.js را در root پروژه تعریف میکنیم که هر کدام از آنها اطلاعات متغیرهای مربوط به محیط خود را دارد. و برای مدیریت آنها پای یک فایل سوم هم در میان می آید به نام keys.js که این دو فایل را با توجه به متغیر NODE_ENV مدیریت می کند.
نکته: باید حواسمان باشد که keys.dev.js را حتما در .gitignore قرار دهیم.
// keys.dev.js ========== module.exports = { PORT: 5000, }; // keys.prod.js ========== module.exports = { PORT: process.env.PORT, }; // keys.js ========== const devKeys = require("keys.dev.js"); const prodKeys = require("keys.prod.js"); if (process.env.NODE_ENV === "production") { module.exports = prodKeys; } else { module.exports = devKeys; }
این روش خوبی هایی هم دارد:
اما این روش تعدادی فایل و برنامه نویسی اضافه بر سازمان به پروژه شما تحمیل میکند که شاید خیلی ها این فایل ها را دوست نداشته باشند.
در این حالت ما می توانیم متغیرهای محیطی مورد نیاز خود را در محل هایی که سیستم عامل به ما اجازه می دهد تعریف کنیم. به عنوان مثال در لینوکس بهتر است در فایل root/.bashrc تعریف شود و یا در ویندوز می توان به این آدرس right click the Computer/Properties/system/Environment Variables مراجعه کرده و متغیرهای محیطی خود را ویرایش یا اضافه کرد. بعد از تعریف این اطلاعات در درون سیستم عامل می توان از دستور زیر برای بازیابی تک تک متغیرهای محلی استفاده کرد.
console.log(process.env.MY_DATA_IN_OS)
حال process در Node.js چه می باشد؟ یک شی عمومی، بدون نیاز به require کردن و قابل دسترس در همه جای برنامه که اطلاعاتی را در موردِ Node.js و کنترل فرآیندهای فعلی آن ارائه می دهد. env یکی از ویژگی های موجود در process می باشد که از آن برای استخراج متغیرهای محلی تعریف شده در سیستم عامل استفاده می کنیم.
برای کار با فایل env. و خواندن متغیرهای محیطی تعریف شده در آن، ما سراغ کتابخانه dotenv رفته ایم و آن را انتخاب کرده ایم. فایل env. باعث کمتر شدن بهم ریختگی های موجود در تعریف متغیرهای محیطی میشود. فایل env. محلی برای نگه داری، تغییر و بازنگری متغیرهای محیطی می باشد که باید در root پروژه تعریف شود.
NODE_ENV=development PORT=3000 # Set your database/API connection information here API_KEY=************************** API_URL=**************************
توصیه می شود فایل env. را درون gitignore. قرار دهید تا روی نسخه تولید منتشر نشود.
برای خواندن متغیرهای محیطی که در بالا تعریف شده است کافی هست ماژول dotenv را نصب کنید و اسکریپت زیر را توسط node server.js اجرا نمایید و خروجی رو بر روی ترمینال خود مشاهده نمایید:
// server.js console.log(`Your port is ${process.env.PORT}`); // undefined const dotenv = require('dotenv'); dotenv.config(); console.log(`Your port is ${process.env.PORT}`); // 3000
حال شاید برای شما سئوال به وجود بیاید که تفاوت process.env تعریف شده در این بخش با قسمت قبلی در چیست؟ تفاوت معنایی و کاری ندارند اما در نحوه اولویت دادن به خواندن متغیرهای محیطی با هم فرق می کنند. مثال: فرض کنید شما در فایل bashrc. لینوکس خود هم متغیری با نام PORT=5000 تعریف کرده بودید آنگاه نتیجه اجرای کد به صورت زیر بود
// server.js console.log(`Your port is ${process.env.PORT}`); // 5000 const dotenv = require('dotenv'); dotenv.config(); console.log(`Your port is ${process.env.NODE_ENV}`); // development console.log(`Your port is ${process.env.PORT}`); // 5000
همان طور که مشاهده میکنید اولویت خواندن با متغیرهای محیطی سیستم عامل می باشد و در صورت نبود متغیر در آن بخش سراغ متغیرهای موجود در فایل env. می رود.