مقدمه
فریمورک Express.js یکی از محبوبترین فریمورکهای Backend و محبوبترین فریمورک Node.js است. در این درس، ابتدا یک معرفی کلی از فریمورک Express ارائه میدهیم و سپس، از آن برای ایجاد یک وبسرور ساده استفاده میکنیم.
آموزش Node.js و Express
فریمورک Express.js یکی از محبوبترین فریمورکهای Backend و محبوبترین فریمورک Node.js است. در این درس، ابتدا یک معرفی کلی از فریمورک Express ارائه میدهیم و سپس، از آن برای ایجاد یک وبسرور ساده استفاده میکنیم.
همانطور که در پایان درس قبل اشاره شد، برای توسعهی اپ با Node.js دو راه داریم. راه اول که با مشقتهای زیادی همراه است، این است که فرایند توسعه را با Node.js و بدون استفاده از فریمورکها انجام دهیم و راه دوم این است که دست از تلاش برای اختراع مجدد چرخ برداریم و از یک فریمورک که روی ماژولهای Node.js مانند http نوشته شده، استفاده کنیم.
در مورد توسعهی Frontend، استفاده یا عدم استفاده از فریمورکها بیش از هر چیز به سلیقهی توسعهدهنده بستگی دارد و نمیتوان با قاطعیت از درست یا غلط بودن استفاده از فریمورکها صحبت کرد. اما وقتی پای توسعهی Backend در میان باشد، تقریباً همهی صاحبنظران عرصهی توسعهی نرمافزار بر استفاده از فریمورکها تأکید دارند.
اولین نسخه از فریمورک Express تقریباً یک سال بعد از انتشار Node.js یعنی اواخر سال 2010 منتشر شد و در حال حاضر، این فریمورک در نسخهی ماژور 4 قرار دارد. سادگی و ماهیت مینیمال این فریمورک باعث محبوبیت آن نزد کاربران شده است. برای یک فریمورک وب، محبوبیت یک عامل کلیدی است؛ چون شاخصی است برای این که آیا توسعه و نگهداری از فریمورک ادامه پیدا میکند یا خیر و اینکه وضعیت مستندات، پشتیبانی و کتابخانههای جانبی برای آن چطور خواهد بود.
گفتیم یکی از دلایل محبوبیت Express، مینیمال بودن آن است. اجازه دهید کمی بیشتر در این مورد توضیح بدهیم و ببینیم اساساً مینیمال بودن یک فریمورک به چه معناست و چه تبعات منفی و مثبتی دارد.
یک فریمورک وب میتواند opinionated یا unopinionated باشد؛ یعنی میتواند اهل نظر دادن باشد یا نباشد.
پس، Express یک فریمورک unopinionated است و شما میتوانید تقریباً هر middleware سازگار دلخواه را به زنجیرهی پردازش درخواست اضافه کنید؛ به هر ترتیبی که دوست دارید. شما میتوانید اپلیکیشن را در یک فایل یا چند فایل ساختار دهید و از هر ساختار دایرکتوری استفاده کنید. این ویژگی، یک شمشیر دولبه است که از یک طرف انعطاف بیشتری دارد و ما را به یک روش خاص محدود نمیکند و از طرف دیگر، میتواند با چالشهایی برای انتخاب روش و ابزار مناسب همراه باشد.
برای استفاده از فریمورک Express، ابتدا باید آن را روی پروژه نصب کنیم. یک پروژهی جدید با نامی دلخواه ایجاد کنید، فایل اصلی آن را app.js بنامید و کامند زیر را از درون دایرکتوری پروژه اجرا کنید.
$ npm install express
بعد از نصب پکیج، کد زیر را در فایل app.js وارد کنید.
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello From Express');
});
app.get('/contact', (req, res) => {
res.send('The Contact Page');
});
app.get('/about', (req, res) => {
res.send('The About Page');
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
در اینجا ماژول express را به پروژه وارد (import) کردهایم و سپس، با فراخوانی تابع express() یک اپلیکیشن Express ایجاد کردهایم. در این اپلیکیشن، یک وبسرور تعریف شده که مشابه وبسروری است که در فصل قبل با استفاده از Node.js ایجاد کرده بودیم. اما این بار به جای استفاده از گزارههای if، هر route به صورت مستقل تعریف شده است.
متد app.get() برای پاسخ به درخواستهای HTTP از نوع GET کاربرد دارد. یک متد مشابه با نام app.post() هم برای مدیریت درخواستهای از نوع POST قابل استفاده است که در آینده از آن استفاده خواهیم کرد.
آخرین route در کد بالا با استفاده از کاراکتر * ایجاد شده که یک کاراکتر wildcard است و به این معناست که هر درخواستی منجر به تولید کد وضعیت 404 و ارسال یک پیغام Not Found شود. البته با توجه به اینکه در Express ترتیب قرارگیری روتها مهم است، فقط هر درخواستی که با روتهای قبلی مطابق نباشد، خطای 404 را تولید میکند.
در نهایت، استفاده از متد app.listen() باعث شده که سرور بتواند به درخواستهای ورودی گوش دهد و پاسخ مناسب را برای هر درخواست برگرداند.
اگر دقت کرده باشید، بر خلاف وبسروری که قبلاً با استفاده از Node.js ایجاد کردیم، در اینجا از متد console.log() برای لاگ آدرس URL استفاده نکردهایم. اگر بخواهیم این کار را انجام دهیم، باید با توجه به مستقل بودن روتها از یکدیگر، از متد console.log() برای تکتک روتها استفاده کنیم. یعنی:
app.get('/', (req, res) => {
console.log(req.url);
res.send('Hello From Node.js');
});
app.get('/contact', (req, res) => {
console.log(req.url);
res.send('The Contact Page');
});
اما بهجای این کار، میتوانیم از یک ابزار logger به نام Morgan استفاده کنیم که به طور خودکار و برای هر درخواست، اطلاعاتی را در مورد آن درخواست لاگ میکند. برای استفاده از Morgan باید ابتدا آن را نصب کنیم.
$ npm install morgan
حالا در فایل app.js ابتدا این پکیج را به پروژه وارد میکنیم و سپس، از یک متد با نام use() به صورت زیر استفاده میکنیم.
const express = require('express');
const morgan = require('morgan');
const app = express();
app.use(morgan('dev'));
app.get('/', (req, res) => {
res.send('Hello From Node.js');
});
app.get('/contact', (req, res) => {
res.send('The Contact Page');
});
app.get('/about', (req, res) => {
res.send('The About Page');
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
متد use() یک تابع middleware را رجیستر میکند تا در هر درخواستی اجرا شود. آرگومان تابع morgan() مشخصکنندهی فرمت اطلاعاتی است که لاگ میشوند. مقادیر دیگری مثل tiny یا common هم قابل استفاده هستند اما برای لاگ در محیط توسعه، بهترین گزینه dev است.
در مورد مفهوم middleware و نقش کلیدی آن در اپلیکیشنهای Express بعداً صحلت خواهیم کرد اما فعلاً سرور را راهاندازی کنید و درخواستهایی را با استفاده از یک مرورگر ایجاد کنید. خواهید دید که در هر درخواست، اطلاعاتی مانند متد HTTP مربوط به درخواست، URL درخواست، کد وضعیت (status code) مربوط به پاسخ و زمان لازم برای تولید پاسخ توسط سرور در کنسول نمایش داده میشود.
GET / 304 5.390 ms - - GET /about 304 0.654 ms - - GET /contact 304 0.671 ms - -