DEV Community

Cover image for الـ Frontend مش مجرد واجهة: إزاي تبني Frontend Project قوي يعيش سنين؟
Ahmed Niazy
Ahmed Niazy

Posted on

الـ Frontend مش مجرد واجهة: إزاي تبني Frontend Project قوي يعيش سنين؟

 # الـ Frontend مش مجرد واجهة: إزاي تبني Frontend Project قوي يعيش سنين؟

في عالم تطوير البرمجيات، فيه فكرة منتشرة عند ناس كتير إن الـ Frontend هو الجزء “الشكلي” من المشروع. يعني التصميم، الألوان، الأزرار، الصفحات، والحاجات اللي المستخدم بيشوفها قدامه.

لكن الحقيقة إن الكلام ده بقى قديم جدًا.

الـ Frontend النهارده مش مجرد HTML وCSS وشوية JavaScript. الـ Frontend بقى جزء ضخم وأساسي من أي منتج رقمي ناجح. هو المكان اللي المستخدم بيتعامل معاه مباشرة، وهو الطبقة اللي بتحوّل فكرة المنتج لتجربة حقيقية. ومن خلاله المستخدم بيقرر: المنتج ده سهل ولا معقد؟ سريع ولا تقيل؟ واضح ولا مربك؟ احترافي ولا عشوائي؟

لكن أهمية الـ Frontend مش بس في اللي المستخدم بيشوفه. الأهم كمان هو اللي ورا الشاشة: تنظيم الكود، إدارة الحالة، التعامل مع البيانات، الأداء، الاختبارات، قابلية التوسع، سهولة الصيانة، وتجهيز المشروع إنه يعيش سنين مش شهور.

أي مشروع Frontend ممكن يبدأ بسيط جدًا.

صفحة Login.
Dashboard صغيرة.
كام Component.
شوية API Calls.
Form هنا.
Table هناك.
Routing بسيط.
وبعض Styles.

في المرحلة دي، كل حاجة بتكون سهلة. المطور يضيف Feature بسرعة، يعدّل Component بسرعة، يربط API بسرعة، والدنيا ماشية.

لكن المشكلة الحقيقية بتبدأ بعد فترة.

لما عدد الصفحات يزيد.
لما عدد الـ Components يكبر.
لما كل Feature تبقى مرتبطة بغيرها.
لما الـ API Responses تتغير.
لما الـ State Management يبقى معقد.
لما الـ Forms تكتر.
لما الـ Validation يبقى مختلف من صفحة للتانية.
لما كل مطور يكتب الكود بطريقته.
لما التصميم يبدأ يفقد اتساقه.
لما أي تعديل بسيط يكسر حاجة قديمة.
لما المطور الجديد يدخل المشروع ومش عارف يبدأ منين.

هنا بنكتشف إن الـ Frontend القوي مش مجرد شاشة شكلها جميل.

الـ Frontend القوي هو نظام كامل.
نظام منظم، واضح، قابل للتطوير، قابل للصيانة، وقابل إنه يكبر مع المنتج.


أولًا: ما هو الـ Frontend فعلًا؟

الـ Frontend هو الجزء الذي يتفاعل معه المستخدم بشكل مباشر. لكنه ليس مجرد “واجهة”. هو الطبقة التي تجمع بين التصميم، المنطق، البيانات، والتجربة.

في أي تطبيق حديث، الـ Frontend قد يكون مسؤولًا عن:

عرض البيانات للمستخدم.
التعامل مع الـ API.
إدارة حالة التطبيق.
التحكم في التنقل بين الصفحات.
حماية الصفحات حسب صلاحيات المستخدم.
عرض رسائل الأخطاء.
التعامل مع النماذج والـ Validation.
تحسين الأداء وسرعة التحميل.
تخزين بعض البيانات مؤقتًا.
التعامل مع الـ Caching.
دعم الـ Responsive Design.
دعم الـ Accessibility.
كتابة اختبارات للواجهات والمنطق.
استخدام Design System موحد.
إدارة Build وDeployment.
متابعة الأخطاء باستخدام Monitoring Tools.

يعني الـ Frontend اليوم أصبح أقرب إلى تطبيق كامل يعمل داخل المتصفح، وليس مجرد طبقة عرض بسيطة.

وهنا تظهر المشكلة: كلما زادت مسؤوليات الـ Frontend، زادت الحاجة لتنظيمه بطريقة صحيحة.

لو المشروع صغير ومؤقت، ممكن الفوضى لا تظهر بسرعة. لكن لو المنتج مستمر، والفريق يكبر، والـ Features تزيد، فغياب التنظيم سيتحول إلى تكلفة كبيرة جدًا.


ثانيًا: الفرق بين Frontend بيشتغل وFrontend مبني صح

فيه فرق كبير بين مشروع Frontend “بيشتغل” ومشروع Frontend “مبني صح”.

المشروع الذي “بيشتغل” هو مشروع يؤدي المطلوب حاليًا. الصفحة تفتح، الزر يعمل، البيانات تظهر، والـ Form يرسل البيانات.

لكن المشروع “المبني صح” هو مشروع يستطيع أن يستمر.

يعني لو احتجت تضيف Feature جديدة، تعرف تضيفها بدون خوف.
لو احتجت تغير API Client، لا تضطر لتعديل كل الصفحات.
لو احتجت تغير Design System، لا تعيد بناء كل Component من الصفر.
لو دخل مطور جديد، يستطيع فهم المشروع بسرعة.
لو حصل Bug، تعرف مكانه غالبًا.
لو أردت كتابة Tests، تجد الكود قابلًا للاختبار.
لو كبر المنتج، لا تنهار البنية الداخلية.

المشكلة إن كثير من المشاريع تهتم بالنتيجة السريعة فقط. المهم “الشاشة تطلع”. لكن بعد شهور، يصبح كل تعديل صعبًا. وكل Feature جديدة تأخذ وقتًا أطول. وكل Bug يأخذ مجهودًا أكبر.

وهنا تبدأ الديون التقنية.

الـ Technical Debt في الـ Frontend لا يظهر دائمًا في شكل Error واضح. أحيانًا يظهر في بطء التطوير. في خوف الفريق من التعديل. في تكرار نفس الكود. في Components ضخمة. في Styles متداخلة. في API calls منتشرة في كل مكان. في State غير مفهومة. في عدم وجود قواعد واضحة.

الـ Frontend الجيد لا يعني فقط أن الواجهة جميلة.
يعني أن الكود خلف الواجهة قابل للحياة.


ثالثًا: Frontend Architecture

واحدة من أهم الركائز في أي مشروع Frontend قوي هي الـ Architecture.

والـ Frontend Architecture لا تعني فقط شكل الفولدرات. صحيح إن Folder Structure جزء مهم، لكنه ليس كل شيء.

الـ Architecture تعني طريقة التفكير في بناء المشروع من الداخل.

كيف نقسم الكود؟
كيف نفصل المسؤوليات؟
كيف نتعامل مع الـ API؟
كيف ندير الـ State؟
كيف نمنع التكرار؟
كيف نكتب Components قابلة لإعادة الاستخدام؟
كيف نعزل الـ Business Logic؟
كيف نجعل المشروع قابلًا للاختبار؟
كيف نجعل كل Feature واضحة ومحددة؟
كيف نمنع المشروع من التحول إلى كتلة واحدة ضخمة؟

في البداية ممكن أي Structure ينجح. لكن مع الوقت، البنية الضعيفة تبدأ تظهر.

تخيل مشروعًا كل الـ Components فيه داخل مجلد واحد:

src/
  components/
  pages/
  hooks/
  services/
  utils/
Enter fullscreen mode Exit fullscreen mode

الشكل ده بسيط ومفهوم في البداية. لكن بعد فترة، مجلد components قد يحتوي على مئات الملفات، ومجلد services يحتوي على كل الـ API calls، ومجلد hooks يحتوي على Hooks لكل شيء.

هنا يصبح السؤال: لو عندي Feature اسمها Orders، أين أجد كل ما يخصها؟

ربما أجد ملفاتها موزعة هكذا:

components/OrderCard.tsx
components/OrderTable.tsx
pages/OrdersPage.tsx
hooks/useOrders.ts
services/ordersApi.ts
utils/formatOrder.ts
types/order.ts
Enter fullscreen mode Exit fullscreen mode

كل شيء متعلق بالـ Orders موجود في أماكن مختلفة. وهذا يجعل فهم Feature واحدة يحتاج بحثًا داخل المشروع كله.

لذلك، Architecture الجيدة تساعدك على بناء حدود واضحة داخل المشروع.


رابعًا: Feature-based Structure

واحدة من أفضل الطرق لتنظيم مشاريع الـ Frontend المتوسطة والكبيرة هي Feature-based Structure.

الفكرة بسيطة: بدل ما تقسّم المشروع حسب نوع الملف، قسّمه حسب الـ Feature أو الـ Domain.

بدل هذا الشكل:

components/
pages/
hooks/
services/
utils/
Enter fullscreen mode Exit fullscreen mode

ممكن يكون عندك:

features/
  auth/
  users/
  orders/
  payments/
  reports/
shared/
  ui/
  lib/
  api/
  config/
app/
  router/
  providers/
  layouts/
Enter fullscreen mode Exit fullscreen mode

كل Feature تحتوي الملفات الخاصة بها:

features/orders/
  components/
  hooks/
  api/
  types/
  utils/
  pages/
Enter fullscreen mode Exit fullscreen mode

الميزة هنا إن كل شيء يخص الـ Orders موجود في مكان واحد تقريبًا. المطور الذي يعمل على Orders لن يحتاج البحث في كل المشروع. سيذهب إلى Feature محددة ويفهمها.

هذا يجعل المشروع أقرب للـ Business نفسه. بدل أن يكون المشروع مقسمًا حسب “نوع الكود”، يصبح مقسمًا حسب “أجزاء المنتج”.

وهذا مهم جدًا لأن المنتجات لا تكبر حسب نوع الملفات. المنتجات تكبر حسب الـ Features.

عندك Auth.
عندك Users.
عندك Orders.
عندك Payments.
عندك Reports.
عندك Settings.

إذًا من المنطقي أن يظهر هذا التقسيم في الكود.

لكن Feature-based Structure لا تعني أن كل Feature تعيش في عزلة كاملة. هناك دائمًا أشياء مشتركة بين كل المشروع، مثل:

UI Components عامة.
API Client عام.
Helpers عامة.
Configuration.
Design Tokens.
Utilities.

هذه الأشياء يمكن وضعها داخل shared.

مثال:

src/
  app/
    router/
    providers/
    layouts/

  features/
    auth/
      api/
      components/
      hooks/
      pages/
      types/

    products/
      api/
      components/
      hooks/
      pages/
      types/

    checkout/
      api/
      components/
      hooks/
      pages/
      types/

  shared/
    ui/
    lib/
    api/
    config/
    assets/
Enter fullscreen mode Exit fullscreen mode

في هذا الشكل:

app مسؤولة عن تشغيل التطبيق وربط الأشياء العامة مثل Routing وProviders.
features مسؤولة عن أجزاء المنتج.
shared مسؤولة عن الأشياء المشتركة فعلًا.

هذه البنية تجعل المشروع أسهل في الفهم، وأسهل في التعديل، وأسهل في التوسع.


خامسًا: لا تجعل shared مقلبًا عامًا

من أكبر الأخطاء في مشاريع الـ Frontend أن يتحول مجلد shared إلى مكان لرمي أي شيء.

أي ملف لا يعرف المطور أين يضعه، يضعه في shared.
أي Component مستخدم مرة واحدة، يضعه في shared.
أي Helper خاص بFeature معينة، يضعه في shared.

بعد فترة، يصبح shared أكبر من features، وتضيع الفكرة كلها.

القاعدة المهمة هنا:

لا تضع شيئًا في shared إلا إذا كان عامًا فعلًا أو مستخدمًا في أكثر من مكان أو جزءًا من البنية العامة للمشروع.

مثال جيد:

shared/ui/Button
shared/ui/Modal
shared/ui/Input
shared/api/httpClient
shared/lib/date
shared/config/env
Enter fullscreen mode Exit fullscreen mode

مثال سيئ:

shared/components/OrderSummary
shared/hooks/useCheckout
shared/utils/calculatePaymentFees
Enter fullscreen mode Exit fullscreen mode

هذه الأشياء غالبًا ليست shared. هي تخص Orders أو Checkout أو Payments.

المبدأ المهم: لا تجعل الكود عامًا قبل أوانه.

ليس كل Component يجب أن يكون reusable. وليس كل Function يجب أن تعيش في utils. أحيانًا الأفضل أن تبقى داخل الـ Feature التي تخصها حتى يظهر احتياج حقيقي لمشاركتها.


سادسًا: Components ليست كل شيء

في الـ Frontend، الـ Component هو وحدة بناء مهمة جدًا. لكن الخطأ أن نتعامل مع المشروع كله كأنه مجرد مجموعة Components.

الـ Component مسؤول بالأساس عن العرض والتفاعل. لكن في مشاريع كثيرة، يتحول Component واحد إلى مكان لكل شيء:

يعرض UI.
يجلب البيانات من API.
يدير State.
يعمل Validation.
ينفذ Business Logic.
يتعامل مع Navigation.
يتعامل مع Errors.
يجهز Payload للـ Backend.

وبعد فترة، يصبح عندك Component ضخم جدًا، صعب القراءة وصعب الاختبار وصعب التعديل.

مثال على مشكلة شائعة:

function CheckoutPage() {
  // state
  // api calls
  // validation
  // business rules
  // formatting
  // submit logic
  // error handling
  // ui rendering
}
Enter fullscreen mode Exit fullscreen mode

هذا الشكل قد يعمل، لكنه لا يعيش جيدًا.

الأفضل أن نفصل المسؤوليات.

الـ UI يكون في Component.
التعامل مع البيانات يكون في Hook أو Service.
الـ Business Rules تكون في Functions أو Use Cases.
الـ API Calls تكون في Layer واضحة.
الـ Types تكون منظمة.

مثال أفضل:

features/checkout/
  ui/
    CheckoutPage.tsx
    CheckoutForm.tsx
  hooks/
    useCheckout.ts
  api/
    checkoutApi.ts
  domain/
    checkoutRules.ts
  types/
    checkoutTypes.ts
Enter fullscreen mode Exit fullscreen mode

هنا كل جزء له مسؤولية واضحة.

الهدف ليس زيادة الملفات لمجرد الزيادة. الهدف أن يكون كل ملف مفهومًا وله سبب واضح.


سابعًا: State Management

إدارة الحالة من أكثر المواضيع التي تسبب فوضى في الـ Frontend.

في أي تطبيق، هناك أنواع مختلفة من الـ State:

Local UI State: مثل فتح Modal أو إغلاق Dropdown.
Server State: بيانات قادمة من API.
Global State: بيانات يحتاجها أكثر من جزء في التطبيق.
Form State: بيانات النماذج والـ Validation.
URL State: Filters وPagination وSearch Params.

الخطأ الشائع هو التعامل مع كل أنواع الـ State بنفس الطريقة.

بعض الناس يضعون كل شيء في Global Store. وهذا يجعل المشروع معقدًا بدون داعي.

ليس كل State يجب أن يكون Global.

مثلاً:
هل Modal مفتوح أم لا؟ غالبًا Local State.
بيانات المستخدم الحالي؟ قد تكون Global أو Server State.
قائمة Products من API؟ غالبًا Server State مع Caching.
Filters في صفحة Reports؟ ممكن تكون في URL.
بيانات Form؟ الأفضل إدارتها داخل Form Library أو Local Form State.

اختيار مكان الـ State مهم جدًا.

لو جعلت كل شيء Global، ستصعب المتابعة.
لو جعلت كل شيء Local، ستكرر البيانات وتفقد التزامن.
لو لم تستخدم Caching مع Server State، ستزيد الطلبات على الـ API.
لو لم تستخدم URL State في الفلاتر المهمة، ستفقد قابلية مشاركة الرابط.

الـ Frontend القوي يعرف الفرق بين أنواع الـ State ولا يستخدم أداة واحدة لكل شيء.


ثامنًا: API Layer

في مشاريع كثيرة، تجد الـ API calls منتشرة في كل مكان.

Component يستدعي fetch مباشرة.
Hook يستخدم axios مباشرة.
Page تبني URL بنفسها.
كل مكان يتعامل مع Errors بطريقة مختلفة.
كل Feature تجهز Headers بطريقتها.

هذا يسبب فوضى كبيرة.

الأفضل أن يكون هناك API Layer واضحة.

مثلاً:

shared/api/httpClient.ts
features/users/api/usersApi.ts
features/orders/api/ordersApi.ts
Enter fullscreen mode Exit fullscreen mode

الـ httpClient مسؤول عن الأشياء العامة:

Base URL.
Headers.
Authentication Token.
Error Handling عام.
Interceptors.
Timeout.

وكل Feature يكون لها API File خاص بها:

export function getOrders() {}
export function getOrderById(id: string) {}
export function createOrder(payload: CreateOrderPayload) {}
Enter fullscreen mode Exit fullscreen mode

الميزة هنا أنك لو أردت تغيير طريقة التعامل مع الـ API، لن تعدل كل Components. ستعدل طبقة واحدة أو مجموعة ملفات واضحة.

كذلك، هذا يجعل الاختبار أسهل، ويجعل التعامل مع Errors أكثر اتساقًا.


تاسعًا: Forms وValidation

الـ Forms من أكثر أجزاء الـ Frontend التي يتم الاستهانة بها.

Form بسيط قد يبدو سهلًا. لكن في المشاريع الحقيقية، الـ Forms قد تكون معقدة جدًا:

Fields كثيرة.
Validation Rules.
Conditional Fields.
Async Validation.
Error Messages.
File Uploads.
Multi-step Forms.
Draft Saving.
Permissions.
Different Payload Shape.

لو كل Form تم بناؤه بطريقة مختلفة، سيصبح المشروع مليئًا بالتكرار والفوضى.

الأفضل أن يكون هناك Pattern واضح للتعامل مع الـ Forms.

كيف نكتب Validation؟
أين نضع Validation Schema؟
كيف نعرض الأخطاء؟
كيف نتعامل مع Submit؟
كيف نحول Form Values إلى API Payload؟
كيف نعرض Loading State؟
كيف نمنع Double Submit؟

هذه التفاصيل تبدو صغيرة، لكنها تؤثر جدًا على جودة المشروع وتجربة المستخدم.

الـ Frontend القوي لا يترك كل Form حسب مزاج المطور. يكون هناك طريقة واضحة ومتكررة.


عاشرًا: Routing وNavigation

الـ Routing ليس مجرد تعريف صفحات.

في التطبيقات الكبيرة، الـ Routing يرتبط بأشياء كثيرة:

Authentication.
Authorization.
Layouts.
Lazy Loading.
Nested Routes.
Breadcrumbs.
Page Titles.
Search Params.
Protected Routes.
Redirects.

لو لم يتم تنظيم Routing جيدًا، سيصبح من الصعب معرفة الصفحات، الصلاحيات، والتدفقات داخل التطبيق.

الأفضل أن يكون Routing جزءًا واضحًا داخل app/router، وأن تكون الصفحات نفسها داخل الـ Features.

مثال:

app/
  router/
    routes.tsx
    protectedRoute.tsx

features/
  auth/
    pages/
      LoginPage.tsx

  users/
    pages/
      UsersPage.tsx
      UserDetailsPage.tsx
Enter fullscreen mode Exit fullscreen mode

بهذا الشكل، الـ Routing يعرف كيف يربط الصفحات، لكن كل صفحة تعيش داخل Feature الخاصة بها.


حادي عشر: Performance

الأداء من أهم مسؤوليات الـ Frontend.

المستخدم لا يهتم إن الكود منظم لو الصفحة بطيئة.
ولا يهتم إنك تستخدم أحدث Framework لو التجربة تقيلة.

الأداء يشمل أشياء كثيرة:

حجم الـ Bundle.
سرعة تحميل الصفحة.
عدد Requests.
Caching.
Lazy Loading.
Code Splitting.
Image Optimization.
تجنب Re-renders غير ضرورية.
تحسين Fonts.
تحسين Third-party Scripts.
قياس Core Web Vitals.

في مشاريع كثيرة، الأداء لا يتم التفكير فيه إلا بعد فوات الأوان. بعد أن يصبح التطبيق ضخمًا وبطيئًا.

الأفضل أن يكون الأداء جزءًا من التفكير من البداية.

ليس معنى ذلك أن تعقد المشروع مبكرًا، لكن يجب أن تكون واعيًا لأثر قراراتك.

هل هذه المكتبة ضرورية؟
هل هذا Component يعيد الرندر كثيرًا؟
هل هذه الصور محسنة؟
هل كل الصفحات تدخل في نفس Bundle؟
هل هناك Lazy Loading للصفحات الثقيلة؟
هل هناك Caching للبيانات المتكررة؟
هل Third-party Scripts تؤثر على التحميل؟

الـ Frontend الجيد لا يكتفي بأنه “شغال”. لازم يكون سريعًا ومريحًا للمستخدم.


ثاني عشر: Accessibility

الـ Accessibility ليست إضافة اختيارية. هي جزء من جودة الواجهة.

واجهة جميلة لكنها صعبة الاستخدام لبعض المستخدمين ليست واجهة جيدة.

الـ Accessibility تعني أن المنتج يمكن استخدامه من أكبر عدد ممكن من الناس، بما في ذلك من يستخدمون Screen Readers أو Keyboard Navigation أو لديهم مشاكل في الرؤية أو الحركة.

أشياء بسيطة تفرق جدًا:

استخدام HTML Semantic.
Labels واضحة للـ Inputs.
Contrast مناسب بين النص والخلفية.
Keyboard Navigation جيد.
Focus States واضحة.
Alt Text للصور المهمة.
رسائل خطأ مفهومة.
عدم الاعتماد على اللون وحده لتوصيل المعلومة.

في مشاريع كثيرة، يتم تذكر Accessibility في آخر مرحلة. وهذا يجعل إصلاحها أصعب.

الأفضل أن تكون جزءًا من Design System ومن طريقة بناء Components من البداية.


ثالث عشر: Design System

الـ Design System ليس مجرد UI Kit أو Components جاهزة.

هو نظام كامل يحافظ على الاتساق بين التصميم والكود وتجربة المستخدم.

Design System قد يحتوي على:

Colors.
Typography.
Spacing.
Grid.
Icons.
Components.
Patterns.
Design Tokens.
Accessibility Guidelines.
Content Guidelines.
Usage Documentation.

الفكرة أن المنتج لا يبدو كأنه مبني من أجزاء مختلفة لا علاقة لها ببعض.

بدل أن كل مطور يصمم Button مختلف، يكون هناك Button موحد.
بدل أن كل صفحة تعرض Error بطريقة مختلفة، يكون هناك Pattern موحد.
بدل أن كل Form له Spacing مختلف، يكون هناك قواعد واضحة.

Design System قوي يوفر وقتًا كبيرًا ويحافظ على شكل المنتج.

لكنه يحتاج إدارة. لا يكفي بناء Components ثم تركها. يجب أن يكون هناك Documentation، تحديثات، Ownership، وقواعد استخدام واضحة.

في المشاريع الكبيرة، Design System قد يعيش كـ Package مستقل:

packages/
  ui/
  design-tokens/
Enter fullscreen mode Exit fullscreen mode

وتستخدمه التطبيقات المختلفة:

apps/
  web/
  admin/
Enter fullscreen mode Exit fullscreen mode

هذا يجعل الواجهة أكثر اتساقًا، ويجعل التطوير أسرع، ويقلل التكرار.


رابع عشر: Testing في الـ Frontend

كثير من مشاريع الـ Frontend تهمل الاختبارات. والسبب غالبًا أن الناس ترى الواجهة شيئًا بصريًا يصعب اختباره.

لكن الحقيقة أن هناك أجزاء كثيرة يمكن ويجب اختبارها.

يمكن اختبار:

Functions.
Hooks.
Components.
Forms.
User Interactions.
API Integration.
Critical Flows.

ليس المطلوب اختبار كل Pixel. لكن يجب حماية الأجزاء المهمة.

مثلاً:

Login Flow.
Checkout Flow.
Payment Flow.
Permissions.
Forms المهمة.
Calculations.
Business Rules.

الاختبارات تساعد الفريق على التعديل بثقة. بدون Tests، أي Refactor يصبح مخيفًا. وكل تعديل قد يكسر شيئًا بدون أن تلاحظ.

أنواع الاختبارات في الـ Frontend قد تشمل:

Unit Tests للمنطق الصغير.
Component Tests للمكونات.
Integration Tests لتفاعل أكثر من جزء.
End-to-End Tests للتدفقات المهمة.

المهم ألا تتحول الاختبارات إلى عبء. اختبر ما يستحق. ركز على الأشياء التي لو انكسرت ستؤثر على المستخدم أو المنتج.


خامس عشر: Clean Architecture في الـ Frontend

Clean Architecture ليست حكرًا على الـ Backend.

في الـ Frontend أيضًا، نحتاج أحيانًا إلى فصل واضح بين طبقات المشروع، خاصة عندما يكون منطق المنتج معقدًا.

الفكرة الأساسية هي فصل منطق العمل عن التفاصيل الخارجية.

يعني لا تجعل الـ Business Logic محبوسًا داخل React Component أو Vue Component أو Angular Component.

لأن الـ Component يجب أن يكون مسؤولًا عن العرض والتفاعل، وليس كل شيء.

يمكن التفكير في طبقات مثل:

ui layer
application layer
domain layer
infrastructure layer
Enter fullscreen mode Exit fullscreen mode

الـ UI Layer:
Components, Pages, Layouts.

الـ Application Layer:
Use Cases وWorkflows.

الـ Domain Layer:
Business Rules وEntities وDomain Types.

الـ Infrastructure Layer:
API Clients وStorage وExternal Services.

مثال:

features/orders/
  domain/
    order.ts
    orderRules.ts

  application/
    createOrder.ts

  infrastructure/
    ordersApi.ts

  ui/
    CreateOrderForm.tsx
Enter fullscreen mode Exit fullscreen mode

في هذا الشكل، الـ UI لا يعرف كل تفاصيل إنشاء Order. هو يستدعي Use Case. والـ Use Case يتعامل مع القواعد والـ API من خلال طبقات واضحة.

هل هذا مطلوب في كل Feature؟ لا.

لو Feature بسيطة، لا داعي للتعقيد. لكن في Features مهمة مثل Payments، Checkout، Subscriptions، Permissions، Reports، يصبح هذا الفصل مفيدًا جدًا.

Clean Architecture لا تعني كثرة الملفات.
تعني وضوح المسؤوليات.


سادس عشر: Monorepo

الـ Monorepo هو أن تضع أكثر من Application أو Package داخل Repository واحد.

مثلاً:

apps/
  web/
  admin/
  mobile/

packages/
  ui/
  api-client/
  types/
  config/
  eslint-config/
  design-tokens/
Enter fullscreen mode Exit fullscreen mode

هذا مفيد عندما يكون لديك أكثر من تطبيق يشترك في نفس الأشياء.

مثلاً:
Website.
Admin Dashboard.
Mobile App.
Shared UI Library.
Shared Types.
Shared API Client.

بدل أن تكرر نفس الكود في أكثر من Repository، يمكنك مشاركته داخليًا.

لكن Monorepo ليس مناسبًا دائمًا.

لو عندك مشروع صغير أو تطبيق واحد فقط، قد يكون Monorepo زيادة عن اللزوم.
أما لو عندك أكثر من App، وفريق كبير، وPackages مشتركة كثيرة، فهو قد يكون مفيدًا جدًا.

المهم أن Monorepo يحتاج Tooling جيد:

Caching.
Affected Builds.
Dependency Graph.
Fast CI.
Clear Boundaries.
Ownership.

بدون هذه الأشياء، قد يتحول Monorepo إلى Repo ضخم وبطيء وفوضوي.


سابع عشر: Micro Frontends

Micro Frontends هي طريقة لتقسيم تطبيق Frontend كبير إلى أجزاء أصغر يمكن تطويرها ونشرها باستقلالية.

الفكرة تكون مفيدة في الشركات الكبيرة جدًا التي لديها فرق متعددة تعمل على نفس المنتج.

مثلاً:
فريق مسؤول عن Catalog.
فريق مسؤول عن Checkout.
فريق مسؤول عن Profile.
فريق مسؤول عن Admin.

كل فريق يمكنه تطوير ونشر الجزء الخاص به بشكل مستقل.

لكن Micro Frontends ليست حلًا سحريًا. وهي ليست مناسبة لكل مشروع.

هي تضيف تعقيدًا كبيرًا في:

Routing.
Authentication.
Shared Dependencies.
Performance.
Deployment.
Testing.
Communication بين التطبيقات.
Consistency في تجربة المستخدم.
Versioning.
Monitoring.

لذلك، لا تبدأ بها مبكرًا.

في كثير من الحالات، Modular Frontend أو Modular Monolith يكون أفضل. يعني تطبيق واحد، لكن منظم داخليًا كـ Modules أو Features بحدود واضحة.

القاعدة المهمة:

لا تستخدم Micro Frontends لأن الاسم جذاب.
استخدمها فقط عندما تكون مشكلة استقلالية الفرق والنشر أكبر من تكلفة التعقيد.


ثامن عشر: Documentation

التوثيق في مشاريع الـ Frontend مهم جدًا.

ليس المطلوب كتابة كتب ضخمة. لكن المشروع يحتاج Documentation صغيرة وواضحة.

مثلًا:

كيف ننشئ Feature جديدة؟
أين نضع Components؟
أين نضع API Calls؟
كيف نكتب Forms؟
ما قواعد استخدام Design System؟
كيف نكتب Tests؟
كيف نضيف Route جديد؟
ما الممنوع في المشروع؟
كيف نستخدم shared؟

غياب التوثيق يجعل المعرفة محصورة في رؤوس أشخاص معينين. وإذا خرج هؤلاء من الفريق، تضيع المعرفة.

Documentation الجيدة توفر وقتًا، وتقلل الأسئلة المتكررة، وتساعد المطورين الجدد على الدخول بسرعة.


تاسع عشر: علامات أن مشروع الـ Frontend بدأ ينهار

هناك علامات واضحة تدل أن المشروع يحتاج إعادة تنظيم:

إضافة Feature صغيرة تحتاج تعديل ملفات كثيرة جدًا.
كل Component تقريبًا يستدعي API مباشرة.
لا أحد يعرف أين يضع الكود الجديد.
مجلد shared أصبح يحتوي نصف المشروع.
تغيير بسيط في UI يكسر صفحات غير متوقعة.
الـ Business Logic موزع بين Components وHooks وUtils.
لا توجد قواعد واضحة للتسمية والتنظيم.
الـ Forms مكتوبة بطرق مختلفة في كل صفحة.
الـ State Management غير مفهوم.
الأداء بدأ يضعف.
المطور الجديد يحتاج وقتًا طويلًا لفهم المشروع.
الفريق يخاف من Refactoring.

هذه العلامات لا تعني أن المشروع فشل. لكنها تعني أن الوقت حان لتحسين الـ Architecture والتنظيم.


عشرون: كيف تحسن مشروع Frontend قائم بدون إعادة كتابته؟

أكبر خطأ عند اكتشاف الفوضى هو التفكير في إعادة كتابة المشروع من الصفر.

إعادة الكتابة قد تكون مغرية، لكنها غالبًا مكلفة وخطرة. الأفضل في معظم الحالات هو التحسين التدريجي.

ابدأ بخطوات بسيطة:

1. حدد الـ Features الأساسية

اكتب قائمة بأجزاء المنتج:

Auth.
Users.
Orders.
Payments.
Reports.
Settings.

ثم ابدأ نقل الكود تدريجيًا داخل Features واضحة.

2. نظم shared

راجع مجلد shared.
انقل منه أي شيء يخص Feature محددة.
اترك فقط الأشياء العامة فعلًا.

3. اعزل API Layer

لا تجعل كل Component يستدعي API مباشرة.
أنشئ API Client واضحًا، وملفات API خاصة بكل Feature.

4. افصل Logic عن UI

أي Component يحتوي على Logic كبير، ابدأ بنقل هذا الـ Logic إلى Hook أو Service أو Use Case.

5. ابنِ Design System تدريجيًا

لا تبدأ بمكتبة ضخمة.
ابدأ بالمكونات الأساسية:

Button.
Input.
Modal.
Table.
Typography.
Form Controls.
Design Tokens.

6. أضف قواعد

استخدم TypeScript بجدية.
استخدم ESLint.
استخدم Path Aliases.
حدد قواعد واضحة للـ Imports.
امنع الاعتمادات العشوائية بين الـ Features لو أمكن.

7. اكتب Documentation صغيرة

صفحة واحدة تشرح طريقة التنظيم قد توفر ساعات كثيرة على الفريق.

8. حسّن الأداء تدريجيًا

ابدأ بقياس الأداء.
قلل Bundle Size.
استخدم Lazy Loading.
راجع الصور والـ Fonts.
راقب Core Web Vitals.

9. أضف Tests للأجزاء الحساسة

لا تحاول اختبار كل شيء مرة واحدة.
ابدأ بالـ Critical Flows.


واحد وعشرون: اختيار التكنولوجيا ليس هو الأهم

كثير من النقاشات في الـ Frontend تدور حول:

React أم Vue؟
Angular أم Svelte؟
Redux أم Zustand؟
Tailwind أم CSS Modules؟
Next.js أم Vite؟

هذه أسئلة مهمة، لكن ليست الأهم.

الأهم هو طريقة استخدامك للتكنولوجيا.

يمكنك بناء مشروع سيئ جدًا بـ React.
ويمكنك بناء مشروع ممتاز بـ Vue.
ويمكنك بناء مشروع منظم بـ Angular.
ويمكنك بناء فوضى بأي Framework.

الأدوات لا تنقذك من غياب التفكير.

التكنولوجيا مجرد وسيلة.
أما التنظيم، وفصل المسؤوليات، وفهم المنتج، وجودة الكود، فهي ما تجعل المشروع يعيش.


اثنان وعشرون: الـ Frontend Developer القوي

الـ Frontend Developer القوي ليس فقط من يعرف Framework.

ليس فقط من يعرف يعمل Components.
وليس فقط من يعرف يربط API.
وليس فقط من يعرف يطابق التصميم.

الـ Frontend Developer القوي هو الذي يفهم الصورة كاملة.

يفهم تجربة المستخدم.
يفهم الأداء.
يفهم Accessibility.
يفهم State Management.
يفهم Architecture.
يفهم Testing.
يفهم Design Systems.
يفهم كيف يكتب كودًا واضحًا.
يفهم كيف يبني Feature قابلة للصيانة.
يفهم متى يستخدم حلًا بسيطًا ومتى يحتاج حلًا أقوى.

القوة ليست في استخدام أدوات كثيرة.
القوة في اختيار الحل المناسب للمشكلة المناسبة.


ثلاثة وعشرون: لا تبالغ في التعقيد

رغم أهمية كل ما سبق، يجب الانتباه لنقطة مهمة جدًا:

ليس كل مشروع يحتاج كل هذه الحلول.

ليس كل مشروع يحتاج Micro Frontends.
ليس كل مشروع يحتاج Monorepo.
ليس كل Feature تحتاج Clean Architecture كاملة.
ليس كل Component يحتاج Abstraction.
ليس كل Function يجب أن تكون reusable.

الـ Overengineering مشكلة حقيقية.

المشروع الصغير يحتاج بساطة.
المشروع المتوسط يحتاج تنظيمًا واضحًا.
المشروع الكبير يحتاج حدودًا أقوى.
المشروع الضخم مع فرق متعددة قد يحتاج Monorepo أو Micro Frontends.

المهم أن تختار على حسب حجم المشكلة، لا على حسب الموضة.

أفضل Architecture ليست الأكثر تعقيدًا.
أفضل Architecture هي أبسط بنية تستطيع تحمل نمو المشروع.


أربعة وعشرون: خريطة تعلم للـ Frontend بشكل أعمق

لو تريد تطوير نفسك في الـ Frontend بشكل حقيقي، لا تكتفِ بتعلم Framework فقط.

تعلم الأساسيات:

HTML Semantic.
CSS Layouts.
JavaScript.
TypeScript.
Browser APIs.
Networking.
Performance.
Accessibility.

ثم تعلم بناء التطبيقات:

Components.
Routing.
Forms.
Validation.
State Management.
Data Fetching.
Caching.
Error Handling.
Authentication.
Authorization.

ثم تعلم ما يجعل المشروع يعيش:

Frontend Architecture.
Feature-based Structure.
Design Systems.
Testing.
Monorepo.
Clean Architecture.
Micro Frontends كمفهوم متقدم.
Refactoring.
Documentation.

لو قرأت وطبقت تدريجيًا، ستتغير طريقة تفكيرك. ستبدأ ترى الـ Frontend كمنظومة كاملة، وليس مجرد صفحات.


الخلاصة

الـ Frontend لم يعد مجرد واجهة جميلة.

الـ Frontend أصبح جزءًا أساسيًا من نجاح أي منتج رقمي.

هو الذي يواجه المستخدم.
وهو الذي يترجم التصميم إلى تجربة.
وهو الذي يتعامل مع البيانات.
وهو الذي يحافظ على سرعة المنتج.
وهو الذي يجعل الاستخدام سهلًا أو صعبًا.
وهو الذي قد يجعل التطوير سريعًا أو مرهقًا.

المشروع الجيد لا يُقاس فقط بأنه يعمل اليوم.
بل يُقاس بأنه يستطيع أن يستمر غدًا.

هل يمكن تطويره؟
هل يمكن فهمه؟
هل يمكن اختباره؟
هل يمكن توسيعه؟
هل يمكن تغييره بدون خوف؟
هل يمكن لمطور جديد الدخول فيه بسهولة؟

هذه هي الأسئلة المهمة.

الـ Frontend القوي هو الذي يجمع بين:

تجربة مستخدم ممتازة.
أداء جيد.
كود منظم.
Architecture واضحة.
Design System متسق.
State Management مفهوم.
API Layer نظيفة.
Testing للأجزاء المهمة.
Documentation تساعد الفريق.
وقابلية للتوسع مع الوقت.

في النهاية، المستخدم يرى الواجهة.
لكن الفريق يعيش مع الكود.

ولو الكود غير منظم، سيعاني الفريق، وسيتأثر المنتج، وسيدفع المستخدم الثمن في النهاية.

لذلك، لا تتعامل مع الـ Frontend كأنه مرحلة تجميل.

تعامل معه كجزء أساسي من هندسة المنتج.

لأن الـ Frontend القوي ليس فقط الذي يبدو جميلًا.
الـ Frontend القوي هو الذي يعمل جيدًا، يتطور بسهولة، ويعيش طويلًا.

Top comments (0)