توسعه API مدرن با Node.js، Express و TypeScript با استفاده از Clean Architecture

Summarize this content to 400 words in Persian Lang
API ها ستون فقرات برنامه های کاربردی وب مدرن هستند. با افزایش پیچیدگی برنامهها، اتخاذ معماری که مقیاسپذیری، قابلیت نگهداری و آزمایشپذیری را ارتقا میدهد، بسیار مهم است. در این وبلاگ، نحوه ساخت یک API مدرن با استفاده از Node.js، Express، و TypeScript را با رعایت اصول Clean Architecture بررسی خواهیم کرد.
لطفا برای حمایت از کانال من و دریافت آموزش های بیشتر توسعه وب، در کانال یوتیوب من مشترک شوید.
📑 فهرست مطالب
1. 🧩 مقدمه ای بر معماری پاک
بازگشت به فهرست مطالب
معماری پاک، معرفی شده توسط رابرت سی مارتین (عمو باب)، بر جداسازی نگرانی ها در یک برنامه تاکید دارد. این ایده را ترویج می کند که منطق تجاری باید مستقل از هر چارچوب، پایگاه داده یا سیستم خارجی باشد. این باعث میشود برنامه ماژولارتر، آزمایش آسانتر و سازگار با تغییرات باشد.
اصول کلیدی معماری پاک:
استقلال: منطق اصلی کسب و کار نباید به کتابخانه های خارجی، UI، پایگاه های داده یا چارچوب ها بستگی داشته باشد.
آزمایش پذیری: آزمایش برنامه باید بدون اتکا به سیستم های خارجی آسان باشد.
انعطاف پذیری: تغییر یا جایگزینی بخش هایی از برنامه باید آسان باشد بدون اینکه روی دیگران تأثیر بگذارد.
2. 💡 چرا Node.js، Express و TypeScript؟
بازگشت به فهرست مطالب
Node.js
Node.js یک زمان اجرا قدرتمند جاوا اسکریپت است که به شما امکان می دهد برنامه های شبکه مقیاس پذیر بسازید. غیر مسدود کننده و رویداد محور است و برای ساخت APIهایی که تعداد زیادی درخواست را مدیریت می کنند ایده آل است.
اکسپرس
Express یک چارچوب وب مینیمالیستی برای Node.js است. مجموعه ای قوی از ویژگی ها را برای ساخت برنامه های کاربردی وب و موبایل و API ارائه می دهد. سادگی آن شروع را آسان می کند و بسیار توسعه پذیر است.
TypeScript
TypeScript ابر مجموعه ای از جاوا اسکریپت است که انواع استاتیک را اضافه می کند. استفاده از TypeScript در برنامه Node.js به شناسایی خطاها در مراحل اولیه توسعه، بهبود خوانایی کد و افزایش تجربه کلی توسعه دهنده کمک می کند.
3. 🚧 راه اندازی پروژه
بازگشت به فهرست مطالب
ابتدا بیایید یک پروژه Node.js جدید ایجاد کنیم و TypeScript را راه اندازی کنیم.
mkdir clean-architecture-api
cd clean-architecture-api
npm init -y
npm install express
npm install typescript @types/node @types/express ts-node-dev –save-dev
npx tsc –init
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
بعد، خود را پیکربندی کنید tsconfig.json:
{
“compilerOptions”: {
“target”: “ES2020”,
“module”: “commonjs”,
“strict”: true,
“esModuleInterop”: true,
“skipLibCheck”: true,
“forceConsistentCasingInFileNames”: true,
“outDir”: “./dist”
},
“include”: [“src/**/*.ts”],
“exclude”: [“node_modules”]
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
4. 🏗️ ساختار پروژه با معماری پاک
بازگشت به فهرست مطالب
یک پروژه معمولی Clean Architecture به لایه های زیر تقسیم می شود:
لایه دامنه: شامل منطق تجاری، موجودیت ها و رابط ها می باشد. این لایه مستقل از هر لایه دیگر است.
از لایه Cases استفاده کنید: شامل موارد استفاده یا قوانین تجاری برنامه است.
لایه زیرساخت: شامل پیاده سازی رابط های تعریف شده در لایه دامنه، مانند اتصالات پایگاه داده است.
لایه رابط: شامل کنترلرها، مسیرها و هر کد دیگری مربوط به چارچوب وب است.
ساختار دایرکتوری ممکن است به شکل زیر باشد:
src/
├── domain/
│ ├── entities/
│ └── interfaces/
├── use-cases/
├── infrastructure/
│ ├── database/
│ └── repositories/
└── interface/
├── controllers/
└── routes/
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
5. 📂 پیاده سازی لایه دامنه
بازگشت به فهرست مطالب
در لایه دامنه، نهادها و رابط های خود را تعریف کنید. فرض کنید در حال ساخت یک API ساده برای مدیریت کتاب هستیم.
نهاد (کتاب):
// src/domain/entities/Book.ts
export class Book {
constructor(
public readonly id: string,
public title: string,
public author: string,
public publishedDate: Date
) {}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
رابط مخزن:
// src/domain/interfaces/BookRepository.ts
import { Book } from “../entities/Book”;
export interface BookRepository {
findAll(): PromiseBook[]>;
findById(id: string): PromiseBook | null>;
create(book: Book): PromiseBook>;
update(book: Book): Promisevoid>;
delete(id: string): Promisevoid>;
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
6. 🔧 پیاده سازی موارد استفاده
بازگشت به فهرست مطالب
موارد استفاده اقداماتی را که می توان در سیستم انجام داد را مشخص می کند. آنها با لایه دامنه تعامل دارند و نسبت به چارچوب یا پایگاه داده مورد استفاده آگنوستیک هستند.
Use Case (GetAllBooks):
// src/use-cases/GetAllBooks.ts
import { BookRepository } from “../domain/interfaces/BookRepository”;
export class GetAllBooks {
constructor(private bookRepository: BookRepository) {}
async execute() {
return await this.bookRepository.findAll();
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
7. 🗂️ پیاده سازی لایه زیرساخت
بازگشت به فهرست مطالب
در لایه زیرساخت، رابط های تعریف شده در لایه دامنه را پیاده سازی کنید. اینجا جایی است که شما با پایگاه های داده یا سرویس های خارجی تعامل دارید.
مخزن درون حافظه (برای سادگی):
// src/infrastructure/repositories/InMemoryBookRepository.ts
import { Book } from “../../domain/entities/Book”;
import { BookRepository } from “../../domain/interfaces/BookRepository”;
export class InMemoryBookRepository implements BookRepository {
private books: Book[] = [];
async findAll(): PromiseBook[]> {
return this.books;
}
async findById(id: string): PromiseBook | null> {
return this.books.find(book => book.id === id) || null;
}
async create(book: Book): PromiseBook> {
this.books.push(book);
return book;
}
async update(book: Book): Promisevoid> {
const index = this.books.findIndex(b => b.id === book.id);
if (index !== -1) {
this.books[index] = book;
}
}
async delete(id: string): Promisevoid> {
this.books = this.books.filter(book => book.id !== id);
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
8. 🌐 پیاده سازی لایه رابط
بازگشت به فهرست مطالب
لایه رابط شامل کنترلکنندهها و مسیرهایی است که درخواستهای HTTP را مدیریت میکنند و آنها را برای موارد استفاده نقشهبرداری میکنند.
کنترل کننده کتاب:
// src/interface/controllers/BookController.ts
import { Request, Response } from “express”;
import { GetAllBooks } from “../../use-cases/GetAllBooks”;
export class BookController {
constructor(private getAllBooks: GetAllBooks) {}
async getAll(req: Request, res: Response) {
const books = await this.getAllBooks.execute();
res.json(books);
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
مسیرها:
// src/interface/routes/bookRoutes.ts
import { Router } from “express”;
import { InMemoryBookRepository } from “../../infrastructure/repositories/InMemoryBookRepository”;
import { GetAllBooks }
from “../../use-cases/GetAllBooks”;
import { BookController } from “../controllers/BookController”;
const router = Router();
const bookRepository = new InMemoryBookRepository();
const getAllBooks = new GetAllBooks(bookRepository);
const bookController = new BookController(getAllBooks);
router.get(“/books”, (req, res) => bookController.getAll(req, res));
export { router as bookRoutes };
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
برنامه اصلی:
// src/index.ts
import express from “express”;
import { bookRoutes } from “./interface/routes/bookRoutes”;
const app = express();
app.use(express.json());
app.use(“/api”, bookRoutes);
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
9. 🔌 تزریق وابستگی
بازگشت به فهرست مطالب
تزریق وابستگی (DI) تکنیکی است که در آن وابستگیهای یک شی به جای کدگذاری سخت در داخل شی ارائه میشوند. این امر اتصال شل را ترویج می کند و آزمایش برنامه شما را آسان تر می کند.
مثال:
بیایید یک مکانیسم DI ساده را با استفاده از TypeScript پیاده سازی کنیم.
// src/infrastructure/DIContainer.ts
import { InMemoryBookRepository } from “./repositories/InMemoryBookRepository”;
import { GetAllBooks } from “../use-cases/GetAllBooks”;
class DIContainer {
private static _bookRepository = new InMemoryBookRepository();
static getBookRepository() {
return this._bookRepository;
}
static getGetAllBooksUseCase() {
return new GetAllBooks(this.getBookRepository());
}
}
export { DIContainer };
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
از DIContainer در کنترلرهای خود استفاده کنید:
// src/interface/controllers/BookController.ts
import { Request, Response } from “express”;
import { DIContainer } from “../../infrastructure/DIContainer”;
export class BookController {
private getAllBooks = DIContainer.getGetAllBooksUseCase();
async getAll(req: Request, res: Response) {
const books = await this.getAllBooks.execute();
res.json(books);
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
10. 🚨 رسیدگی به خطا
بازگشت به فهرست مطالب
مدیریت صحیح خطا تضمین میکند که API شما میتواند موقعیتهای غیرمنتظره را به خوبی مدیریت کند و پیامهای خطای معنیداری را به مشتریان ارائه دهد.
مثال:
یک میان افزار متمرکز رسیدگی به خطا ایجاد کنید:
// src/interface/middleware/errorHandler.ts
import { Request, Response, NextFunction } from “express”;
export function errorHandler(err: any, req: Request, res: Response, next: NextFunction) {
console.error(err.stack);
res.status(500).json({ message: “Internal Server Error” });
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
از این میان افزار در برنامه اصلی خود استفاده کنید:
// src/index.ts
import express from “express”;
import { bookRoutes } from “./interface/routes/bookRoutes”;
import { errorHandler } from “./interface/middleware/errorHandler”;
const app = express();
app.use(express.json());
app.use(“/api”, bookRoutes);
app.use(errorHandler);
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
11. ✔️ اعتبار سنجی
بازگشت به فهرست مطالب
اعتبارسنجی برای اطمینان از صحت و ایمن بودن داده های وارد شده به برنامه شما بسیار مهم است.
مثال:
ادغام کنید class-validator برای تایید درخواست های دریافتی:
npm install class-validator class-transformer
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
یک DTO (Data Transfer Object) برای ایجاد کتاب ایجاد کنید:
// src/interface/dto/CreateBookDto.ts
import { IsString, IsDate } from “class-validator”;
export class CreateBookDto {
@IsString()
title!: string;
@IsString()
author!: string;
@IsDate()
publishedDate!: Date;
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
DTO را در کنترلر خود تأیید کنید:
// src/interface/controllers/BookController.ts
import { Request, Response } from “express”;
import { validate } from “class-validator”;
import { CreateBookDto } from “../dto/CreateBookDto”;
import { DIContainer } from “../../infrastructure/DIContainer”;
export class BookController {
private getAllBooks = DIContainer.getGetAllBooksUseCase();
async create(req: Request, res: Response) {
const dto = Object.assign(new CreateBookDto(), req.body);
const errors = await validate(dto);
if (errors.length > 0) {
return res.status(400).json({ errors });
}
// Proceed with the creation logic…
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
12. 💾 یکپارچه سازی پایگاه داده واقعی
بازگشت به فهرست مطالب
جابجایی از یک پایگاه داده در حافظه به یک پایگاه داده واقعی مانند MongoDB یا PostgreSQL باعث می شود برنامه شما آماده تولید باشد.
مثال:
ادغام MongoDB:
npm install mongoose @types/mongoose
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
یک مدل Mongoose برای Book:
// src/infrastructure/models/BookModel.ts
import mongoose, { Schema, Document } from “mongoose”;
interface IBook extends Document {
title: string;
author: string;
publishedDate: Date;
}
const BookSchema: Schema = new Schema({
title: { type: String, required: true },
author: { type: String, required: true },
publishedDate: { type: Date, required: true },
});
const BookModel = mongoose.modelIBook>(“Book”, BookSchema);
export { BookModel, IBook };
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
اجرای مخزن:
// src/infrastructure/repositories/MongoBookRepository.ts
import { Book } from “../../domain/entities/Book”;
import { BookRepository } from “../../domain/interfaces/BookRepository”;
import { BookModel } from “../models/BookModel”;
export class MongoBookRepository implements BookRepository {
async findAll(): PromiseBook[]> {
return await BookModel.find();
}
async findById(id: string): PromiseBook | null> {
return await BookModel.findById(id);
}
async create(book: Book): PromiseBook> {
const newBook = new BookModel(book);
await newBook.save();
return newBook;
}
async update(book: Book): Promisevoid> {
await BookModel.findByIdAndUpdate(book.id, book);
}
async delete(id: string): Promisevoid> {
await BookModel.findByIdAndDelete(id);
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
DIContainer را برای استفاده از MongoBookRepository به روز کنید:
// src/infrastructure/DIContainer.ts
import { MongoBookRepository } from “./repositories/MongoBookRepository”;
import { GetAllBooks } from “../use-cases/GetAllBooks”;
class DIContainer {
private static _bookRepository = new MongoBookRepository();
static getBookRepository() {
return this._bookRepository;
}
static getGetAllBooksUseCase() {
return new GetAllBooks(this.getBookRepository());
}
}
export { DIContainer };
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
13. 🔒 احراز هویت و مجوز
بازگشت به فهرست مطالب
ایمن سازی API ضروری است. JWT (JSON Web Tokens) یک رویکرد رایج برای احراز هویت بدون حالت است.
مثال:
JWT را برای احراز هویت ادغام کنید:
npm install jsonwebtoken @types/jsonwebtoken
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
ایجاد یک میان افزار احراز هویت:
// src/interface/middleware/auth.ts
import jwt from “jsonwebtoken”;
import { Request, Response, NextFunction } from “express”;
export function authenticateToken(req: Request, res: Response, next: NextFunction) {
const token = req.header(“Authorization”)?.split(” “)[1];
if (!token) return res.sendStatus(401);
jwt.verify(token, process.env.JWT_SECRET as string, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
از این میان افزار برای محافظت از مسیرها استفاده کنید:
// src/interface/routes/bookRoutes.ts
import { Router } from “express”;
import { BookController } from “../controllers/BookController”;
import { authenticateToken } from “../middleware/auth”;
const router = Router();
router.get(“/books”, authenticateToken, (req, res) => bookController.getAll(req, res));
export { router as bookRoutes };
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
14. 📝 ثبت و نظارت
بازگشت به فهرست مطالب
ورود به سیستم برای اشکال زدایی و نظارت بر برنامه شما در تولید بسیار مهم است.
مثال:
ادغام کنید winston برای ورود به سیستم:
npm install winston
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
ایجاد یک لاگر:
// src/infrastructure/logger.ts
import { createLogger, transports, format } from “winston”;
const logger = createLogger({
level: “info”,
format: format.combine(format.timestamp(), format.json()),
transports: [new transports.Console()],
});
export { logger };
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
از لاگر در برنامه خود استفاده کنید:
// src/index.ts
import express from “express”;
import { bookRoutes } from “./interface/routes/bookRoutes”;
import { errorHandler } from “./interface/middleware/errorHandler”;
import { logger } from “./infrastructure/logger”;
const app = express();
app.use(express.json());
app.use(“/api”, bookRoutes);
app.use(errorHandler);
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
logger.info(`Server is running on port ${PORT}`);
});
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
15. ⚙️ پیکربندی محیط
بازگشت به فهرست مطالب
مدیریت محیط های مختلف برای اطمینان از اجرای صحیح برنامه شما در توسعه، آزمایش و تولید بسیار مهم است.
مثال:
استفاده از `
dotenv` برای پیکربندی محیط:
npm install dotenv
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
ایجاد یک .env فایل:
PORT=3000
JWT_SECRET=your_jwt_secret
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
بارگذاری متغیرهای محیطی در برنامه شما:
// src/index.ts
import express from “express”;
import dotenv from “dotenv”;
dotenv.config();
import { bookRoutes } from “./interface/routes/bookRoutes”;
import { errorHandler } from “./interface/middleware/errorHandler”;
import { logger } from “./infrastructure/logger”;
const app = express();
app.use(express.json());
app.use(“/api”, bookRoutes);
app.use(errorHandler);
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
logger.info(`Server is running on port ${PORT}`);
});
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
16. 🚀 CI/CD و استقرار
بازگشت به فهرست مطالب
خودکارسازی آزمایش، ساخت و استقرار API شما ثبات و قابلیت اطمینان را تضمین می کند.
مثال:
راه اندازی GitHub Actions برای CI/CD:
ایجاد یک .github/workflows/ci.yml فایل:
name: Node.js CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x, 16.x]
steps:
– uses: actions/checkout@v2
– name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
– run: npm install
– run: npm test
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
17. 🧹 کیفیت و لینتینگ کد
بازگشت به فهرست مطالب
حفظ کیفیت کد یکنواخت در محیط های مشارکتی بسیار مهم است.
مثال:
ESLint و Prettier را ادغام کنید:
npm install eslint prettier eslint-config-prettier eslint-plugin-prettier –save-dev
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
یک پیکربندی ESLint ایجاد کنید:
// .eslintrc.json
{
“env”: {
“node”: true,
“es6”: true
},
“extends”: [“eslint:recommended”, “plugin:@typescript-eslint/recommended”, “prettier”],
“plugins”: [“@typescript-eslint”, “prettier”],
“parser”: “@typescript-eslint/parser”,
“rules”: {
“prettier/prettier”: “error”
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
افزودن پیکربندی زیباتر:
// .prettierrc
{
“singleQuote”: true,
“trailingComma”: “all”,
“printWidth”: 80
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
18. 🛠️ مستندات پروژه
بازگشت به فهرست مطالب
مستندسازی API شما هم برای توسعه دهندگان و هم برای کاربران نهایی بسیار مهم است.
مثال:
مستندات API را با Swagger ایجاد کنید:
npm install swagger-jsdoc swagger-ui-express
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
ایجاد مستندات Swagger:
// src/interface/swagger.ts
import swaggerJSDoc from “swagger-jsdoc”;
import swaggerUi from “swagger-ui-express”;
import { Express } from “express”;
const options = {
definition: {
openapi: “3.0.0”,
info: {
title: “Clean Architecture API”,
version: “1.0.0”,
},
},
apis: [“./src/interface/routes/*.ts”],
};
const swaggerSpec = swaggerJSDoc(options);
function setupSwagger(app: Express) {
app.use(“/api-docs”, swaggerUi.serve, swaggerUi.setup(swaggerSpec));
}
export { setupSwagger };
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
Swagger را در برنامه اصلی خود راه اندازی کنید:
// src/index.ts
import express from “express”;
import dotenv from “dotenv”;
dotenv.config();
import { bookRoutes } from “./interface/routes/bookRoutes”;
import { errorHandler } from “./interface/middleware/errorHandler”;
import { logger } from “./infrastructure/logger”;
import { setupSwagger } from “./interface/swagger”;
const app = express();
app.use(express.json());
app.use(“/api”, bookRoutes);
app.use(errorHandler);
setupSwagger(app);
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
logger.info(`Server is running on port ${PORT}`);
});
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
19. 🏁 نتیجه گیری
بازگشت به فهرست مطالب
در این وبلاگ، نحوه ساخت یک API مدرن با استفاده از Node.js، Express و TypeScript را با رعایت اصول Clean Architecture بررسی کردیم. ما پیادهسازی اولیه را با افزودن ویژگیهای کلیدی مانند تزریق وابستگی، مدیریت خطا، اعتبارسنجی، یکپارچهسازی پایگاه داده واقعی، احراز هویت و مجوز، ثبت و نظارت، پیکربندی محیط، CI/CD، کیفیت کد و پر کردن و مستندات پروژه گسترش دادیم.
با پیروی از این شیوهها، مطمئن خواهید شد که API شما نه تنها کاربردی است، بلکه قابل نگهداری، مقیاسپذیر و آماده برای تولید است. همانطور که به توسعه ادامه می دهید، با خیال راحت الگوها و ابزارهای اضافی را برای بهبود بیشتر برنامه خود کشف کنید.
سفر جاوا اسکریپت خود را شروع کنید
اگر با جاوا اسکریپت تازه کار هستید یا می خواهید یک تازه کننده داشته باشید، از وبلاگ من در BuyMeACoffee دیدن کنید تا با اصول اولیه شروع کنید.
👉 مقدمه ای بر جاوا اسکریپت: اولین قدم های شما در کدنویسی
فهرست سری
قسمت
عنوان
پیوند
1
گذرواژهها را حذف کنید: با FACEIO قابلیت تشخیص چهره را به وبسایت خود اضافه کنید
بخوانید
2
چیت چیت نهایی Git Command
بخوانید
3
12 منبع برتر جاوا اسکریپت برای یادگیری و تسلط
بخوانید
4
Angular vs. React: مقایسه ای جامع
بخوانید
5
10 روش برتر جاوا اسکریپت برای نوشتن کد پاک
بخوانید
6
20 ترفند و نکته برتر جاوا اسکریپت برای هر توسعه دهنده 🚀
بخوانید
7
8 مفهوم جدید و هیجان انگیز جاوا اسکریپت که باید بدانید
بخوانید
8
7 نکته برتر برای مدیریت وضعیت در برنامه های جاوا اسکریپت
بخوانید
9
🔒 بهترین روش های امنیتی Essential Node.js
بخوانید
10
10 بهترین روش برای بهینه سازی عملکرد زاویه ای
بخوانید
11
10 تکنیک برتر بهینه سازی عملکرد React
بخوانید
12
15 پروژه برتر جاوا اسکریپت برای تقویت نمونه کارها
بخوانید
13
6 مخزن برای Master Node.js
بخوانید
14
بهترین 6 مخزن برای استاد Next.js
بخوانید
15
5 کتابخانه برتر جاوا اسکریپت برای ایجاد رابط کاربری تعاملی
بخوانید
16
3 مفهوم برتر جاوا اسکریپت که هر توسعه دهنده ای باید بداند
بخوانید
17
20 روش برای بهبود عملکرد Node.js در مقیاس
بخوانید
18
عملکرد برنامه Node.js خود را با فشرده سازی میان افزار افزایش دهید
بخوانید
19
درک الگوریتم دایکسترا: راهنمای گام به گام
بخوانید
20
آشنایی با NPM و NVM: ابزارهای ضروری برای توسعه Node.js
بخوانید
فالو کنید و مشترک شوید:
API ها ستون فقرات برنامه های کاربردی وب مدرن هستند. با افزایش پیچیدگی برنامهها، اتخاذ معماری که مقیاسپذیری، قابلیت نگهداری و آزمایشپذیری را ارتقا میدهد، بسیار مهم است. در این وبلاگ، نحوه ساخت یک API مدرن با استفاده از Node.js، Express، و TypeScript را با رعایت اصول Clean Architecture بررسی خواهیم کرد.
لطفا برای حمایت از کانال من و دریافت آموزش های بیشتر توسعه وب، در کانال یوتیوب من مشترک شوید.
📑 فهرست مطالب
1. 🧩 مقدمه ای بر معماری پاک
بازگشت به فهرست مطالب
معماری پاک، معرفی شده توسط رابرت سی مارتین (عمو باب)، بر جداسازی نگرانی ها در یک برنامه تاکید دارد. این ایده را ترویج می کند که منطق تجاری باید مستقل از هر چارچوب، پایگاه داده یا سیستم خارجی باشد. این باعث میشود برنامه ماژولارتر، آزمایش آسانتر و سازگار با تغییرات باشد.
اصول کلیدی معماری پاک:
- استقلال: منطق اصلی کسب و کار نباید به کتابخانه های خارجی، UI، پایگاه های داده یا چارچوب ها بستگی داشته باشد.
- آزمایش پذیری: آزمایش برنامه باید بدون اتکا به سیستم های خارجی آسان باشد.
- انعطاف پذیری: تغییر یا جایگزینی بخش هایی از برنامه باید آسان باشد بدون اینکه روی دیگران تأثیر بگذارد.
2. 💡 چرا Node.js، Express و TypeScript؟
بازگشت به فهرست مطالب
Node.js
Node.js یک زمان اجرا قدرتمند جاوا اسکریپت است که به شما امکان می دهد برنامه های شبکه مقیاس پذیر بسازید. غیر مسدود کننده و رویداد محور است و برای ساخت APIهایی که تعداد زیادی درخواست را مدیریت می کنند ایده آل است.
اکسپرس
Express یک چارچوب وب مینیمالیستی برای Node.js است. مجموعه ای قوی از ویژگی ها را برای ساخت برنامه های کاربردی وب و موبایل و API ارائه می دهد. سادگی آن شروع را آسان می کند و بسیار توسعه پذیر است.
TypeScript
TypeScript ابر مجموعه ای از جاوا اسکریپت است که انواع استاتیک را اضافه می کند. استفاده از TypeScript در برنامه Node.js به شناسایی خطاها در مراحل اولیه توسعه، بهبود خوانایی کد و افزایش تجربه کلی توسعه دهنده کمک می کند.
3. 🚧 راه اندازی پروژه
بازگشت به فهرست مطالب
ابتدا بیایید یک پروژه Node.js جدید ایجاد کنیم و TypeScript را راه اندازی کنیم.
mkdir clean-architecture-api
cd clean-architecture-api
npm init -y
npm install express
npm install typescript @types/node @types/express ts-node-dev --save-dev
npx tsc --init
بعد، خود را پیکربندی کنید tsconfig.json
:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist"
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}
4. 🏗️ ساختار پروژه با معماری پاک
بازگشت به فهرست مطالب
یک پروژه معمولی Clean Architecture به لایه های زیر تقسیم می شود:
- لایه دامنه: شامل منطق تجاری، موجودیت ها و رابط ها می باشد. این لایه مستقل از هر لایه دیگر است.
- از لایه Cases استفاده کنید: شامل موارد استفاده یا قوانین تجاری برنامه است.
- لایه زیرساخت: شامل پیاده سازی رابط های تعریف شده در لایه دامنه، مانند اتصالات پایگاه داده است.
- لایه رابط: شامل کنترلرها، مسیرها و هر کد دیگری مربوط به چارچوب وب است.
ساختار دایرکتوری ممکن است به شکل زیر باشد:
src/
├── domain/
│ ├── entities/
│ └── interfaces/
├── use-cases/
├── infrastructure/
│ ├── database/
│ └── repositories/
└── interface/
├── controllers/
└── routes/
5. 📂 پیاده سازی لایه دامنه
بازگشت به فهرست مطالب
در لایه دامنه، نهادها و رابط های خود را تعریف کنید. فرض کنید در حال ساخت یک API ساده برای مدیریت کتاب هستیم.
نهاد (کتاب):
// src/domain/entities/Book.ts
export class Book {
constructor(
public readonly id: string,
public title: string,
public author: string,
public publishedDate: Date
) {}
}
رابط مخزن:
// src/domain/interfaces/BookRepository.ts
import { Book } from "../entities/Book";
export interface BookRepository {
findAll(): PromiseBook[]>;
findById(id: string): PromiseBook | null>;
create(book: Book): PromiseBook>;
update(book: Book): Promisevoid>;
delete(id: string): Promisevoid>;
}
6. 🔧 پیاده سازی موارد استفاده
بازگشت به فهرست مطالب
موارد استفاده اقداماتی را که می توان در سیستم انجام داد را مشخص می کند. آنها با لایه دامنه تعامل دارند و نسبت به چارچوب یا پایگاه داده مورد استفاده آگنوستیک هستند.
Use Case (GetAllBooks):
// src/use-cases/GetAllBooks.ts
import { BookRepository } from "../domain/interfaces/BookRepository";
export class GetAllBooks {
constructor(private bookRepository: BookRepository) {}
async execute() {
return await this.bookRepository.findAll();
}
}
7. 🗂️ پیاده سازی لایه زیرساخت
بازگشت به فهرست مطالب
در لایه زیرساخت، رابط های تعریف شده در لایه دامنه را پیاده سازی کنید. اینجا جایی است که شما با پایگاه های داده یا سرویس های خارجی تعامل دارید.
مخزن درون حافظه (برای سادگی):
// src/infrastructure/repositories/InMemoryBookRepository.ts
import { Book } from "../../domain/entities/Book";
import { BookRepository } from "../../domain/interfaces/BookRepository";
export class InMemoryBookRepository implements BookRepository {
private books: Book[] = [];
async findAll(): PromiseBook[]> {
return this.books;
}
async findById(id: string): PromiseBook | null> {
return this.books.find(book => book.id === id) || null;
}
async create(book: Book): PromiseBook> {
this.books.push(book);
return book;
}
async update(book: Book): Promisevoid> {
const index = this.books.findIndex(b => b.id === book.id);
if (index !== -1) {
this.books[index] = book;
}
}
async delete(id: string): Promisevoid> {
this.books = this.books.filter(book => book.id !== id);
}
}
8. 🌐 پیاده سازی لایه رابط
بازگشت به فهرست مطالب
لایه رابط شامل کنترلکنندهها و مسیرهایی است که درخواستهای HTTP را مدیریت میکنند و آنها را برای موارد استفاده نقشهبرداری میکنند.
کنترل کننده کتاب:
// src/interface/controllers/BookController.ts
import { Request, Response } from "express";
import { GetAllBooks } from "../../use-cases/GetAllBooks";
export class BookController {
constructor(private getAllBooks: GetAllBooks) {}
async getAll(req: Request, res: Response) {
const books = await this.getAllBooks.execute();
res.json(books);
}
}
مسیرها:
// src/interface/routes/bookRoutes.ts
import { Router } from "express";
import { InMemoryBookRepository } from "../../infrastructure/repositories/InMemoryBookRepository";
import { GetAllBooks }
from "../../use-cases/GetAllBooks";
import { BookController } from "../controllers/BookController";
const router = Router();
const bookRepository = new InMemoryBookRepository();
const getAllBooks = new GetAllBooks(bookRepository);
const bookController = new BookController(getAllBooks);
router.get("/books", (req, res) => bookController.getAll(req, res));
export { router as bookRoutes };
برنامه اصلی:
// src/index.ts
import express from "express";
import { bookRoutes } from "./interface/routes/bookRoutes";
const app = express();
app.use(express.json());
app.use("/api", bookRoutes);
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
9. 🔌 تزریق وابستگی
بازگشت به فهرست مطالب
تزریق وابستگی (DI) تکنیکی است که در آن وابستگیهای یک شی به جای کدگذاری سخت در داخل شی ارائه میشوند. این امر اتصال شل را ترویج می کند و آزمایش برنامه شما را آسان تر می کند.
مثال:
بیایید یک مکانیسم DI ساده را با استفاده از TypeScript پیاده سازی کنیم.
// src/infrastructure/DIContainer.ts
import { InMemoryBookRepository } from "./repositories/InMemoryBookRepository";
import { GetAllBooks } from "../use-cases/GetAllBooks";
class DIContainer {
private static _bookRepository = new InMemoryBookRepository();
static getBookRepository() {
return this._bookRepository;
}
static getGetAllBooksUseCase() {
return new GetAllBooks(this.getBookRepository());
}
}
export { DIContainer };
از DIContainer در کنترلرهای خود استفاده کنید:
// src/interface/controllers/BookController.ts
import { Request, Response } from "express";
import { DIContainer } from "../../infrastructure/DIContainer";
export class BookController {
private getAllBooks = DIContainer.getGetAllBooksUseCase();
async getAll(req: Request, res: Response) {
const books = await this.getAllBooks.execute();
res.json(books);
}
}
10. 🚨 رسیدگی به خطا
بازگشت به فهرست مطالب
مدیریت صحیح خطا تضمین میکند که API شما میتواند موقعیتهای غیرمنتظره را به خوبی مدیریت کند و پیامهای خطای معنیداری را به مشتریان ارائه دهد.
مثال:
یک میان افزار متمرکز رسیدگی به خطا ایجاد کنید:
// src/interface/middleware/errorHandler.ts
import { Request, Response, NextFunction } from "express";
export function errorHandler(err: any, req: Request, res: Response, next: NextFunction) {
console.error(err.stack);
res.status(500).json({ message: "Internal Server Error" });
}
از این میان افزار در برنامه اصلی خود استفاده کنید:
// src/index.ts
import express from "express";
import { bookRoutes } from "./interface/routes/bookRoutes";
import { errorHandler } from "./interface/middleware/errorHandler";
const app = express();
app.use(express.json());
app.use("/api", bookRoutes);
app.use(errorHandler);
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
11. ✔️ اعتبار سنجی
بازگشت به فهرست مطالب
اعتبارسنجی برای اطمینان از صحت و ایمن بودن داده های وارد شده به برنامه شما بسیار مهم است.
مثال:
ادغام کنید class-validator
برای تایید درخواست های دریافتی:
npm install class-validator class-transformer
یک DTO (Data Transfer Object) برای ایجاد کتاب ایجاد کنید:
// src/interface/dto/CreateBookDto.ts
import { IsString, IsDate } from "class-validator";
export class CreateBookDto {
@IsString()
title!: string;
@IsString()
author!: string;
@IsDate()
publishedDate!: Date;
}
DTO را در کنترلر خود تأیید کنید:
// src/interface/controllers/BookController.ts
import { Request, Response } from "express";
import { validate } from "class-validator";
import { CreateBookDto } from "../dto/CreateBookDto";
import { DIContainer } from "../../infrastructure/DIContainer";
export class BookController {
private getAllBooks = DIContainer.getGetAllBooksUseCase();
async create(req: Request, res: Response) {
const dto = Object.assign(new CreateBookDto(), req.body);
const errors = await validate(dto);
if (errors.length > 0) {
return res.status(400).json({ errors });
}
// Proceed with the creation logic...
}
}
12. 💾 یکپارچه سازی پایگاه داده واقعی
بازگشت به فهرست مطالب
جابجایی از یک پایگاه داده در حافظه به یک پایگاه داده واقعی مانند MongoDB یا PostgreSQL باعث می شود برنامه شما آماده تولید باشد.
مثال:
ادغام MongoDB:
npm install mongoose @types/mongoose
یک مدل Mongoose برای Book
:
// src/infrastructure/models/BookModel.ts
import mongoose, { Schema, Document } from "mongoose";
interface IBook extends Document {
title: string;
author: string;
publishedDate: Date;
}
const BookSchema: Schema = new Schema({
title: { type: String, required: true },
author: { type: String, required: true },
publishedDate: { type: Date, required: true },
});
const BookModel = mongoose.modelIBook>("Book", BookSchema);
export { BookModel, IBook };
اجرای مخزن:
// src/infrastructure/repositories/MongoBookRepository.ts
import { Book } from "../../domain/entities/Book";
import { BookRepository } from "../../domain/interfaces/BookRepository";
import { BookModel } from "../models/BookModel";
export class MongoBookRepository implements BookRepository {
async findAll(): PromiseBook[]> {
return await BookModel.find();
}
async findById(id: string): PromiseBook | null> {
return await BookModel.findById(id);
}
async create(book: Book): PromiseBook> {
const newBook = new BookModel(book);
await newBook.save();
return newBook;
}
async update(book: Book): Promisevoid> {
await BookModel.findByIdAndUpdate(book.id, book);
}
async delete(id: string): Promisevoid> {
await BookModel.findByIdAndDelete(id);
}
}
DIContainer را برای استفاده از MongoBookRepository به روز کنید:
// src/infrastructure/DIContainer.ts
import { MongoBookRepository } from "./repositories/MongoBookRepository";
import { GetAllBooks } from "../use-cases/GetAllBooks";
class DIContainer {
private static _bookRepository = new MongoBookRepository();
static getBookRepository() {
return this._bookRepository;
}
static getGetAllBooksUseCase() {
return new GetAllBooks(this.getBookRepository());
}
}
export { DIContainer };
13. 🔒 احراز هویت و مجوز
بازگشت به فهرست مطالب
ایمن سازی API ضروری است. JWT (JSON Web Tokens) یک رویکرد رایج برای احراز هویت بدون حالت است.
مثال:
JWT را برای احراز هویت ادغام کنید:
npm install jsonwebtoken @types/jsonwebtoken
ایجاد یک میان افزار احراز هویت:
// src/interface/middleware/auth.ts
import jwt from "jsonwebtoken";
import { Request, Response, NextFunction } from "express";
export function authenticateToken(req: Request, res: Response, next: NextFunction) {
const token = req.header("Authorization")?.split(" ")[1];
if (!token) return res.sendStatus(401);
jwt.verify(token, process.env.JWT_SECRET as string, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
}
از این میان افزار برای محافظت از مسیرها استفاده کنید:
// src/interface/routes/bookRoutes.ts
import { Router } from "express";
import { BookController } from "../controllers/BookController";
import { authenticateToken } from "../middleware/auth";
const router = Router();
router.get("/books", authenticateToken, (req, res) => bookController.getAll(req, res));
export { router as bookRoutes };
14. 📝 ثبت و نظارت
بازگشت به فهرست مطالب
ورود به سیستم برای اشکال زدایی و نظارت بر برنامه شما در تولید بسیار مهم است.
مثال:
ادغام کنید winston
برای ورود به سیستم:
npm install winston
ایجاد یک لاگر:
// src/infrastructure/logger.ts
import { createLogger, transports, format } from "winston";
const logger = createLogger({
level: "info",
format: format.combine(format.timestamp(), format.json()),
transports: [new transports.Console()],
});
export { logger };
از لاگر در برنامه خود استفاده کنید:
// src/index.ts
import express from "express";
import { bookRoutes } from "./interface/routes/bookRoutes";
import { errorHandler } from "./interface/middleware/errorHandler";
import { logger } from "./infrastructure/logger";
const app = express();
app.use(express.json());
app.use("/api", bookRoutes);
app.use(errorHandler);
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
logger.info(`Server is running on port ${PORT}`);
});
15. ⚙️ پیکربندی محیط
بازگشت به فهرست مطالب
مدیریت محیط های مختلف برای اطمینان از اجرای صحیح برنامه شما در توسعه، آزمایش و تولید بسیار مهم است.
مثال:
استفاده از `
dotenv` برای پیکربندی محیط:
npm install dotenv
ایجاد یک .env
فایل:
PORT=3000
JWT_SECRET=your_jwt_secret
بارگذاری متغیرهای محیطی در برنامه شما:
// src/index.ts
import express from "express";
import dotenv from "dotenv";
dotenv.config();
import { bookRoutes } from "./interface/routes/bookRoutes";
import { errorHandler } from "./interface/middleware/errorHandler";
import { logger } from "./infrastructure/logger";
const app = express();
app.use(express.json());
app.use("/api", bookRoutes);
app.use(errorHandler);
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
logger.info(`Server is running on port ${PORT}`);
});
16. 🚀 CI/CD و استقرار
بازگشت به فهرست مطالب
خودکارسازی آزمایش، ساخت و استقرار API شما ثبات و قابلیت اطمینان را تضمین می کند.
مثال:
راه اندازی GitHub Actions برای CI/CD:
ایجاد یک .github/workflows/ci.yml
فایل:
name: Node.js CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x, 16.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test
17. 🧹 کیفیت و لینتینگ کد
بازگشت به فهرست مطالب
حفظ کیفیت کد یکنواخت در محیط های مشارکتی بسیار مهم است.
مثال:
ESLint و Prettier را ادغام کنید:
npm install eslint prettier eslint-config-prettier eslint-plugin-prettier --save-dev
یک پیکربندی ESLint ایجاد کنید:
// .eslintrc.json
{
"env": {
"node": true,
"es6": true
},
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
"plugins": ["@typescript-eslint", "prettier"],
"parser": "@typescript-eslint/parser",
"rules": {
"prettier/prettier": "error"
}
}
افزودن پیکربندی زیباتر:
// .prettierrc
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 80
}
18. 🛠️ مستندات پروژه
بازگشت به فهرست مطالب
مستندسازی API شما هم برای توسعه دهندگان و هم برای کاربران نهایی بسیار مهم است.
مثال:
مستندات API را با Swagger ایجاد کنید:
npm install swagger-jsdoc swagger-ui-express
ایجاد مستندات Swagger:
// src/interface/swagger.ts
import swaggerJSDoc from "swagger-jsdoc";
import swaggerUi from "swagger-ui-express";
import { Express } from "express";
const options = {
definition: {
openapi: "3.0.0",
info: {
title: "Clean Architecture API",
version: "1.0.0",
},
},
apis: ["./src/interface/routes/*.ts"],
};
const swaggerSpec = swaggerJSDoc(options);
function setupSwagger(app: Express) {
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerSpec));
}
export { setupSwagger };
Swagger را در برنامه اصلی خود راه اندازی کنید:
// src/index.ts
import express from "express";
import dotenv from "dotenv";
dotenv.config();
import { bookRoutes } from "./interface/routes/bookRoutes";
import { errorHandler } from "./interface/middleware/errorHandler";
import { logger } from "./infrastructure/logger";
import { setupSwagger } from "./interface/swagger";
const app = express();
app.use(express.json());
app.use("/api", bookRoutes);
app.use(errorHandler);
setupSwagger(app);
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
logger.info(`Server is running on port ${PORT}`);
});
19. 🏁 نتیجه گیری
بازگشت به فهرست مطالب
در این وبلاگ، نحوه ساخت یک API مدرن با استفاده از Node.js، Express و TypeScript را با رعایت اصول Clean Architecture بررسی کردیم. ما پیادهسازی اولیه را با افزودن ویژگیهای کلیدی مانند تزریق وابستگی، مدیریت خطا، اعتبارسنجی، یکپارچهسازی پایگاه داده واقعی، احراز هویت و مجوز، ثبت و نظارت، پیکربندی محیط، CI/CD، کیفیت کد و پر کردن و مستندات پروژه گسترش دادیم.
با پیروی از این شیوهها، مطمئن خواهید شد که API شما نه تنها کاربردی است، بلکه قابل نگهداری، مقیاسپذیر و آماده برای تولید است. همانطور که به توسعه ادامه می دهید، با خیال راحت الگوها و ابزارهای اضافی را برای بهبود بیشتر برنامه خود کشف کنید.
سفر جاوا اسکریپت خود را شروع کنید
اگر با جاوا اسکریپت تازه کار هستید یا می خواهید یک تازه کننده داشته باشید، از وبلاگ من در BuyMeACoffee دیدن کنید تا با اصول اولیه شروع کنید.
👉 مقدمه ای بر جاوا اسکریپت: اولین قدم های شما در کدنویسی
فهرست سری
قسمت | عنوان | پیوند |
---|---|---|
1 | گذرواژهها را حذف کنید: با FACEIO قابلیت تشخیص چهره را به وبسایت خود اضافه کنید | بخوانید |
2 | چیت چیت نهایی Git Command | بخوانید |
3 | 12 منبع برتر جاوا اسکریپت برای یادگیری و تسلط | بخوانید |
4 | Angular vs. React: مقایسه ای جامع | بخوانید |
5 | 10 روش برتر جاوا اسکریپت برای نوشتن کد پاک | بخوانید |
6 | 20 ترفند و نکته برتر جاوا اسکریپت برای هر توسعه دهنده 🚀 | بخوانید |
7 | 8 مفهوم جدید و هیجان انگیز جاوا اسکریپت که باید بدانید | بخوانید |
8 | 7 نکته برتر برای مدیریت وضعیت در برنامه های جاوا اسکریپت | بخوانید |
9 | 🔒 بهترین روش های امنیتی Essential Node.js | بخوانید |
10 | 10 بهترین روش برای بهینه سازی عملکرد زاویه ای | بخوانید |
11 | 10 تکنیک برتر بهینه سازی عملکرد React | بخوانید |
12 | 15 پروژه برتر جاوا اسکریپت برای تقویت نمونه کارها | بخوانید |
13 | 6 مخزن برای Master Node.js | بخوانید |
14 | بهترین 6 مخزن برای استاد Next.js | بخوانید |
15 | 5 کتابخانه برتر جاوا اسکریپت برای ایجاد رابط کاربری تعاملی | بخوانید |
16 | 3 مفهوم برتر جاوا اسکریپت که هر توسعه دهنده ای باید بداند | بخوانید |
17 | 20 روش برای بهبود عملکرد Node.js در مقیاس | بخوانید |
18 | عملکرد برنامه Node.js خود را با فشرده سازی میان افزار افزایش دهید | بخوانید |
19 | درک الگوریتم دایکسترا: راهنمای گام به گام | بخوانید |
20 | آشنایی با NPM و NVM: ابزارهای ضروری برای توسعه Node.js | بخوانید |
فالو کنید و مشترک شوید: