معالج SASS/SCSS

أفضل ممارسات SASS والأداء

20 دقيقة الدرس 27 من 30

مقدمة إلى أفضل ممارسات SASS

كتابة كود SASS نظيف وقابل للصيانة وعالي الأداء أمر ضروري لنجاح المشروع على المدى الطويل. في هذا الدرس الشامل، سنستكشف أفضل ممارسات الصناعة واتفاقيات التسمية وتقنيات تحسين الأداء والمخاطر الشائعة التي يجب تجنبها. ستساعدك هذه الإرشادات على كتابة كود SASS سهل الفهم والصيانة ويتوسع بشكل جيد في المشاريع الكبيرة.

كتابة كود SASS قابل للصيانة

قابلية الصيانة أمر حاسم للمشاريع التي تتطور بمرور الوقت وتشمل عدة مطورين.

الحفاظ على الملفات صغيرة ومركزة

يجب أن يكون لكل ملف جزئي مسؤولية واحدة واضحة:

البنية الجيدة

// _buttons.scss - أنماط الأزرار فقط
.btn {
  // أنماط الزر الأساسية
}

.btn-primary {
  // متغير الزر الأساسي
}

// _forms.scss - أنماط النماذج فقط
.form-group {
  // أنماط مجموعة النموذج
}

.form-control {
  // أنماط عنصر التحكم في النموذج
}
تحذير: تجنب إنشاء ملفات "حوض المطبخ" التي تحتوي على أنماط غير ذات صلة. ملف باسم _utilities.scss يحتوي على أزرار ونماذج وطباعة يصعب صيانته.

استخدم تعليقات ذات معنى

علق على كودك لشرح "لماذا" وليس "ماذا":

التعليقات الجيدة مقابل السيئة

// سيء: يذكر الواضح
.btn {
  padding: 10px 20px; // إضافة حشو
}

// جيد: يشرح السبب
.btn {
  // الحشو الإضافي يعوض عن الوهم البصري
  // الناجم عن الزوايا المستديرة التي تجعل الأزرار تبدو أصغر
  padding: 10px 20px;
}

// جيد: يوثق الحسابات المعقدة
$container-width: 1200px;
$column-count: 12;
$gutter-width: 30px;

// احسب عرض العمود مع مراعاة الفجوات
// الصيغة: (الحاوية - (الفجوات * (الأعمدة - 1))) / الأعمدة
$column-width: ($container-width - ($gutter-width * ($column-count - 1))) / $column-count;

اتفاقيات التسمية

اتفاقيات التسمية المتسقة تحسن قابلية قراءة الكود وتمنع تعارضات التسمية.

تسمية المتغيرات

أنماط تسمية المتغيرات

// استخدم أسماء دلالية، وليس أسماء تقديمية
$brand-primary: #3498db;      // جيد
$blue: #3498db;               // تجنب - ماذا لو تغير لون العلامة التجارية؟

// استخدم التسمية الهرمية للقيم ذات الصلة
$font-size-base: 16px;
$font-size-small: 14px;
$font-size-large: 18px;
$font-size-xlarge: 24px;

// قم بتجميع المتغيرات ذات الصلة بالبادئات
$spacing-xs: 4px;
$spacing-sm: 8px;
$spacing-md: 16px;
$spacing-lg: 24px;
$spacing-xl: 32px;

// استخدم أسماء وصفية لطبقات z-index
$z-index-dropdown: 1000;
$z-index-modal: 1050;
$z-index-tooltip: 1070;

// المتغيرات المنطقية يجب أن تكون أسئلة
$has-border: true;
$is-responsive: true;
$should-animate: false;

تسمية Mixin والدوال

أسماء Mixin والدوال

// Mixins: استخدم أفعالاً تصف ما تفعله
@mixin center-content() { }       // جيد
@mixin clearfix() { }             // جيد
@mixin content-center() { }       // أقل وضوحاً

// الدوال: سمِّ مثل الدوال في البرمجة
@function calculate-rem($px) { }  // جيد
@function get-color($name) { }    // جيد
@function rem($px) { }            // جيد (دوال مساعدة قصيرة)

// تجنب الأسماء العامة
@mixin utility() { }              // غامض جداً
@function process($value) { }     // ماذا يعالج؟

تسمية الملفات

اتفاقيات تسمية الملفات

// الملفات الجزئية تبدأ بشرطة سفلية
_variables.scss
_mixins.scss
_buttons.scss

// الملفات الرئيسية ليس بها شرطة سفلية
main.scss
admin.scss

// استخدم kebab-case للملفات متعددة الكلمات
_button-groups.scss
_dropdown-menus.scss
_form-validation.scss

// نظّم بالبادئات إذا لزم الأمر
_component-card.scss
_component-modal.scss
_layout-header.scss
_layout-footer.scss

الحد الأقصى لعمق التداخل

التداخل العميق ينشئ محددات محددة جداً يصعب تجاوزها ويزيد من حجم الملف.

قاعدة المستويات 3-4

أمثلة على عمق التداخل

// سيء: عميق جداً (5 مستويات)
.navigation {
  .menu {
    .item {
      .link {
        .icon {
          color: red; // ينتج: .navigation .menu .item .link .icon
        }
      }
    }
  }
}

// جيد: الحد الأقصى 3-4 مستويات
.navigation {
  .menu-item {
    // استخدم التحديد المباشر عند الاقتضاء
    > .link {
      color: blue;

      .icon {
        margin-right: 8px;
      }
    }
  }
}

// أفضل: استخدم BEM لتجنب التداخل العميق
.nav { }
.nav__menu { }
.nav__item { }
.nav__link { }
.nav__icon { }
نصيحة: إذا وجدت نفسك تتداخل أكثر من 3-4 مستويات، ففكر في استخدام منهجية BEM أو إنشاء مكون جديد.

متى يكون التداخل مناسباً

حالات استخدام جيدة للتداخل

// 1. الفئات الزائفة والعناصر الزائفة
.button {
  &:hover {
    background: blue;
  }

  &::before {
    content: "";
  }
}

// 2. استعلامات الوسائط
.card {
  width: 100%;

  @media (min-width: 768px) {
    width: 50%;
  }
}

// 3. فئات الحالة
.modal {
  display: none;

  &.is-open {
    display: block;
  }
}

// 4. محددات الوالدين مع المعدلات
.alert {
  padding: 16px;

  &--success {
    background: green;
  }

  &--error {
    background: red;
  }
}

تجنب مخاطر @extend

في حين أن @extend يمكن أن يكون مفيداً، إلا أن لديه العديد من المزالق التي يمكن أن تسبب سلوكاً غير متوقع.

مشاكل @extend

مشاكل @extend

// المشكلة 1: ينشئ مجموعات محددات غير متوقعة
.error {
  color: red;
}

.serious-error {
  @extend .error;
  font-weight: bold;
}

// ينتج:
// .error, .serious-error { color: red; }
// .serious-error { font-weight: bold; }

// لكن إذا كان لديك:
.error.icon { }

// ينتج أيضاً:
// .serious-error.icon { } <-- غير متوقع!

// المشكلة 2: لا يمكن التمديد عبر استعلامات الوسائط
@media (min-width: 768px) {
  .button {
    @extend .btn; // خطأ! لا يمكن التمديد خارج استعلام الوسائط
  }
}

// المشكلة 3: مشاكل التسلسل والخصوصية
.component {
  .message {
    color: blue;
  }
}

.alert {
  @extend .message; // أين يمتد هذا؟
}

بدائل لـ @extend

نهج أفضل

// البديل 1: استخدم mixins بدلاً من ذلك
@mixin error-styles {
  color: red;
  border: 1px solid red;
}

.error {
  @include error-styles;
}

.serious-error {
  @include error-styles;
  font-weight: bold;
}

// البديل 2: استخدم فئات المساعدة في HTML
<div class="error font-bold"></div>

// البديل 3: استخدم محددات النائب (إذا كان عليك التمديد)
%error-styles {
  color: red;
  border: 1px solid red;
}

.error {
  @extend %error-styles;
}

.serious-error {
  @extend %error-styles;
  font-weight: bold;
}
تحذير: يوصي العديد من خبراء SASS بتجنب @extend تماماً لصالح mixins، والتي أكثر قابلية للتنبؤ وليس لديها نفس مشاكل التسلسل.

الحفاظ على المحددات بسيطة ومنخفضة الخصوصية

الخصوصية العالية تجعل من الصعب تجاوز الأنماط وتؤدي إلى إساءة استخدام !important.

أمثلة على الخصوصية

تقليل الخصوصية

// سيء: محدد جداً (الخصوصية: 0,0,4,0)
.sidebar .widget .title .link {
  color: blue;
}

// جيد: خصوصية أقل (0,0,1,0)
.widget-link {
  color: blue;
}

// سيء: محددات الهوية لها خصوصية عالية
#header .nav .item { } // الخصوصية: 0,1,2,0

// جيد: استخدم الفئات
.header-nav-item { }   // الخصوصية: 0,0,1,0

// سيء: دمج الكثير من المحددات
nav.primary-nav ul.nav-list li.nav-item a.nav-link { }

// جيد: حافظ على البساطة
.nav-link { }

تجنب !important

بدائل !important

// سيء: استخدام !important كإصلاح سريع
.button {
  background: blue;
}

.special-button {
  background: red !important; // يبدأ حرب !important
}

// جيد: زيادة الخصوصية بشكل صحيح أو إعادة الهيكلة
.button {
  background: blue;
}

.button.special {
  background: red; // أكثر تحديداً بشكل طبيعي
}

// أو إعادة صياغة المحددات الخاصة بك
.btn-primary {
  background: blue;
}

.btn-special {
  background: red; // نفس الخصوصية، ترتيب المصدر يفوز
}

تحسين حجم ملف الإخراج

يمكن أن يقلل تحسين كود SASS بشكل كبير من حجم ملف CSS النهائي.

تقنيات لإخراج أصغر

تقنيات التحسين

// 1. استخدم خصائص الاختصار
// سيء
.box {
  margin-top: 10px;
  margin-right: 20px;
  margin-bottom: 10px;
  margin-left: 20px;
}

// جيد
.box {
  margin: 10px 20px;
}

// 2. دمج المحددات بنفس الخصائص
// سيء
.header {
  font-size: 16px;
}
.footer {
  font-size: 16px;
}

// جيد
.header,
.footer {
  font-size: 16px;
}

// 3. تجنب توليد أنماط غير مستخدمة
// سيء: ينتج 12 فئة قد لا تستخدمها
@for $i from 1 through 12 {
  .col-#{$i} {
    width: percentage($i / 12);
  }
}

// جيد: ولّد فقط ما تحتاجه
$columns: (1, 2, 3, 4, 6, 12);
@each $col in $columns {
  .col-#{$col} {
    width: percentage($col / 12);
  }
}

// 4. استخدم خصائص CSS المخصصة للتغييرات في وقت التشغيل
// سيء: ينتج فئة منفصلة لكل لون
@each $name, $color in $colors {
  .bg-#{$name} {
    background: $color;
  }
}

// أفضل: استخدم متغيرات CSS
:root {
  @each $name, $color in $colors {
    --color-#{$name}: #{$color};
  }
}

.bg-primary {
  background: var(--color-primary);
}

تجنب توليد الكثير من المحددات

كن حذراً مع الحلقات والخرائط التي تولد أعداداً كبيرة من المحددات.

توليد المحددات

// سيء: ينتج مئات الفئات
@for $i from 1 through 100 {
  .mt-#{$i} {
    margin-top: #{$i}px;
  }
  .mb-#{$i} {
    margin-bottom: #{$i}px;
  }
  // ... ينتج أكثر من 200 فئة
}

// جيد: استخدم مقياس تباعد
$spacings: (
  0: 0,
  1: 4px,
  2: 8px,
  3: 16px,
  4: 24px,
  5: 32px
);

@each $name, $value in $spacings {
  .mt-#{$name} { margin-top: $value; }
  .mb-#{$name} { margin-bottom: $value; }
}

// أفضل: فكر في خصائص CSS المخصصة
:root {
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 16px;
}

.mt-3 {
  margin-top: var(--space-3);
}

التدقيق باستخدام stylelint

يساعد stylelint في فرض معايير ترميز متسقة واكتشاف الأخطاء تلقائياً.

تثبيت stylelint

التثبيت

npm install --save-dev stylelint stylelint-config-standard-scss

تكوين stylelint

.stylelintrc.json

{
  "extends": "stylelint-config-standard-scss",
  "rules": {
    "max-nesting-depth": 3,
    "selector-max-compound-selectors": 4,
    "selector-max-specificity": "0,4,0",
    "declaration-no-important": true,
    "selector-no-qualifying-type": true,
    "selector-class-pattern": "^[a-z][a-z0-9]*(-[a-z0-9]+)*$",
    "color-named": "never",
    "scss/at-extend-no-missing-placeholder": true,
    "scss/selector-no-redundant-nesting-selector": true,
    "scss/at-import-partial-extension": "never"
  }
}

تشغيل stylelint

سكريبتات package.json

{
  "scripts": {
    "lint:scss": "stylelint \"src/**/*.scss\"",
    "lint:scss:fix": "stylelint \"src/**/*.scss\" --fix",
    "prelint": "npm run lint:scss"
  }
}

قائمة التحقق من مراجعة كود SASS

استخدم هذه القائمة عند مراجعة كود SASS:

قائمة التحقق من مراجعة كود SASS

□ اتفاقيات التسمية
  □ المتغيرات تستخدم أسماء دلالية (وليست تقديمية)
  □ Mixins والدوال لها أسماء واضحة ووصفية
  □ الملفات تتبع اتفاقية التسمية (_partial.scss)

□ البنية
  □ الملفات مركزة ولها مسؤولية واحدة
  □ عمق التداخل لا يتجاوز 3-4 مستويات
  □ الاستخدام الصحيح لـ @use/@forward (وليس @import)

□ الأداء
  □ لا توليد محددات مفرط
  □ الحلقات والخرائط ضرورية وفعالة
  □ لا كود غير مستخدم أو كتل معلقة

□ قابلية الصيانة
  □ الكود DRY (لا تكرر نفسك)
  □ الحسابات المعقدة معلقة
  □ الأرقام السحرية مستبدلة بمتغيرات

□ أفضل الممارسات
  □ الحد الأدنى من استخدام @extend (يفضل mixins)
  □ لا محددات محددة جداً
  □ لا تصريحات !important
  □ إخراج CSS محسّن ومصغر

□ التوافق
  □ بادئات البائعين تتم معالجتها بواسطة autoprefixer
  □ تلبية متطلبات دعم المتصفح
  □ لا بناء جملة SASS لا يترجم

أنماط مضادة شائعة يجب تجنبها

الأنماط المضادة

// 1. معالجة الألوان بدون متغيرات
.button {
  background: lighten(#3498db, 10%); // صعب التتبع
}
// أفضل: استخدم متغيرات ألوان دلالية
$btn-bg: $brand-primary;
$btn-bg-hover: lighten($btn-bg, 10%);

// 2. الأرقام السحرية
.header {
  padding-top: 73px; // لماذا 73؟ من أين جاء هذا؟
}
// أفضل: استخدم متغيرات ذات معنى
$header-padding: $spacing-lg + $spacing-sm; // حساب واضح

// 3. تكرار الحسابات
.col-6 { width: percentage(6 / 12); }
.col-4 { width: percentage(4 / 12); }
// أفضل: استخدم دالة
@function col-width($cols) {
  @return percentage($cols / 12);
}

// 4. خلط المخاوف في ملف واحد
// _utilities.scss يحتوي على أزرار ونماذج وطباعة، إلخ.
// أفضل: افصل إلى ملفات مركزة

// 5. أسماء فئات عامة جداً
.wrapper { }
.container { }
.item { }
// أفضل: كن محدداً حول الغرض
.card-wrapper { }
.article-container { }
.menu-item { }

تمرين 1: إعادة الصياغة لقابلية الصيانة

أعد صياغة كود SASS السيء هذا:

.nav {
  .list {
    .item {
      .link {
        .icon {
          color: #3498db !important;
        }
        .text {
          font-size: 14px;
        }
      }
    }
  }
}

.footer {
  .list {
    .item {
      .link {
        .icon {
          color: #3498db !important;
        }
        .text {
          font-size: 14px;
        }
      }
    }
  }
}

طبّق أفضل الممارسات: قلل التداخل، احذف !important، استخدم المتغيرات، تخلّص من التكرار.

تمرين 2: تحسين المحددات المولدة

حسّن هذا الكود الذي يولد الكثير من المحددات:

@for $i from 1 through 50 {
  .text-#{$i} {
    font-size: #{$i}px;
  }
}

@each $color in (red, blue, green, yellow, orange, purple, pink, brown, gray, black, white) {
  .color-#{$color} {
    color: $color;
  }
  .bg-#{$color} {
    background: $color;
  }
}

قلل عدد الفئات المولدة إلى ما هو ضروري فقط، استخدم مقياساً مناسباً، وفكر في بدائل مثل خصائص CSS المخصصة.

تمرين 3: إعداد stylelint

كوّن stylelint لمشروعك:

  1. ثبّت stylelint و stylelint-config-standard-scss
  2. أنشئ ملف تكوين .stylelintrc.json
  3. أضف قواعد لـ: الحد الأقصى لعمق التداخل (3)، لا !important، نمط تسمية الفئة (kebab-case)، ولا تمديدات نائب مفقودة
  4. أضف سكريبتات npm للتدقيق والإصلاح التلقائي
  5. قم بتشغيل المدقق على ملفات SASS وإصلاح أي انتهاكات