همیشه برای توسعه دهندهها مهم بوده که بتونن اپلیکیشن هاشون رو روی یه مجموعه یکپارچه از تکنولوژیهای پایه بسازن. وقتی از همون اول کار یه سری ابزار استاندارد و هماهنگ در اختیار داشته باشی، میتونی بیشتر وقتت رو روی ساختن چیزی بذاری که کسب وکارت رو متمایز میکنه. اینجوری دیگه لازم نیست از صفر شروع کنی و کلی قطعه پراکنده رو به هم بچسبونی. اینجاست که MEAN Stack وارد میشه و همه این کارها رو برات راحت میکنه. آماده ای بریم سراغ این تکنولوژی جذاب؟!
MEAN Stack یه ترکیب از چهار تکنولوژی قدرتمنده که بهت اجازه میده یه اپلیکیشن وب فول استک بسازی. این چهار تکنولوژی عبارتند از:
با استفاده از این چهار ابزار، میتونی یه اپلیکیشن وب کامل بسازی که از پایگاه داده تا واسط کاربری همه چی رو پوشش بده. حالا بیا هر کدوم از این ابزارها رو به طور جداگانه بررسی کنیم.
MongoDB یه پایگاه داده NoSQL هست که بهت اجازه میده دادهها رو به صورت سندهای JSON ذخیره کنی. این یعنی میتونی دادهها رو به صورت ساختار یافته و با انعطاف بالا ذخیره کنی. برای مثال، فرض کن میخوای اطلاعات کاربران رو ذخیره کنی. با MongoDB میتونی به راحتی سندی به شکل زیر بسازی:
{
"name": "John Doe",
"email": "john@example.com",
"age": 30
}
این انعطاف پذیری باعث میشه که بتونی به راحتی ساختار داده هات رو تغییر بدی و با نیازهای پروژه ت تطبیق بدی.
Express.js یه فریم ورک سبک و قدرتمنده که برای ساخت سرور با استفاده از Node.js استفاده میشه. این فریم ورک بهت اجازه میده تا با استفاده از متدهای ساده، روتهای مختلف بسازی و درخواستهای HTTP رو مدیریت کنی. مثلا، با استفاده از Express.js میتونی یه سرور ساده به شکل زیر بسازی:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello, World!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Angular یه فریم ورک فرانت اند قدرتمنده که توسط گوگل توسعه داده شده. این فریم ورک بهت اجازه میده تا اپلیکیشنهای تک صفحه ای (SPA) بسازی که تجربه کاربری فوق العاده ای دارن. با Angular میتونی به راحتی کامپوننتهای مختلف بسازی و دادهها رو بین اونها به اشتراک بذاری. برای مثال، میتونی یه کامپوننت ساده به شکل زیر بسازی:
import { Component } from '@angular/core';
@Component({
selector: 'app-hello',
template: `<h1>Hello, {{ name }}!</h1>`,
})
export class HelloComponent {
name = '7Learn';
}
Node.js یه محیط اجرایی برای جاوا اسکریپته که روی سرور استفاده میشه. این محیط بهت اجازه میده تا با استفاده از جاوا اسکریپت، کدهای سمت سرور بنویسی و از همون زبان برای فرانت اند و بک اند استفاده کنی. این یعنی نیاز نیست برای هر بخش از اپلیکیشن ت زبانهای مختلف یاد بگیری و میتونی همه چی رو با جاوا اسکریپت انجام بدی.
حالا که با MEAN Stack آشنا شدی، بیا ببینیم کجاها میتونی از این تکنولوژی خفن استفاده کنی. MEAN Stack برای همه نوع اپلیکیشن مناسب نیست، اما جاهایی که به درد میخوره، حسابی میدرخشه. از اونجایی که MEAN Stack قابلیت مقیاس پذیری بالایی داره و میتونه تعداد زیادی کاربر رو همزمان مدیریت کنه، یه انتخاب عالی برای توسعه اپلیکیشنهای ابری (Cloud-native) هست. همچنین، فریم ورک Angular که در بخش فرانت اند استفاده میشه، ایده آل برای ساخت اپلیکیشنهای تک صفحه ای (SPA) است که همه اطلاعات و امکانات رو روی یک صفحه ارائه میده. بیا چند تا مثال از کاربردهای MEAN Stack ببینیم:
اگر دنبال ساخت یه تقویم آنلاین هستی که کاربران بتونن رویدادها و برنامه هاشون رو مدیریت کنن، MEAN Stack میتونه انتخاب خوبی باشه. با استفاده از MongoDB میتونی دادهها رو به صورت ساختار یافته ذخیره کنی و با Angular یه واسط کاربری زیبا و کاربرپسند بسازی.
یه اپلیکیشن ردیابی هزینهها که کاربران بتونن مخارج روزانه شون رو ثبت و مدیریت کنن، نیاز به یه پایگاه داده قوی و یه واسط کاربری منعطف داره. MEAN Stack با ترکیب MongoDB و Angular بهت اجازه میده تا یه اپلیکیشن کارآمد و مقیاس پذیر برای مدیریت هزینهها بسازی.
برای ساختن سایتهای تجمیع اخبار که اطلاعات رو از منابع مختلف جمع آوری میکنن و به کاربران نمایش میدن، MEAN Stack یه گزینه عالیه. با استفاده از Node.js و Express.js میتونی اطلاعات رو از منابع مختلف جمع آوری و پردازش کنی و با Angular اونها رو به کاربران نمایش بدی.
اپلیکیشنهای نقشه برداری و مکان یابی نیاز به پردازش سریع دادهها و نمایش دقیق اطلاعات دارن. MEAN Stack با قابلیت مقیاس پذیری بالا و انعطاف پذیری زیاد میتونه بهت کمک کنه تا یه اپلیکیشن نقشه برداری و مکان یابی کارآمد و قابل اعتماد بسازی.
اگر به فکر ساختن یه اپلیکیشن چت یا پیام رسانی هستی که کاربران بتونن به صورت همزمان با هم ارتباط برقرار کنن، MEAN Stack یه انتخاب عالیه. با استفاده از Socket.io و Node.js میتونی ارتباطات بی درنگ (real-time) رو مدیریت کنی و با Angular یه واسط کاربری جذاب و کاربرپسند بسازی.
همون طور که دیدی، MEAN Stack میتونه توی زمینههای مختلفی به کارت بیاد و بهت کمک کنه تا اپلیکیشنهای متنوع و قدرتمندی بسازی. فقط کافیه با خلاقیت و دانش خودت از این ابزارها استفاده کنی و بهترین نتیجه رو بگیری.
حالا که با هر کدوم از ابزارهای MEAN Stack آشنا شدیم، بیا ببینیم چرا استفاده از این تکنولوژی میتونه یه انتخاب عالی برای توسعه وب باشه.
یکی از بزرگترین مزایای MEAN Stack اینه که تمام ابزارهای مورد استفاده در این تکنولوژی با همدیگه هماهنگ و یکپارچه هستن. این یعنی میتونی با استفاده از یه زبان (جاوا اسکریپت) تمام بخشهای اپلیکیشن ت رو بنویسی و نیازی به یادگیری زبانهای مختلف نداری.
MEAN Stack بهت انعطاف پذیری بالایی میده تا به راحتی ساختار دادهها و اپلیکیشن ت رو تغییر بدی. با MongoDB میتونی به راحتی دادهها رو به شکل سند ذخیره کنی و با Angular میتونی به راحتی رابط کاربری ت رو تغییر بدی.
با استفاده از Node.js میتونی کدهای سمت سرور رو با سرعت بالا اجرا کنی و درخواستهای همزمان زیادی رو مدیریت کنی. این باعث میشه اپلیکیشن ت عملکرد بالایی داشته باشه و تجربه کاربری بهتری ارائه بده.
هر کدوم از ابزارهای MEAN Stack توسط جامعه بزرگی از توسعه دهندهها پشتیبانی میشن. این یعنی همیشه میتونی به منابع آموزشی و پشتیبانی فنی دسترسی داشته باشی و مشکلاتت رو به راحتی حل کنی.
تا اینجا درباره مزایا و کاربردهای MEAN Stack حرف زدیم. اما هیچ تکنولوژی ای بدون عیب و ایراد نیست. حالا بیا یه نگاه دقیقتر به معایب و چالشهای MEAN Stack بندازیم.
یکی از بزرگترین چالشهای MEAN Stack اینه که اگر تازه کاری، یادگیری همه ابزارهای این استک ممکنه برات زمان بر باشه. هر چند که همه چیز با جاوا اسکریپت کار میکنه، ولی یادگیری عمیق MongoDB، Express.js، Angular و Node.js هر کدوم خودش یه چالش جداست. باید حسابی وقت بذاری و با هر کدوم از این تکنولوژیها خوب آشنا بشی تا بتونی بهترین استفاده رو ازشون بکنی.
تنظیم و پیکربندی اولیه MEAN Stack ممکنه برات پیچیده باشه، به خصوص اگر تجربه کافی نداشته باشی. هر کدوم از این ابزارها نیاز به تنظیمات خاص خودش داره و اگه یکی از اونها رو اشتباه تنظیم کنی، ممکنه کل پروژه ت به مشکل بخوره. پس باید حسابی حواست به جزئیات باشه و از منابع و داکیومنتهای موجود استفاده کنی.
درسته که MEAN Stack بهت کمک میکنه اپلیکیشنهای مقیاس پذیر بسازی، ولی این مقیاس پذیری هم خودش چالشهای خاصی داره. مدیریت تعداد زیاد کاربر و درخواستهای همزمان میتونه منابع سرورت رو حسابی تحت فشار بذاره. باید حواست به بهینه سازی کدها و استفاده از بهترین روشها برای مدیریت منابع باشه تا اپلیکیشن ت همیشه روان و سریع کار کنه.
اگر داری یه اپلیکیشن تک صفحه ای (SPA) میسازی، باید بدونی که این نوع اپلیکیشنها به خاطر لود شدن تمام محتوا با جاوا اسکریپت، ممکنه با مشکلاتی در زمینه SEO مواجه بشن. موتورهای جستجو ممکنه نتونن به خوبی محتوای صفحات رو بخونن و این میتونه روی رتبه بندی سایتت توی نتایج جستجو تاثیر منفی بذاره. برای حل این مشکل میتونی از تکنیکهای مختلفی مثل سرور ساید رندرینگ (SSR) استفاده کنی.
هر چند که MEAN Stack توسط جامعه بزرگی از توسعه دهندهها پشتیبانی میشه، ولی وابستگی به ابزارهای متن باز همیشه ریسک هایی داره. ممکنه بعضی از کتابخانهها و ابزارهای مورد استفاده به روزرسانی نشن یا مشکلات امنیتی داشته باشن که باید حواست به این موضوعات هم باشه.
در نهایت، هر تکنولوژی ای چالشها و معایب خودش رو داره، ولی اگه خوب باهاش کنار بیای و یاد بگیری چطور بهترین استفاده رو ازش ببری، میتونی پروژههای عالی و موفقی بسازی.
حالا که با MEAN Stack آشنا شدی، باید بدونی که تنها گزینه موجود نیست. دوتا استک دیگه هم هستن که حسابی محبوبن: MERN و MEVN. بیا ببینیم اینا چه فرقی با MEAN دارن.
MERN Stack هم مثل MEAN عمل میکنه، با این تفاوت که به جای Angular، از ReactJS استفاده میکنه. ReactJS توسط فیسبوک توسعه داده شده و برای ساخت رابطهای کاربری سریع و تعاملی خیلی خوبه. این استک بیشتر برای اپلیکیشنهای بزرگ و پیچیده که نیاز به رابط کاربری سریع دارن، مناسبه.
MEVN Stack هم یه جایگزین دیگه ست که به جای Angular از Vue.js استفاده میکنه. Vue.js یه فریم ورک جاوا اسکریپت ساده و پیشرفته ست که به خاطر سادگی و سرعت یادگیریش معروفه. MEVN بیشتر برای پروژههای کوچک تا متوسط که توسعه سریع و ساده مد نظره، به کار میاد.
تفاوت اصلی بین این سه استک توی انتخاب فریم ورک فرانت اند هست، در حالی که همه شون از MongoDB، Express.js و Node.js برای بک اند استفاده میکنن. بیا چند تا فاکتور مهم رو بررسی کنیم:
حالا که با MEAN Stack آشنا شدی، بریم ببینیم کجاها میتونی از این استک جذاب استفاده کنی. MEAN از سه لایه اصلی تشکیل شده: لایه نمایش (Angular.js)، لایه برنامه (Express.js و Node.js) و لایه پایگاه داده (MongoDB). این یعنی از نمایش دادهها تا مدیریت درخواستها و ذخیره سازی اطلاعات، همه چی توی یه پکیج آماده هست.
اگه داری یه اپلیکیشن جاوا اسکریپتی میسازی، به ویژه با نود جی اس، MEAN یه گزینه عالی برات محسوب میشه. MongoDB دادهها رو به صورت JSON ذخیره میکنه و کار باهاش خیلی راحته. کوئریها و رابط خط فرمان (CLI) هم با جاوا اسکریپت کار میکنن، پس همه چیز یکپارچه و سازگار میشه.
MongoDB پر از ویژگیهای پیشرفته مثل ایندکس گذاری و جستجوی عمیق در اسناد JSON هست. درایورهای قدرتمند Node.js بومی داره و برای مقیاس پذیری افقی طراحی شده. استفاده از MongoDB Atlas، که یه سرویس ابری مدیریت شده ست، این کار رو حتی راحتتر هم میکنه.
درایور Node.js برای MongoDB کار با MongoDB رو در داخل یه اسکریپت Node.js ساده و شهودی میکنه، و این باعث میشه وقت کمتری صرف کنی و بهره وری ت بالا بره.
اول از همه، نیاز به یه پایگاه داده MongoDB داری. سادهترین راه برای شروع کار با MongoDB اینه که یه کلاستر رایگان توی MongoDB Atlas بسازی، که یه دیتابیس مستند ابری چندگانه و مدیریت شده ست.
دیتابیسهای Atlas به راحتی مستقر و مقیاس پذیر هستن و یه URI سازگار برای اتصال فراهم میکنن. برای اطلاعات بیشتر میتونی به مستندات رسمی MongoDB برای اتصال به یه کلاستر مراجعه کنی.
اتصالات Atlas با نام کاربری/رمز عبور داخلی و رمزگذاری TLS از ابتدا همراه هستن. همچنین، این اتصالات بهت اجازه میدن از ویژگیهای پیشرفته امنیتی MongoDB مثل احراز هویت با گواهینامه/IAM، ال دی ای پی (LDAP)، رمزگذاری در حالت استراحت، و حسابرسی با یک کلیک استفاده کنی.
علاوه بر این، یه پروژه Atlas میتونه از پلتفرم برنامههای Atlas App Services برای یکپارچه سازی راحت با ارائه دهندگان احراز هویت مختلف مثل گوگل، فیسبوک، JWT و احراز هویت سفارشی استفاده کنه.
مدیریت و مقیاس پذیری Atlas خیلی راحته و بزرگترین مزیتش اینه که لایه داده ارزشمندترین بخش MEAN Stack رو پشتیبانی و ایمن میکنه.
ما پیشنهاد میکنیم از MEAN Stack با MongoDB Atlas استفاده کنی، چون Atlas دارای اعتبارنامههای داخلی، فایروال و رمزگذاری End-to-End هست که بهترین پایه برای ایمن کردن MongoDBته.
علاوه بر این، MEAN Stack دارای یک جداسازی سه لایه قوی هست که اگه با بهترین روشها و شبکه سازی صحیح استفاده بشه، باید از دسترسی کاربران نهایی به منطق کسب وکار و حتی لایه پایگاه داده ت جلوگیری کنه. بنابراین، اپلیکیشن ت به صورت پیش فرض طراحی شده تا از تعاملات مخرب کاربران که ممکنه اپلیکیشن ت رو به خطر بندازه (مثل تزریق کوئری، دستکاری کد، تقلید پورت و غیره) جلوگیری کنه.
با خیال راحت از MEAN Stack استفاده کن و مطمئن باش که امنیت دیتابیس و اپلیکیشن ت تامین شده!
در این بخش میخوایم درباره تفاوت بین یه MEAN Stack Developer و یه Full Stack Developer حرف بزنیم. ممکنه این اصطلاحات به نظرت پیچیده بیان، اما با یه توضیح ساده همه چی روشن میشه.
Full Stack Developer کسیه که توانایی کار کردن با هر دو بخش فرانت اند (frontend) و بک اند (backend) یه اپلیکیشن وب رو داره. این یعنی هم میتونه واسط کاربری جذاب بسازه و هم میتونه منطق سرور و پایگاه داده رو پیاده سازی کنه. یه Full Stack Developer معمولاً با تکنولوژیها و فریم ورکهای مختلفی مثل HTML، CSS، JavaScript، Python، Ruby، PHP، MySQL و غیره کار میکنه. این افراد توانایی طراحی، توسعه، تست و نگهداری کل اپلیکیشن رو دارن و به خاطر داشتن دانش گسترده در این زمینه ها، برای شرکتها بسیار ارزشمند هستن.
MEAN Stack Developer هم مثل Full Stack Developer، توانایی کار با هر دو بخش فرانت اند و بک اند رو داره، اما با یه تفاوت مهم: این افراد فقط با تکنولوژیهای MEAN Stack کار میکنن. این تکنولوژیها شامل MongoDB، Express.js، Angular.js و Node.js هستن. MEAN Stack Developerها تخصصشون در جاوا اسکریپت و ابزارهای مربوط به اون هست و معمولاً برای پروژه هایی که به این تکنولوژیها نیاز دارن، خیلی مناسبن.
معیار | Full Stack Developer | MEAN Stack Developer |
---|---|---|
تکنولوژیهای مورد استفاده | HTML، CSS، JavaScript، Python، Ruby، PHP، MySQL و غیره | MongoDB، Express.js، Angular.js، Node.js |
دامنه دانش | گسترده و شامل تکنولوژیها و فریم ورکهای مختلف | متمرکز بر جاوا اسکریپت و ابزارهای مربوط به آن |
کاربردها | پروژههای بزرگ و پیچیده که نیاز به تکنولوژیهای مختلف دارن | پروژههای جاوا اسکریپتی و مقیاس پذیر |
مزایا | توانایی تغییر بین فرانت اند و بک اند، مناسب برای پروژههای متنوع | توسعه سریعتر و سادهتر به خاطر یکپارچگی ابزارها |
نمونه ابزارها | LAMP (Linux، Apache، MySQL، PHP)، MERN (MongoDB، Express، React، Node) | تنها چهار تکنولوژی: MongoDB، Express.js، Angular.js، Node.js |
مزایای Full Stack Developer:
مزایای MEAN Stack Developer:
هم Full Stack Developer و هم MEAN Stack Developer هر دو نقش مهمی در توسعه وب دارن، اما هر کدوم با توجه به تخصصها و تکنولوژیهای مورد استفاده شون برای پروژههای خاصی مناسبتر هستن. انتخاب بین این دو به نیازهای پروژه و تکنولوژیهای مورد استفاده بستگی داره.
می خوای بدونی یه MEAN Stack Developer چه کارهایی انجام میده؟ بیا این مسئولیتها رو با هم بررسی کنیم:
در کل، یه MEAN Stack Developer مسئول تمام مراحل توسعه وب هست و باید اپلیکیشنهای مقیاس پذیر و قوی بسازه.
برای موفقیت در این نقش، باید یه سری مهارتهای تخصصی داشته باشی:
حالا که با مزایای MEAN Stack آشنا شدی، بیا ببینیم چطور میتونی با این تکنولوژی شروع به کار کنی. برای شروع کار با MEAN Stack، ابتدا باید ابزارهای مورد نیاز رو نصب کنی. این ابزارها عبارتند از:
برای نصب Node.js میتونی به سایت رسمی Node.js بری و نسخه مناسب برای سیستم عامل ت رو دانلود و نصب کنی. بعد از نصب، میتونی با استفاده از دستور زیر نسخه نصب شده رو چک کنی:
node -v
برای نصب MongoDB میتونی به سایت رسمی MongoDB بری و نسخه مناسب برای سیستم عامل ت رو دانلود و نصب کنی. بعد از نصب، میتونی با استفاده از دستور زیر MongoDB رو اجرا کنی:
mongod
برای نصب Angular CLI میتونی از دستور زیر استفاده کنی:
npm install -g @angular/cli
برای نصب Express.js میتونی از دستور زیر استفاده کنی:
npm install express --save
حالا که ابزارهای مورد نیاز رو نصب کردی، بیا یه پروژه ساده MEAN Stack بسازیم. ابتدا یه دایرکتوری جدید برای پروژه ت ایجاد کن و وارد اون شو:
mkdir mean-project
cd mean-project
سپس با استفاده از Angular CLI یه پروژه جدید ایجاد کن:
ng new client
بعد از ایجاد پروژه Angular، یه دایرکتوری جدید برای سرور ایجاد کن:
mkdir server
cd server
npm init -y
حالا بیا یه سرور ساده با استفاده از Express.js بسازیم. یه فایل جدید به نام server.js ایجاد کن و کدهای زیر رو توی اون بنویس:
const express = require('express');
const app = express();
app.get('/api/hello', (req, res) => {
res.json({ message: 'Hello, 7Learn!' });
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
حالا بیا سرورمون رو به MongoDB متصل کنیم. برای این کار باید از کتابخانه mongoose استفاده کنیم. ابتدا این کتابخانه رو نصب کن:
npm install mongoose --save
سپس کدهای زیر رو به فایل server.js اضافه کن:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/mean-db', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
console.log('Connected to MongoDB');
});
حالا بیا یه مدل ساده برای کاربران بسازیم. یه فایل جدید به نام user.model.js ایجاد کن و کدهای زیر رو توی اون بنویس:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
name: String,
email: String,
age: Number,
});
const User = mongoose.model('User', userSchema);
module.exports = User;
حالا بیا روتهای API برای مدیریت کاربران ایجاد کنیم. یه فایل جدید به نام user.routes.js ایجاد کن و کدهای زیر رو توی اون بنویس:
const express = require('express');
const router = express.Router();
const User = require('./user.model');
router.get('/users', async (req, res) => {
const users = await User.find();
res.json(users);
});
router.post('/users', async (req, res) => {
const newUser = new User(req.body);
await newUser.save();
res.json(newUser);
});
module.exports = router;
حالا بیا روتهای API رو به سرورمون متصل کنیم. کدهای زیر رو به فایل server.js اضافه کن:
const bodyParser = require('body-parser');
const userRoutes = require('./user.routes');
app.use(bodyParser.json());
app.use('/api', userRoutes);
خب ، حالا میخوایم با هم یه پروژه واقعی رو پیاده سازی کنیم. هدف این آموزش ساخت یه API RESTful هست که عملیات CRUD (ایجاد، خواندن، به روزرسانی، حذف) رو برای یه اپلیکیشن مدیریت کارمندان پیاده سازی کنه. برای ذخیره سازی دادهها از یک کلاستر MongoDB Atlas استفاده میکنیم.
برای شروع به Node.js و یک کلاستر MongoDB Atlas نیاز داری.
node --version
ابتدا یه دایرکتوری برای پروژه مون میسازیم و واردش میشیم:
mkdir mean-stack-example
cd mean-stack-example
دایرکتوریها و فایلهای مورد نیاز برای اپلیکیشن سمت سرور رو میسازیم:
mkdir server && mkdir server/src
cd server
npm init -y
touch tsconfig.json .env
cd src
touch database.ts employee.routes.ts employee.ts server.ts
برای ساخت API و اتصال به MongoDB Atlas به چند بسته خارجی نیاز داریم. این بستهها رو نصب کن:
npm install cors dotenv express mongodb
npm install --save-dev typescript @types/cors @types/express @types/node ts-node
محتوای زیر رو در فایل tsconfig.json قرار بده:
{
"include": ["src/**/*"],
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"outDir": "./dist"
}
}
در فایل employee.ts کد زیر رو قرار بده تا ساختار کارمند رو تعریف کنه:
import * as mongodb from "mongodb";
export interface Employee {
name: string;
position: string;
level: "junior" | "mid" | "senior";
_id?: mongodb.ObjectId;
}
در فایل database.ts کد زیر رو قرار بده:
import * as mongodb from "mongodb";
import { Employee } from "./employee";
export const collections: {
employees?: mongodb.Collection<Employee>;
} = {};
export async function connectToDatabase(uri: string) {
const client = new mongodb.MongoClient(uri);
await client.connect();
const db = client.db("meanStackExample");
await applySchemaValidation(db);
const employeesCollection = db.collection<Employee>("employees");
collections.employees = employeesCollection;
}
async function applySchemaValidation(db: mongodb.Db) {
const jsonSchema = {
$jsonSchema: {
bsonType: "object",
required: ["name", "position", "level"],
additionalProperties: false,
properties: {
_id: {},
name: {
bsonType: "string",
description: "'name' is required and is a string",
},
position: {
bsonType: "string",
description: "'position' is required and is a string",
minLength: 5
},
level: {
bsonType: "string",
description: "'level' is required and is one of 'junior', 'mid', 'senior'",
enum: ["junior", "mid", "senior"],
},
},
},
};
await db.command({
collMod: "employees",
validator: jsonSchema
}).catch(async (error: mongodb.MongoServerError) => {
if (error.codeName === "NamespaceNotFound") {
await db.createCollection("employees", {validator: jsonSchema});
}
});
}
در فایل server.ts کد زیر رو قرار بده:
import * as dotenv from "dotenv";
import express from "express";
import cors from "cors";
import { connectToDatabase } from "./database";
dotenv.config();
const { ATLAS_URI } = process.env;
if (!ATLAS_URI) {
console.error("No ATLAS_URI environment variable has been defined in config.env");
process.exit(1);
}
connectToDatabase(ATLAS_URI)
.then(() => {
const app = express();
app.use(cors());
app.listen(5200, () => {
console.log(`Server running at http://localhost:5200...`);
});
})
.catch((error) => console.error(error));
حالا بیایم اپلیکیشن رو اجرا کنیم تا ببینیم آیا همه چیز درست کار میکنه یا نه:
npx ts-node src/server.ts
باید خروجی زیر رو ببینی:
Server running at http://localhost:5200...
عالی! حالا آماده ایم تا API RESTful برای کارمندانمون رو بسازیم.
خب، حالا میخوایم API رو بسازیم که شامل چهار عمل اصلی CRUD (ایجاد، خواندن، به روزرسانی، حذف) باشه. تو این قسمت، ما اندپوینتهای GET، POST، PUT و DELETE رو پیاده سازی میکنیم. این اندپوینتها برای مدیریت اطلاعات کارمندان در دیتابیس استفاده میشن.
فایل employee.routes.ts رو باز کن و کد زیر رو اضافه کن:
این اندپوینت لیست همه کارمندان رو برمی گردونه.
import * as express from "express";
import { ObjectId } from "mongodb";
import { collections } from "./database";
export const employeeRouter = express.Router();
employeeRouter.use(express.json());
employeeRouter.get("/", async (_req, res) => {
try {
const employees = await collections?.employees?.find({}).toArray();
res.status(200).send(employees);
} catch (error) {
res.status(500).send(error instanceof Error ? error.message : "Unknown error");
}
});
اینجا از متد find() استفاده میکنیم و چون پارامتر خالی {} بهش میدیم، همه کارمندان رو برمی گردونه. بعدش از متد toArray() استفاده میکنیم تا نتیجه به صورت آرایه برگرده.
این اندپوینت یک کارمند رو با استفاده از ID برمی گردونه.
employeeRouter.get("/:id", async (req, res) => {
try {
const id = req?.params?.id;
const query = { _id: new ObjectId(id) };
const employee = await collections?.employees?.findOne(query);
if (employee) {
res.status(200).send(employee);
} else {
res.status(404).send(`Failed to find an employee: ID ${id}`);
}
} catch (error) {
res.status(404).send(`Failed to find an employee: ID ${req?.params?.id}`);
}
});
اینجا از ObjectId برای تبدیل ID به فرمت مورد نیاز MongoDB استفاده میکنیم و بعدش از متد findOne() برای پیدا کردن کارمند استفاده میکنیم.
این اندپوینت یک کارمند جدید ایجاد میکنه.
employeeRouter.post("/", async (req, res) => {
try {
const employee = req.body;
const result = await collections?.employees?.insertOne(employee);
if (result?.acknowledged) {
res.status(201).send(`Created a new employee: ID ${result.insertedId}.`);
} else {
res.status(500).send("Failed to create a new employee.");
}
} catch (error) {
console.error(error);
res.status(400).send(error instanceof Error ? error.message : "Unknown error");
}
});
اینجا از متد insertOne() برای اضافه کردن کارمند جدید به دیتابیس استفاده میکنیم. در صورت موفقیت، یک پیام با کد 201 برمی گردونیم.
این اندپوینت یک کارمند رو به روزرسانی میکنه.
employeeRouter.put("/:id", async (req, res) => {
try {
const id = req?.params?.id;
const employee = req.body;
const query = { _id: new ObjectId(id) };
const result = await collections?.employees?.updateOne(query, { $set: employee });
if (result && result.matchedCount) {
res.status(200).send(`Updated an employee: ID ${id}.`);
} else if (!result?.matchedCount) {
res.status(404).send(`Failed to find an employee: ID ${id}`);
} else {
res.status(304).send(`Failed to update an employee: ID ${id}`);
}
} catch (error) {
const message = error instanceof Error ? error.message : "Unknown error";
console.error(message);
res.status(400).send(message);
}
});
اینجا از updateOne() برای به روزرسانی کارمند استفاده میکنیم. در صورت موفقیت، یک پیام با کد 200 برمی گردونیم.
این اندپوینت یک کارمند رو حذف میکنه.
employeeRouter.delete("/:id", async (req, res) => {
try {
const id = req?.params?.id;
const query = { _id: new ObjectId(id) };
const result = await collections?.employees?.deleteOne(query);
if (result && result.deletedCount) {
res.status(202).send(`Removed an employee: ID ${id}`);
} else if (!result) {
res.status(400).send(`Failed to remove an employee: ID ${id}`);
} else if (!result.deletedCount) {
res.status(404).send(`Failed to find an employee: ID ${id}`);
}
} catch (error) {
const message = error instanceof Error ? error.message : "Unknown error";
console.error(message);
res.status(400).send(message);
}
});
اینجا از deleteOne() برای حذف کارمند استفاده میکنیم. در صورت موفقیت، یک پیام با کد 202 برمی گردونیم.
حالا باید سرور Express رو طوری تنظیم کنیم که از این روتها استفاده کنه. ابتدا در ابتدای فایل server.ts، روت رو ایمپورت کن:
import { employeeRouter } from "./employee.routes";
بعدش، قبل از فراخوانی app.listen()، کد زیر رو اضافه کن:
app.use("/employees", employeeRouter);
حالا سرور رو مجدداً راه اندازی کن:
npx ts-node src/server.ts
باید همون پیام قبلی رو ببینی:
Server running at http://localhost:5200...
عالی! حالا یه API ساده برای مدیریت کارمندان ساختیم. مرحله بعدی، ساخت یک اپلیکیشن وب با استفاده از Angular هست که با این API تعامل کنه.
مرحله بعدی ساخت یک اپلیکیشن وب با استفاده از Angular هست که با API ما تعامل داشته باشه. برای این کار از Angular CLI استفاده میکنیم.
npm install -g @angular/cli
حالا یه پروژه جدید Angular به اسم client بساز:
ng new client --inline-template --inline-style --minimal --routing --style=css
cd client
این دستور یه اپلیکیشن جدید با تنظیمات مینیمال ایجاد میکنه و فایلهای CSS و HTML رو به صورت خطی داخل کامپوننتها قرار میده.
حالا اپلیکیشن رو اجرا کن تا مطمئن بشی همه چی درسته:
ng serve -o
باید یه تب جدید تو مرورگرت باز بشه و اپلیکیشن رو نشون بده که نوشته "Welcome to client!".
برای استایل دهی، از Angular Material استفاده میکنیم. برای نصبش، دستور زیر رو اجرا کن:
ng add @angular/material
مثل اپلیکیشن سمت سرور، یه اینترفیس برای کارمندان میسازیم. دستور زیر رو اجرا کن:
ng generate interface employee
بعد فایل src/app/employee.ts رو باز کن و کد زیر رو اضافه کن:
export interface Employee {
name: string;
position: string;
level: 'junior' | 'mid' | 'senior';
_id?: string;
}
خب، حالا وقتشه که سرویس ارتباط با API رو بسازیم. تو Angular، پیشنهاد میشه که منطق کسب وکار رو از منطق نمایش جدا کنیم. برای همین، یه سرویس میسازیم که تمام ارتباطات با اندپوینت /employee از API رو مدیریت کنه. این سرویس توسط کامپوننتها در اپلیکیشن استفاده میشه.
برای ایجاد سرویس، دستور زیر رو اجرا کن:
ng generate service employee
این دستور یه سرویس جدید به اسم EmployeeService تو فایل src/app/employee.service.ts میسازه. محتوای این فایل رو با کد زیر جایگزین کن:
import { Injectable, signal } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Employee } from './employee';
@Injectable({
providedIn: 'root'
})
export class EmployeeService {
private url = 'http://localhost:5200';
employees$ = signal<Employee[]>([]);
employee$ = signal<Employee>({} as Employee);
constructor(private httpClient: HttpClient) { }
private refreshEmployees() {
this.httpClient.get<Employee[]>(`${this.url}/employees`)
.subscribe(employees => {
this.employees$.set(employees);
});
}
getEmployees() {
this.refreshEmployees();
return this.employees$();
}
getEmployee(id: string) {
this.httpClient.get<Employee>(`${this.url}/employees/${id}`).subscribe(employee => {
this.employee$.set(employee);
return this.employee$();
});
}
createEmployee(employee: Employee) {
return this.httpClient.post(`${this.url}/employees`, employee, { responseType: 'text' });
}
updateEmployee(id: string, employee: Employee) {
return this.httpClient.put(`${this.url}/employees/${id}`, employee, { responseType: 'text' });
}
deleteEmployee(id: string) {
return this.httpClient.delete(`${this.url}/employees/${id}`, { responseType: 'text' });
}
}
ما از سرویس HttpClient برای ایجاد درخواستهای HTTP به API استفاده میکنیم. متد refreshEmployees() برای گرفتن لیست کامل کارمندان استفاده میشه و این لیست رو در سیگنالی به نام employees$ ذخیره میکنه که برای بقیه اپلیکیشن در دسترس هست.
سرویس HttpClient باید به اپلیکیشن اضافه بشه. برای این کار، وارد فایل src/app/app.config.ts شو و کد زیر رو اضافه کن:
import { provideHttpClient, withFetch } from '@angular/common/http';
بعدش، این فانکشن رو به لیست providers در متغیر ApplicationConfig اضافه کن:
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(withFetch()),
// ...
],
};
فانکشن withFetch برای پیکربندی سرویس HttpClient برای استفاده از API fetch استفاده میشه.
حالا میخوایم یه صفحه برای نمایش لیست کارمندان بسازیم. تو Angular، کامپوننتها قطعات قابل استفاده مجددی از کد هستن که میتونن برای نمایش ویو استفاده بشن. یه کامپوننت جدید به اسم EmployeesList میسازیم و اون رو به عنوان روت /employees در اپلیکیشن ثبت میکنیم.
برای ایجاد کامپوننت، دستور زیر رو اجرا کن:
ng generate component employees-list
فایل src/app/employees-list/employees-list.component.ts رو باز کن و محتوای زیر رو جایگزین کن:
import { Component, OnInit, WritableSignal } from '@angular/core';
import { Employee } from '../employee';
import { EmployeeService } from '../employee.service';
import { RouterModule } from '@angular/router';
import { MatTableModule } from '@angular/material/table';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
@Component({
selector: 'app-employees-list',
standalone: true,
imports: [RouterModule, MatTableModule, MatButtonModule, MatCardModule],
styles: [
`
table {
width: 100%;
button:first-of-type {
margin-right: 1rem;
}
}
`,
],
template: `
<mat-card>
<mat-card-header>
<mat-card-title>Employees List</mat-card-title>
</mat-card-header>
<mat-card-content>
<table mat-table [dataSource]="employees$()">
<ng-container matColumnDef="col-name">
<th mat-header-cell *matHeaderCellDef>Name</th>
<td mat-cell *matCellDef="let element">{{ element.name }}</td>
</ng-container>
<ng-container matColumnDef="col-position">
<th mat-header-cell *matHeaderCellDef>Position</th>
<td mat-cell *matCellDef="let element">{{ element.position }}</td>
</ng-container>
<ng-container matColumnDef="col-level">
<th mat-header-cell *matHeaderCellDef>Level</th>
<td mat-cell *matCellDef="let element">{{ element.level }}</td>
</ng-container>
<ng-container matColumnDef="col-action">
<th mat-header-cell *matHeaderCellDef>Action</th>
<td mat-cell *matCellDef="let element">
<button mat-raised-button [routerLink]="['edit/', element._id]">
Edit
</button>
<button
mat-raised-button
color="warn"
(click)="deleteEmployee(element._id || '')"
>
Delete
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</mat-card-content>
<mat-card-actions>
<button mat-raised-button color="primary" [routerLink]="['new']">
Add a New Employee
</button>
</mat-card-actions>
</mat-card>
`,
})
export class EmployeesListComponent implements OnInit {
employees$ = {} as WritableSignal<Employee[]>;
displayedColumns: string[] = [
'col-name',
'col-position',
'col-level',
'col-action',
];
constructor(private employeesService: EmployeeService) {}
ngOnInit() {
this.fetchEmployees();
}
deleteEmployee(id: string): void {
this.employeesService.deleteEmployee(id).subscribe({
next: () => this.fetchEmployees(),
});
}
private fetchEmployees(): void {
this.employees$ = this.employeesService.employees$;
this.employeesService.getEmployees();
}
}
حالا باید این کامپوننت رو به عنوان روت در فایل src/app/app.routes.ts ثبت کنیم. محتوای این فایل رو با کد زیر جایگزین کن:
import { Routes } from '@angular/router';
import { EmployeesListComponent } from './employees-list/employees-list.component';
export const routes: Routes = [
{ path: '', component: EmployeesListComponent, title: 'Employees List' },
];
حالا فایل src/app/app.component.ts رو باز کن و محتوای زیر رو جایگزین کن:
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { EmployeesListComponent } from './employees-list/employees-list.component';
import { MatToolbarModule } from '@angular/material/toolbar';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, EmployeesListComponent, MatToolbarModule],
styles: [
`
main {
display: flex;
justify-content: center;
padding: 2rem 4rem;
}
`,
],
template: `
<mat-toolbar>
<span>Employees Management System</span>
</mat-toolbar>
<main>
<router-outlet />
</main>
`,
})
export class AppComponent {
title = 'client';
}
حالا مرورگر رو رفرش کن تا ببینی همه چیز درست کار میکنه یا نه. اگر همه چی درست باشه، باید لیست کارمندان رو ببینی.
خب، تا حالا یه لیست از کارمندان داریم، ولی هنوز نمیتونیم کارمند جدید اضافه کنیم. بیاید یه صفحه جدید برای افزودن کارمندان ایجاد کنیم.
برای ایجاد فرم کارمند که شامل فیلدهای نام، موقعیت شغلی و سطح هست، از ReactiveFormsModule و FormBuilder تو Angular استفاده میکنیم.
ابتدا یه کامپوننت به اسم EmployeeForm ایجاد کن که هم برای افزودن و هم برای ویرایش کارمندان استفاده بشه:
ng g c employee-form
محتوای فایل employee-form.component.ts رو با کد زیر جایگزین کن:
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatRadioModule } from '@angular/material/radio';
import { MatButtonModule } from '@angular/material/button';
import { Employee } from '../employee';
@Component({
selector: 'app-employee-form',
standalone: true,
imports: [
ReactiveFormsModule,
MatFormFieldModule,
MatInputModule,
MatRadioModule,
MatButtonModule,
],
styles: [
`
.employee-form {
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 2rem;
}
.mat-mdc-radio-button ~ .mat-mdc-radio-button {
margin-left: 16px;
}
.mat-mdc-form-field {
width: 100%;
}
`
],
template: `
<form class="employee-form" autocomplete="off" [formGroup]="employeeForm" (submit)="submitForm()">
<mat-form-field>
<mat-label>Name</mat-label>
<input matInput placeholder="Name" formControlName="name" required />
<mat-error *ngIf="name.invalid">Name must be at least 3 characters long.</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Position</mat-label>
<input matInput placeholder="Position" formControlName="position" required />
<mat-error *ngIf="position.invalid">Position must be at least 5 characters long.</mat-error>
</mat-form-field>
<mat-radio-group formControlName="level" aria-label="Select an option">
<mat-radio-button value="junior" required>Junior</mat-radio-button>
<mat-radio-button value="mid">Mid</mat-radio-button>
<mat-radio-button value="senior">Senior</mat-radio-button>
</mat-radio-group>
<button mat-raised-button color="primary" type="submit" [disabled]="employeeForm.invalid">Add</button>
</form>
`
})
export class EmployeeFormComponent {
@Input() initialState: Employee | undefined;
@Output() formValuesChanged = new EventEmitter<Employee>();
@Output() formSubmitted = new EventEmitter<Employee>();
employeeForm = this.formBuilder.group({
name: ['', [Validators.required, Validators.minLength(3)]],
position: ['', [Validators.required, Validators.minLength(5)]],
level: ['junior', [Validators.required]],
});
constructor(private formBuilder: FormBuilder) {
if (this.initialState) {
this.employeeForm.setValue({
name: this.initialState.name || '',
position: this.initialState.position || '',
level: this.initialState.level || 'junior',
});
}
}
get name() {
return this.employeeForm.get('name')!;
}
get position() {
return this.employeeForm.get('position')!;
}
get level() {
return this.employeeForm.get('level')!;
}
submitForm() {
this.formSubmitted.emit(this.employeeForm.value as Employee);
}
}
اینجا از FormBuilder برای ایجاد یک فرم واکنش گرا با سه فیلد استفاده میکنیم و همچنین اعتبارسنجیها رو به فرم اضافه میکنیم.
حالا یه کامپوننت جدید به اسم AddEmployee برای افزودن کارمند ایجاد کن:
ng generate component add-employee
محتوای فایل add-employee.component.ts رو با کد زیر جایگزین کن:
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { EmployeeFormComponent } from '../employee-form/employee-form.component';
import { Employee } from '../employee';
import { EmployeeService } from '../employee.service';
import { MatCardModule } from '@angular/material/card';
@Component({
selector: 'app-add-employee',
standalone: true,
imports: [EmployeeFormComponent, MatCardModule],
template: `
<mat-card>
<mat-card-header>
<mat-card-title>Add a New Employee</mat-card-title>
</mat-card-header>
<mat-card-content>
<app-employee-form (formSubmitted)="addEmployee($event)"></app-employee-form>
</mat-card-content>
</mat-card>
`,
styles: [``]
})
export class AddEmployeeComponent {
constructor(
private router: Router,
private employeeService: EmployeeService
) {}
addEmployee(employee: Employee) {
this.employeeService.createEmployee(employee).subscribe({
next: () => {
this.router.navigate(['/']);
},
error: (error) => {
alert('Failed to create employee');
console.error(error);
},
});
this.employeeService.getEmployees();
}
}
ما از EmployeeFormComponent استفاده میکنیم و هر بار که AddEmployeeComponent یه فرم دریافت میکنه، از EmployeeService برای ایجاد کارمند جدید استفاده میکنه.
حالا یه کامپوننت جدید به اسم EditEmployee برای ویرایش کارمند ایجاد کن:
ng generate component edit-employee
محتوای فایل edit-employee.component.ts رو با کد زیر جایگزین کن:
import { Component, OnInit, WritableSignal } from '@angular/core';
import { EmployeeFormComponent } from '../employee-form/employee-form.component';
import { ActivatedRoute, Router } from '@angular/router';
import { Employee } from '../employee';
import { EmployeeService } from '../employee.service';
import { MatCardModule } from '@angular/material/card';
@Component({
selector: 'app-edit-employee',
standalone: true,
imports: [EmployeeFormComponent, MatCardModule],
template: `
<mat-card>
<mat-card-header>
<mat-card-title>Edit an Employee</mat-card-title>
</mat-card-header>
<mat-card-content>
<app-employee-form [initialState]="employee()" (formSubmitted)="editEmployee($event)"></app-employee-form>
</mat-card-content>
</mat-card>
`,
styles: [``]
})
export class EditEmployeeComponent implements OnInit {
employee = {} as WritableSignal<Employee>;
constructor(
private router: Router,
private route: ActivatedRoute,
private employeeService: EmployeeService
) {}
ngOnInit() {
const id = this.route.snapshot.paramMap.get('id');
if (!id) {
alert('No id provided');
}
this.employeeService.getEmployee(id!);
this.employee = this.employeeService.employee$;
}
editEmployee(employee: Employee) {
this.employeeService.updateEmployee(this.employee()._id || '', employee).subscribe({
next: () => {
this.router.navigate(['/']);
},
error: (error) => {
alert('Failed to update employee');
console.error(error);
},
});
}
}
تنها تفاوت قابل توجه با AddEmployeeComponent اینه که ما از ID کارمند از URL استفاده میکنیم، کارمند رو از API میگیریم و بعد اون رو به فرم پاس میدیم.
حالا باید ناوبری به صفحات جدید رو اضافه کنیم. فایل app-routing.module.ts رو باز کن و کد زیر رو اضافه کن:
import { Routes } from '@angular/router';
import { EmployeesListComponent } from './employees-list/employees-list.component';
import { AddEmployeeComponent } from './add-employee/add-employee.component';
import { EditEmployeeComponent } from './edit-employee/edit-employee.component';
export const routes: Routes = [
{ path: '', component: EmployeesListComponent, title: 'Employees List' },
{ path: 'new', component: AddEmployeeComponent },
{ path: 'edit/:id', component: EditEmployeeComponent },
];
حالا میتونیم اپلیکیشن رو تست کنیم. یه کارمند جدید بساز، بعد با کلیک روی دکمه Edit، اطلاعاتش رو ویرایش کن و تغییرات رو ببین. در نهایت میتونی با کلیک روی دکمه Delete، کارمند رو حذف کنی.
با این مراحل، یه اپلیکیشن مدیریت کارمندان ساده با MEAN Stack ساختیم که شامل تمام عملیات CRUD هست. اگر سوال یا چالشی داشتی، من اینجا هستم تا کمک کنم!
بله، MEAN Stack بر پایه جاوااسکریپت ساخته شده که یادگیریش نسبتاً ساده و شهودی هست. استفاده از MongoDB که یه دیتابیس NoSQL هست و با ساختارهای JSON کار میکنه، باعث میشه یادگیری و استفاده از این تکنولوژی راحتتر باشه. البته این که چقدر سریع و آسون یاد میگیری به چند عامل بستگی داره:
البته، اگه همه این موارد رو هم ندونی، باز هم میتونی MEAN رو یاد بگیری چون منابع آموزشی زیادی آنلاین وجود دارن که میتونی ازشون استفاده کنی.
بله، MEAN یه راه حل کامل فول استک محسوب میشه. این استک شامل سه لایه اصلی هست: لایه نمایش (Angular.js)، لایه اپلیکیشن (Express.js و Node.js)، و لایه دیتابیس (MongoDB).
MEAN و MERN هر دو فریم ورکهای ارزشمندی هستن. توسعه دهندگان بر اساس تخصص خودشون در AngularJS یا ReactJS، نیازهای پروژه، اندازه محیط، نیازهای عملکردی و ملاحظات مقیاس پذیری تصمیم میگیرن که از کدوم استفاده کنن.
بله، تقاضا برای توسعه دهندگان MEAN Stack در سال 2024 بالاست و پیش بینی میشه که این تقاضا بیشتر هم بشه. به علاوه، چون نرم افزار MEAN هزینه کمی داره و استفاده ازش آسونه، خیلی از کسب وکارهای کوچک و متوسط به توسعه دهندگان MEAN Stack بیشتر وابسته میشن.
در نهایت، استفاده از MEAN Stack میتونه یه انتخاب عالی برای توسعه دهندههای وب باشه. این تکنولوژی بهت اجازه میده تا با یه زبان (جاوا اسکریپت) تمام بخشهای اپلیکیشن ت رو بسازی و از ابزارهای یکپارچه و هماهنگ استفاده کنی. امیدوارم این مقاله بهت کمک کرده باشه تا با MEAN Stack آشنا بشی و آماده باشی تا پروژههای جذابت رو با این تکنولوژی بسازی.
دوره الفبای برنامه نویسی با هدف انتخاب زبان برنامه نویسی مناسب برای شما و پاسخگویی به سوالات متداول در شروع یادگیری موقتا رایگان شد: