🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

كيفية إعداد Turborepo Monorepo في عام 2026: الدليل الكامل مع Next.js والحزم

⏱️3 min read  ·  575 words

يعد Turborepo هو المعيار الخاص بـ JavaScript/TypeScript monorepos في عام 2026 – يؤدي إنشاء التخزين المؤقت وحده إلى خفض وقت CI بنسبة 70-90% على قواعد التعليمات البرمجية الكبيرة. يقوم هذا الدليل بإعداد monorepo جاهز للإنتاج مع تطبيقين Next.js وحزم مشتركة من البداية.

ما نبنيه

my-monorepo/
├── apps/
│   ├── web/          # Next.js marketing site
│   └── docs/         # Next.js documentation site
├── packages/
│   ├── ui/           # Shared React components
│   ├── utils/        # Shared utilities
│   └── tsconfig/     # Shared TypeScript configs
├── turbo.json        # Turborepo configuration
└── package.json      # Workspace root

الخطوة 1: التهيئة باستخدام Turborepo

# Create from official template
npx create-turbo@latest my-monorepo
cd my-monorepo

# Or manual setup
mkdir my-monorepo && cd my-monorepo
pnpm init
# pnpm is recommended for monorepos — faster, better disk usage

الخطوة 2: جذر package.json

{
  "name": "my-monorepo",
  "private": true,
  "scripts": {
    "build":   "turbo build",
    "dev":     "turbo dev",
    "lint":    "turbo lint",
    "test":    "turbo test",
    "format":  "prettier --write "**/*.{ts,tsx,md}""
  },
  "devDependencies": {
    "turbo":     "^2.0.0",
    "prettier":  "^3.0.0",
    "typescript": "^5.0.0"
  },
  "packageManager": "pnpm@9.0.0"
}

الخطوة 3: تكوين مساحة عمل pnpm

# pnpm-workspace.yaml
packages:
  - "apps/*"
  - "packages/*"

الخطوة 4: Turbo.json – تكوين خط الأنابيب

{
  "$schema": "https://turbo.build/schema.json",
  "globalDependencies": ["**/.env.*local"],
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],    // build dependencies first
      "outputs": [".next/**", "dist/**", "!.next/cache/**"],
      "env": ["NODE_ENV", "NEXT_PUBLIC_*"]  // cache key includes these env vars
    },
    "dev": {
      "cache":     false,   // never cache dev servers
      "persistent": true    // keep running (don't wait for exit)
    },
    "lint": {
      "dependsOn": ["^lint"]
    },
    "test": {
      "dependsOn": ["build"],
      "outputs":   ["coverage/**"],
      "inputs":    ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts"]
    },
    "typecheck": {
      "dependsOn": ["^build"],
      "outputs":   []
    }
  }
}

الخطوة 5: حزمة تكوين TypeScript المشتركة

mkdir -p packages/tsconfig
cat > packages/tsconfig/package.json << 'EOF'
{
  "name": "@mymonorepo/tsconfig",
  "version": "0.0.0",
  "private": true,
  "files": ["*.json"]
}
EOF
// packages/tsconfig/base.json
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Default",
  "compilerOptions": {
    "target":           "ES2022",
    "lib":              ["ES2022", "DOM"],
    "module":           "ESNext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "allowJs":          true,
    "strict":           true,
    "esModuleInterop":  true,
    "skipLibCheck":     true,
    "noEmit":           true
  }
}

// packages/tsconfig/nextjs.json
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Next.js",
  "extends":      "./base.json",
  "compilerOptions": {
    "plugins": [{ "name": "next" }],
    "jsx":     "preserve",
    "module":  "ESNext"
  }
}

الخطوة 6: حزمة واجهة المستخدم المشتركة

mkdir -p packages/ui/src

cat > packages/ui/package.json << 'EOF'
{
  "name": "@mymonorepo/ui",
  "version": "0.0.0",
  "private": true,
  "exports": {
    "./button":   "./src/button.tsx",
    "./card":     "./src/card.tsx"
  },
  "scripts": {
    "lint":      "eslint src/",
    "typecheck": "tsc --noEmit"
  },
  "devDependencies": {
    "@mymonorepo/tsconfig": "workspace:*",
    "typescript": "^5.0.0"
  },
  "peerDependencies": {
    "react": "^18.0.0 || ^19.0.0"
  }
}
EOF
// packages/ui/src/button.tsx
import { type ButtonHTMLAttributes } from "react";

interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
  variant?: "primary" | "secondary";
}

export function Button({ variant = "primary", children, ...props }: ButtonProps) {
  return (
    <button
      className={variant === "primary" ? "btn-primary" : "btn-secondary"}
      {...props}
    >
      {children}
    </button>
  );
}

الخطوة 7: تطبيق Next.js باستخدام الحزمة المشتركة

# apps/web/package.json
{
  "name": "web",
  "dependencies": {
    "@mymonorepo/ui":      "workspace:*",
    "@mymonorepo/utils":   "workspace:*",
    "next":                "^15.0.0",
    "react":               "^19.0.0"
  },
  "devDependencies": {
    "@mymonorepo/tsconfig": "workspace:*"
  }
}
// apps/web/tsconfig.json
{
  "extends": "@mymonorepo/tsconfig/nextjs.json",
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"]
}
// apps/web/app/page.tsx
import { Button } from "@mymonorepo/ui/button";  // shared component

export default function HomePage() {
  return (
    <main>
      <h1>Welcome</h1>
      <Button variant="primary">Get Started</Button>
    </main>
  );
}

الخطوة 8: تشغيل مونوريبو

# Install all dependencies
pnpm install

# Run all dev servers in parallel
pnpm dev

# Build all apps and packages (with caching)
pnpm build

# Build only one app
pnpm turbo build --filter=web

# Build only changed packages (incremental)
pnpm turbo build --filter="[HEAD^1]"

الخطوة 9: التخزين المؤقت عن بعد لـ CI

# Turbo remote cache with Vercel (free tier available)
npx turbo login
npx turbo link

# Now CI can use remote cache — artifacts shared across team
# .github/workflows/ci.yml
- name: Build
  run: pnpm turbo build
  env:
    TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
    TURBO_TEAM:  ${{ vars.TURBO_TEAM }}

معدلات ضرب ذاكرة التخزين المؤقت عمليًا: في فريق مكون من 5 مطورين، تكون معدلات الوصول إلى ذاكرة التخزين المؤقت بنسبة 70-80% أمرًا شائعًا في CI. غالبًا ما يستغرق البناء الذي يستغرق 8 دقائق عند التشغيل لأول مرة أقل من دقيقة واحدة مع نتائج ذاكرة التخزين المؤقت – يعد عائد الاستثمار مهمًا لأي فريق يقوم بتشغيل CI عدة مرات يوميًا.

الأسئلة المتداولة

س: pnpm vs npm vs غزل monorepos؟
ج: pnpm هو الاختيار الواضح لوحدات monorepos في عام 2026 — تستخدم وحدات العقدة المرتبطة الرمزية مساحة قرص أقل بنسبة 60-80% مقارنة بـ npm، كما أن بروتوكول مساحة العمل (workspace:*) أكثر موثوقية، والتثبيت أسرع بشكل ملحوظ. تستخدم معظم مشاريع Turborepo الجديدة pnpm.

س: متى يجب علي استخدام monorepo؟
ج: عندما يكون لديك أكثر من مشروعين مرتبطين برمز مشاركة المشاريع (الأنواع والمكونات والأدوات المساعدة). مشروع واحد: لا تهتم. 2-3 تطبيقات وثيقة الصلة: monorepo يؤتي ثماره بسرعة. نقطة التعادل هي تقريبًا “لقد سئمت من نسخ وظائف المرافق بين عمليات إعادة الشراء.”

س: كيف يمكنني إضافة باقة جديدة؟
A: mkdir packages/my-package && cd packages/my-package && pnpm init، قم بإضافته إلى مساحة العمل، ثمpnpm install. الحزمة متاحة على الفور عبرworkspace:* في حزم أخرى.

س: هل Turborepo أفضل من Nx؟
ج: يعد Turborepo أسهل في الإعداد والتكوين. يحتوي Nx على المزيد من المولدات المدمجة ونظام بيئي أكثر ثراءً للمكونات الإضافية. Turborepo للفرق الصغيرة التي تريد البساطة؛ Nx للمؤسسات الكبيرة ذات الرسوم البيانية المعقدة للبناء. كلاهما أثبت كفاءته في الإنتاج.

س: كيف يمكنني نشر التطبيقات الفردية من monorepo؟
ج: لدى Vercel وNetlify دعم monorepo أصلي – قم بتكوين “الدليل الجذر” للدليل الفرعي للتطبيق. وبدلاً من ذلك، استخدم Docker معCOPY . . في جذر monorepo وturbo build --filter=app-name.

الخلاصة

يقوم Turborepo بتحويل تطوير JavaScript متعدد التطبيقات من خلال التخلص من الإصدارات الزائدة ومشاركة التعليمات البرمجية بشكل نظيف. يستغرق الإعداد — مساحات عمل pnpm، وحزمة tsconfig المشتركة، وحزمة واجهة المستخدم المشتركة، وخط أنابيب Turbo.json، والتخزين المؤقت عن بُعد — حوالي ساعتين للتهيئة، ولكنه يُؤتي ثماره في كل إنشاء لاحق. ابدأ باستخدام قالب إنشاء توربو للحصول على أسرع مسار، أو اتبع هذا الدليل للحصول على إعداد مخصص بالكامل يتوافق مع هيكل مشروعك الفعلي.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা