مستودع أحادي مع TypeScript: تنظيم الكود عمليًا

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

المستودع الأحادي مع TypeScript: تنظيم الكود عمليًا

\n\n

في تطوير الويب الحديث، خاصة عند العمل مع TypeScript، غالبًا ما يواجه المطورون معضلة: تخزين كل الكود في مستودع واحد (مستودع أحادي) أو تقسيمه إلى العديد من المستودعات الصغيرة (مستودعات متعددة). بالنسبة للمشاريع المتوسطة والكبيرة، حيث تكون إعادة استخدام الكود والتكوين الموحد أمرًا مهمًا، يصبح المستودع الأحادي هو المعيار الفعلي. في هذه المقالة، سنشرح كيفية تنظيم مستودع أحادي باستخدام TypeScript بشكل صحيح، بدءًا من الهيكل الأساسي وصولاً إلى التقنيات المتقدمة.

\n\n

ما هو المستودع الأحادي ولماذا هو مطلوب؟

\n\n

المستودع الأحادي هو نهج يتم فيه تخزين كود عدة مشاريع (حزم، مكتبات، تطبيقات) في مستودع واحد. في سياق TypeScript، هذا مناسب بشكل خاص، لأنه يسمح بـ:

\n\n
    \n
  • إعادة استخدام الأنواع والواجهات بين أجزاء مختلفة من النظام دون نشرها في npm.
  • \n
  • تبسيط إعادة الهيكلة: يتم التحقق من صحة التغيير في حزمة واحدة تلقائيًا في جميع الحزم التابعة.
  • \n
  • الحصول على تكوين موحد للمدقق اللغوي (linter)، والمنسق (formatter)، وأداة البناء (bundler).
  • \n
  • تبسيط CI/CD: مستودع واحد يعني مسار عمل واحد (pipeline).
  • \n
\n\n

من بين الأدوات الشائعة للعمل مع المستودعات الأحادية في TypeScript، تبرز Nx وTurborepo ومساحات عمل npm/yarn/pnpm. سننظر في نهج استخدام مساحات عمل pnpm ومراجع مشاريع TypeScript، لأنها مجموعة بسيطة ومرنة.

\n\n

هيكل المستودع الأحادي: الإعداد الأساسي

\n\n

لنقم بإنشاء هيكل نموذجي لمستودع أحادي لمشروع TypeScript. لنفترض أن لدينا ثلاث حزم: core (الأنواع والأدوات المساعدة المشتركة)، server (الخلفية)، وweb (الواجهة الأمامية).

\n\n

1. التكوين الجذري

\n\n

لنبدأ من جذر المشروع. لننشئ ملف package.json مع مساحة العمل:

\n\n
{\n  "name": "my-monorepo",\n  "private": true,\n  "workspaces": [\n    "packages/*"\n  ],\n  "scripts": {\n    "build": "tsc -b",\n    "clean": "tsc -b --clean",\n    "lint": "eslint packages/*/src"\n  }\n}\n
\n\n

ثم لنقم بإعداد tsconfig.json الجذري. سنستخدم مراجع المشاريع (Project References) - وهي ميزة رئيسية في TypeScript للمستودعات الأحادية:

\n\n
{\n  "compilerOptions": {\n    "target": "ES2020",\n    "module": "commonjs",\n    "strict": true,\n    "composite": true,\n    "declaration": true,\n    "declarationMap": true,\n    "sourceMap": true,\n    "outDir": "./dist",\n    "rootDir": ".",\n    "skipLibCheck": true\n  },\n  "references": [\n    { "path": "./packages/core" },\n    { "path": "./packages/server" },\n    { "path": "./packages/web" }\n  ]\n}\n
\n\n

هام: الخيار composite: true إلزامي للحزم التي تشير إليها حزم أخرى. فهو يمكّن البناء التزايدي (incremental build) وتوليد ملفات .d.ts.

\n\n

2. إعداد حزمة core

\n\n

لننتقل إلى packages/core. لننشئ package.json:

\n\n
{\n  "name": "@my/core",\n  "version": "1.0.0",\n  "main": "dist/index.js",\n  "types": "dist/index.d.ts",\n  "scripts": {\n    "build": "tsc -b"\n  }\n}\n
\n\n

و tsconfig.json لهذه الحزمة:

\n\n
{\n  "extends": "../../tsconfig.json",\n  "compilerOptions": {\n    "outDir": "./dist",\n    "rootDir": "./src"\n  },\n  "include": ["src"]\n}\n
\n\n

لننشئ وحدة بسيطة src/index.ts:

\n\n
export interface User {\n  id: string;\n  name: string;\n  email: string;\n}\n\nexport function greet(user: User): string {\n  return `Hello, ${user.name}!`;\n}\n
\n\n

الآن الحزمة

المدونات

توصيات الكتب