مقدمه

در درس قبل، یک وب‌سرور ساده را با استفاده از Node.js ایجاد کردیم که به درخواست‌های ورودی (incoming requests) پاسخ می‌دهد. البته وب‌سرور ما فعلاً برای همه‌ی درخواست‌ها پاسخ یکسانی را تولید و ارسال می‌کند و آن نمایش عبارت Hello, World! است. در این درس با مفهوم کلیدی مسیریابی یا Routing آشنا شده و نحوه‌ی پیاده‌سازی یک مکانیزم مسیریابی را در پروژه‌های Node.js می‌بینیم. با پیاده‌سازی یک مکانیزم مسیریابی و تعریف مسیرها (routes) در پروژه، برنامه قادر می‌شود که برای درخواست‌های مختلف، پاسخ‌های متفاوتی ایجاد کند.

تعریف Route در Node.js

ابتدا نگاهی به وب‌سروری که در درس قبل ایجاد کردیم، بیندازید. فایل app.js دارای محتویات زیر است.

Copy Icon app.js
const http = require('http');

// Create a server object
const app = http.createServer((req, res) => {
  // Set the response header with a status code and content type
  res.writeHead(200, { 'Content-Type': 'text/plain' });
                
  // Send the response body "Hello, World!"
  res.end('Hello, World!\n');
});
            
// Define the port number and IP address
const PORT = 3000;
const HOSTNAME = '127.0.0.1';
            
// Make the server listen to requests
app.listen(PORT, HOSTNAME, () => {
  console.log(`Server running at http://${HOSTNAME}:${PORT}/`);
});

همانطور که در درس قبل هم دیدیم، اگر این فایل را با استفاده از کامند node app.js اجرا کنیم، وب‌سرور ما استارت شده و آماده‌ی دریافت درخواست‌ها خواهد بود. این موضوع را می‌توانید با استفاده از یک کلاینت (مثلاً یک مرورگر یا ابزاری مثل cURL) تست کنید. برای مثال، یک مرورگر وب اجرا کنید و آدرس http://127.0.0.1:3000 یا http://localhost:3000 را در نوار آدرس وارد کنید. وب‌سرور لوکال ما درخواست را دریافت کرده و پاسخی را تولید می‌کند که منجر به نمایش عبارت Hello, World! می‌شود.

در حال حاضر، وب‌سرور ما فقط قادر به مدیریت همین یک URL است. اما حالا قصد داریم این قابلیت را برای وب‌سرور فراهم کنیم که بتواند چند URL دیگر را هم هندل کند و برای هر URL یک پاسخ متفاوت تولید کند. این کاری است که با تعریف مسیرها (routes) در پروژه محقق می‌شود.

یک route یا مسیر چیزی نیست جز یک آدرس URL که به یک پاسخ مشخص اشاره می‌کند و routing یا مسیریابی یعنی اینکه آدرس‌های URL را به پاسخ‌ها متناظر کنیم؛ طوری که هر URL متناظر با یک پاسخ باشد. به این ترتیب، یک نقشه در اختیار Node.js قرار می‌گیرد که از روی آن می‌فهمد باید برای هر URL چه پاسخی را تولید کند.

اضافه کردن Route به وب‌سرور

برای اضافه کردن چند route به وب‌سرور می‌توانیم از یک گزاره ی if برای بررسی مقدار req.url و تولید پاسخ بر اساس آن، استفاده کنیم.

Copy Icon app.js
const http = require('http');

const app = http.createServer((req, res) => {
  const { url } = req;
  console.log(url);
  if (url === '/') {
    res.end('Hello, World!');
  } else if (url === '/contact') {
    res.end('The Contact Page');
  } else if (url === '/about') {
    res.end('The About Page');
  } else {
    res.writeHead(404)
    res.end('Not Found');
  }
});
            
const PORT = 3000;
const HOSTNAME = '127.0.0.1';
            
app.listen(PORT, HOSTNAME, () => {
  console.log(`Server running at http://${HOSTNAME}:${PORT}/`);
});

در اینجا ابتدا مقدار url را از شیء req استخراج کرده‌ایم تا مجبور نباشیم هر بار که به آن نیاز داریم، عبارت req.url را بنویسیم. سپس، مقدار url را لاگ کرده‌ایم و یک گزاره‌ی if ایجاد کرده و پاسخ‌های متفاوتی برای درخواست‌ها ایجاد کرده‌ایم. برای مسیرهایی که تعریف نشده‌اند، کد خطای 404 برگردانده می‌شود. کد پاسخ پیش‌فرض 200 است که نشان می‌دهد که درخواست با موفقیت پردازش شده اما کد 404 نشان‌دهنده‌ی یک خطای Not Found است.

اگر سرور در حال اجرا باشد، برای اعمال تغییرات بالا باید ابتدا سرور را متوقف کنیم و مجدداً آن را راه‌اندازی کنیم. حالا می‌توانید آدرس‌های URL مختلف را تست کنید و ببینید که برای هر URL یک پاسخ متفاوت تولید می‌شود.

استفاده از پکیج Nodemon برای توسعه

گفتیم که برای اعمال تغییرات، باید سرور ری‌استارت شود. اما این که با هر تغییر در پروژه، مجبور به ری‌استارت سرور باشیم، اتفاق چندان مطلوبی نیست. خوشبختانه می‌توانیم با استفاده از پکیجی با نام nodemon این مشکل را حل کنیم. با استفاده از کامند زیر این پکیج را نصب می‌کنیم.

$ npm install -D nodemon

پکیج nodemon در کار توسعه به دردمان می‌خورد و روی سرور نهایی به آن نیاز نیست. از این‌رو آن را با استفاده از آپشن -D که معادل --save-dev است، نصب کرده‌ایم. اگر بعد از تصب nodemon نگاهی به فایل package.json بیندازید، خواهید دید که این پکیح به بخش devDependencies اضافه شده است.

حالا اگر به جای کامند node app.js از کامند npx nodemon app.js برای اجرای اپلیکیشن و راه‌اندازی وب‌سرور استفاده کنیم، nodemon با هر تغییر در کدهای پروژه، سرور را ری‌استارت می‌کند و ما از انجام دستی و مکرر این کار بی‌نیاز می‌شویم.

بحث در مورد Node.js را می‌توان با مباحث دیگری مثل بهبود مدل مسیریابی، میزبانی از فایل‌های استاتیک و بسیاری موضوعات دیگر ادامه داد. اما با وجود ارگونومی بالاتر Node.js نسبت به سایر تکنولوژی‌های Backend، همچنان کار توسعه بدون استفاده از یک فریمورک Backend ساده نیست و چالش‌های زیادی دارد. هدف اصلی ما در این دوره این است که شما را با فریمورک Express.js آشنا کنیم که یک فریمورک مینیمال بسیار کارامد و محبوب است که روی Node.js نوشته شده و کار توسعه‌ی Backend را خیلی ساده‌تر می‌کند. البته لازم بود که یک آشنایی کلی و مقدماتی با معماری Node.js پیدا کنید و به همین دلیل چند درس لبتدایی را به این موضوع اختصاص دادیم. اما از این نقطه به بعد، موضوع اصلی مورد بحث ما فریمورک Express و نحوه‌ی استفاده از آن برای تولید اپلیکیشن‌های وب خواهد بود. البته داستان Express از Node.js جدا نیست، بلکه یک لایه بر روی آن است که کار ما را ساده‌تر می‌کند.