ضرورت و نحوه استفاده از Environment Variables در Node.Js

مقدمهمتغیرهای محیطی بخشی اساسی برای توسعه و کار با Node.js یا هر زبان سمت سرور دیگری می باشد. آنها همیشه حاوی داده های بسیار حساس هستند اما با این تفاوت که نمی خواهند داده هایشان را با دنیای بیرون به اشتراک بگذارند. همان طور که می دانیم بسیاری از برنامه ها قبل از اعزام به محیط تولید در یک محیط توسعه مستقر هستند. پس ما باید داده های محیطی را به درستی در تمام محیط ها (توسعه و تولید و ...) تنظیم کنیم زیرا متغیرهای محیطی به ما این امکان را می دهند که پیکربندی برنامه های خود را جدا از مبنای کد خود مدیریت کنیم و هر اشتباهی در تنظیمات می تواند منجر به خرابی سرورمان شود.چرا ما نیاز به تعریف و استفاده از متغیرهای محیطی داریم؟امنیت: با تعریف متغیر محیطی ما عملا بسیاری از متغیرهایی که در کد می توانستند مقدار بگیرند و در دسترس همه باشند و از آنها آگاه باشند را حذف کرده ایم و کسی از تنظیمات سرور ما آگاهی پیدا نمی کند.انعطاف پذیری: در صورت تعریف متغیرهای محیطی بسیاری از شروط راه اندازی سرور در محیط های مختلف کاهش می یابد، به گونه ای که سرور در هر محیط تنظیمات خود را از متغیرهای مربوطه خوانده و همان رفتار را انجام میدهد. به عبارت دیگر آنها جنبه های خاصی از محصول شما را به محیط خارج منتقل می کنند و به نوعی برنامه شما را محصور نگه می دارند. اکنون می توانید برنامه خود را در هر نقطه با تغییر متغیرهای محیطی بدون تغییر کد خود و بدون بازسازی آن اجرا کنید!عدم دوباره کاری: با وجود متغیرهای محیطی دیگر لازم نیست برای هر بار راه اندازی سرور در محیط های توسعه و تولید تمام تنظیمات را در بخش ها مختلف کد تغییر بدهیم. همچنین امکان خطا در تغییر کلیه تنظیمات سرور به حداقل می رسد.چه زمانی ما نیاز به استفاده از متغیرهای محیطی داریم؟به طور خلاصه می توان گفت: هر مکانی که در کد شما که براساس محیط تغییر می کند، نیاز به استفاده از متغیرهای محیطی دارد. پس وقتی این موقعیت ها را مشاهده کردید، از هر متغیری که برای تغییر یا پیکربندی لازم است استفاده کنید. طبق کنوانسیون، این نام با حروف بزرگ تعریف می شود. به عنوان مثال SENDER_EMAIL=me@thisemail.com و مقادیر انتساب داده شده به این نام ها از نوع رشته می باشد.اگر برنامه ترمینال یا خط فرمان را در Linux ، Mac OS یا Windows باز کنید و set را وارد کنید، لیستی از تمام متغیرهای محیطی را که برای آن ماشین تعریف کرده اید را مشاهده خواهید کرد.حال بهتر است برخی از نمونه های رایج استفاده از متغیرهای محیطی را عنوان کنیم: تنضیمات مربوط پورتها، آدرس های آی پی، نام های دامنه که برای انواع پروتکل ها (HTTP, HTTPS, SOCKET, ...) تعریف می شود.اطلاعات اتصال به پایگاه داده ها،‌سامانه های کش و سایر محلهای ذخیره سازی اطلاعاتمحل ذخیره سازی و بازیابی فایل ها و پوشه های استاتیکاطلاعات اتصال به سرویس های خارجی که مورد استفاده سیستم ما هستند.(API URL)در ضمن داده های حساس مانند کلیدهای API، نام های کاربری و کلمات عبور و ... نباید در سورس کد موجود باشند تا برای افرادی که نیازی به دسترسی به آن سرویس های خارجی یا اطلاعات حساس را ندارند، قابل مشاهده باشد.نحوه های استفاده از متغیرهای محیطی در سرور node jsاستفاده از command lineساده ترین راه برای انتقال متغیرهای محیطی به کد شما، استفاده از خط فرمان است. نام متغیر را مشخص کنید، به دنبال آن علامت مساوی، و سپس مقدار مورد نظر را ثبت نمایید. سپس برنامه Node.js خود را فراخوانی کنید. این الگو قابل تکرار می باشد.PORT=8626 node server.js PORT=8626 NODE_ENV=development node server.jsدر نگاه اول شاید این روش ساده و به کارگیری آن راحتتر، نسبت به سایر روش ها باشد اما مشکلاتی هم در این نوع تعریف وجود دارد:مکان مناسبی برای دیدن لیست متغیرهای محیطی وجود ندارد.امکان اشتباه تایپ کردن در خط فرمان برای تعریف متغیرها بسیار آسان است.یادآوری همه متغیرها و مقادیر آنها کار آسانی نیست.حتی با اجرا کردن توسط اسکریپت های npm، آنها را باید نگهداری و به یاد داشته باشیم.استفاده از package.jsonشما می توانید جفت key = value را مستقیماً در اسکریپت های npm در package.json منتقل کنید. این مکان معتبری برای قرار دادن متغیر محیطی می باشد اما مکانی مطمئن و امن نیست.{ ... &quotscripts&quot: { &quotstart&quot: &quotNODE_ENV=production node bin/www.js&quot } ... }این روش علاوه بر سادگی و قابل دسترس بودن در تعریف متغیرهای محیطی معایبی نیز دارد به طور نمونه:داده های حساس را در اینجا قرار ندهید زیرا برای همه قابل مشاهده است. ما نمی توانیم package.json را در gitignore. قرار دهیم و آن را نادیده بگیریم. پس اطلاعات آن برای همه در سترس بوده و این تنظیمات برای همه اعمال می شود.بهتر است بیش از 2 متغیر را قرار ندهید زیرا می تواند به سرعت باعث آشفتگی و عدم مدیریت داده ها شود.جدا کردن متغیرها برای محیط توسعه و تولید می تواند بسیار سخت باشد.استفاده از فایل های کلیدی متفاوتبا استفاده از این روش عملا خودمان را گول میزنیم و از ترفند های برنامه نویسی خودمان بیشتر بهره می بریم. اما خوب این حالت هم می تواند یک روش برای تعریف و پیاده سازی متغیرهای محیطی باشد.بدین گونه که ما دو فایل مجزا به نام های 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(&quotkeys.dev.js&quot); const prodKeys = require(&quotkeys.prod.js&quot); if (process.env.NODE_ENV === &quotproduction&quot) { module.exports = prodKeys; } else { module.exports = devKeys; }این روش خوبی هایی هم دارد: متغیرهای متفاوت را به راحتی می توان مدیریت کرد.تمام محیط ها متغیرهای خود را به صورت مجزا دارند.با gitignore کردن فایل keys.dev.js عملا بخشی از اطلاعات محرمانه می ماند.اما این روش تعدادی فایل و برنامه نویسی اضافه بر سازمان به پروژه شما تحمیل میکند که شاید خیلی ها این فایل ها را دوست نداشته باشند.تعریف متغیرهای محیطی درون خود سیستم عاملدر این حالت ما می توانیم متغیرهای محیطی مورد نیاز خود را در محل هایی که سیستم عامل به ما اجازه می دهد تعریف کنیم. به عنوان مثال در لینوکس بهتر است در فایل 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 می باشد که از آن برای استخراج متغیرهای محلی تعریف شده در سیستم عامل استفاده می کنیم.استفاده از Environment Variables Libraries و تعریف فایل envبرای کار با فایل 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. می رود.