همیشه برای توسعهدهندهها مهم بوده که بتونن اپلیکیشنهاشون رو روی یه مجموعه یکپارچه از تکنولوژیهای پایه بسازن. وقتی از همون اول کار یه سری ابزار استاندارد و هماهنگ در اختیار داشته باشی، میتونی بیشتر وقتت رو روی ساختن چیزی بذاری که کسبوکارت رو متمایز میکنه. اینجوری دیگه لازم نیست از صفر شروع کنی و کلی قطعه پراکنده رو به هم بچسبونی. اینجاست که 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 آشنا بشی و آماده باشی تا پروژههای جذابت رو با این تکنولوژی بسازی.
دوره الفبای برنامه نویسی با هدف انتخاب زبان برنامه نویسی مناسب برای شما و پاسخگویی به سوالات متداول در شروع یادگیری موقتا رایگان شد: