فارسی

راهنمای جامع لیست امن Tailwind CSS، شامل تولید نام کلاس‌های دینامیک، بهینه‌سازی برای پروداکشن و بهترین شیوه‌ها برای حفاظت از استایل‌شیت‌های شما.

لیست امن Tailwind CSS: حفاظت از نام‌های کلاس دینامیک برای محیط پروداکشن

Tailwind CSS یک فریم‌ورک CSS مبتنی بر ابزار (utility-first) است که مجموعه‌ی وسیعی از کلاس‌های از پیش تعریف‌شده را برای استایل‌دهی به برنامه‌های وب شما فراهم می‌کند. در حالی که رویکرد utility-first آن انعطاف‌پذیری و سرعت بی‌نظیری در توسعه ارائه می‌دهد، اگر به درستی مدیریت نشود، می‌تواند منجر به فایل‌های CSS حجیم در محیط پروداکشن شود. اینجاست که لیست امن (safelisting) که به آن لیست سفید (whitelisting) نیز گفته می‌شود، وارد عمل می‌شود. لیست امن فرآیندی است که در آن شما به صراحت به Tailwind CSS می‌گویید قصد دارید از کدام نام‌های کلاس در پروژه‌ی خود استفاده کنید، و به آن اجازه می‌دهد تا تمام کلاس‌های استفاده‌نشده‌ی دیگر را در طول فرآیند بیلد حذف کند. این کار به طور چشمگیری حجم فایل CSS شما را کاهش می‌دهد و منجر به زمان بارگذاری سریع‌تر صفحه و بهبود عملکرد می‌شود.

درک نیاز به لیست امن

Tailwind CSS به طور پیش‌فرض هزاران کلاس CSS تولید می‌کند. اگر قرار بود تمام این کلاس‌ها را در بیلد پروداکشن خود بگنجانید، حتی اگر فقط از بخش کوچکی از آنها استفاده کنید، فایل CSS شما به طور غیرضروری بزرگ می‌شد. این موضوع به چند طریق بر عملکرد وب‌سایت شما تأثیر می‌گذارد:

لیست امن با گنجاندن انتخابی فقط کلاس‌هایی که واقعاً استفاده می‌کنید، این مشکلات را برطرف می‌کند و منجر به یک فایل CSS بسیار کوچک‌تر و کارآمدتر می‌شود. شیوه‌های مدرن توسعه وب نیازمند کدی سبک و بهینه‌سازی شده هستند. لیست امن با Tailwind CSS فقط یک رویه‌ی پیشنهادی نیست؛ بلکه یک ضرورت برای ارائه برنامه‌های وب با عملکرد بالا است.

چالش‌های نام‌های کلاس دینامیک

در حالی که لیست امن بسیار مهم است، اما هنگام استفاده از نام‌های کلاس دینامیک، چالشی را ایجاد می‌کند. نام‌های کلاس دینامیک آنهایی هستند که در زمان اجرا تولید یا اصلاح می‌شوند، که اغلب بر اساس ورودی کاربر، داده‌های دریافت شده از یک API، یا منطق شرطی در کد جاوا اسکریپت شما است. پیش‌بینی این کلاس‌ها در طول فرآیند اولیه بیلد Tailwind CSS دشوار است، زیرا ابزارها نمی‌توانند «ببینند» که به این کلاس‌ها نیاز خواهد بود.

برای مثال، سناریویی را در نظر بگیرید که در آن شما به صورت دینامیک رنگ‌های پس‌زمینه را بر اساس ترجیحات کاربر اعمال می‌کنید. ممکن است مجموعه‌ای از گزینه‌های رنگی (مانند `bg-red-500`، `bg-green-500`، `bg-blue-500`) داشته باشید و از جاوا اسکریپت برای اعمال کلاس مناسب بر اساس انتخاب کاربر استفاده کنید. در این حالت، Tailwind CSS ممکن است این کلاس‌ها را در فایل CSS نهایی قرار ندهد، مگر اینکه شما به صراحت آنها را در لیست امن قرار دهید.

مثال رایج دیگر شامل محتوای تولید شده به صورت دینامیک با استایل‌های مرتبط با آن است. تصور کنید در حال ساخت یک داشبورد هستید که ویجت‌های مختلفی را نمایش می‌دهد و هر کدام استایل منحصر به فردی دارند که توسط نوع یا منبع داده آن تعیین می‌شود. کلاس‌های خاص Tailwind CSS که به هر ویجت اعمال می‌شوند ممکن است به داده‌های در حال نمایش بستگی داشته باشد، که این امر قرار دادن آنها در لیست امن را از قبل چالش‌برانگیز می‌کند. این موضوع همچنین در مورد کتابخانه‌های کامپوننت نیز صدق می‌کند، جایی که شما می‌خواهید کاربر نهایی بتواند از برخی کلاس‌های CSS استفاده کند.

روش‌های ایجاد لیست امن برای نام‌های کلاس دینامیک

چندین استراتژی برای ایجاد لیست امن برای نام‌های کلاس دینامیک در Tailwind CSS وجود دارد. بهترین رویکرد به پیچیدگی پروژه شما و درجه دینامیک بودن آن بستگی دارد.

۱. استفاده از گزینه‌ی `safelist` در `tailwind.config.js`

ساده‌ترین روش استفاده از گزینه‌ی `safelist` در فایل `tailwind.config.js` شما است. این گزینه به شما امکان می‌دهد تا به صراحت نام‌های کلاسی را که باید همیشه در فایل CSS نهایی گنجانده شوند، مشخص کنید.

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
  ],
  safelist: [
    'bg-red-500',
    'bg-green-500',
    'bg-blue-500',
    'text-xl',
    'font-bold',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

مزایا:

معایب:

۲. استفاده از عبارات باقاعده در `safelist`

برای سناریوهای پیچیده‌تر، می‌توانید از عبارات باقاعده (regular expressions) در گزینه‌ی `safelist` استفاده کنید. این به شما امکان می‌دهد تا الگوهایی از نام‌های کلاس را مطابقت دهید، به جای اینکه هر کدام را به صراحت لیست کنید.

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
  ],
  safelist: [
    /^bg-.*-500$/,
    /^text-./, // مثالی برای تطبیق تمام کلاس‌های متن
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

در این مثال، عبارت باقاعده `/^bg-.*-500$/` با هر نام کلاسی که با `bg-` شروع می‌شود، سپس هر کاراکتری (`.*`) و سپس `-500` دنبال می‌شود، مطابقت خواهد داشت. این شامل کلاس‌هایی مانند `bg-red-500`، `bg-green-500`، `bg-blue-500` و حتی `bg-mycustomcolor-500` خواهد بود.

مزایا:

معایب:

۳. تولید یک لیست امن دینامیک در زمان بیلد

برای سناریوهای بسیار دینامیک که نام کلاس‌ها واقعاً غیرقابل پیش‌بینی هستند، می‌توانید در طول فرآیند بیلد یک لیست امن دینامیک تولید کنید. این شامل تجزیه و تحلیل کد شما برای شناسایی نام‌های کلاس دینامیک و سپس اضافه کردن آنها به گزینه‌ی `safelist` قبل از اجرای Tailwind CSS است.

این رویکرد معمولاً شامل استفاده از یک اسکریپت بیلد (مثلاً یک اسکریپت Node.js) برای موارد زیر است:

  1. تجزیه فایل‌های جاوا اسکریپت، تایپ‌اسکریپت یا سایر فایل‌های کد شما.
  2. شناسایی نام‌های کلاس دینامیک بالقوه (مثلاً با جستجوی الحاق رشته یا منطق شرطی که نام کلاس تولید می‌کند).
  3. تولید یک آرایه‌ی `safelist` حاوی نام‌های کلاس شناسایی شده.
  4. به‌روزرسانی فایل `tailwind.config.js` خود با آرایه‌ی `safelist` تولید شده.
  5. اجرای فرآیند بیلد Tailwind CSS.

این پیچیده‌ترین رویکرد است، اما بیشترین انعطاف‌پذیری و دقت را برای مدیریت نام‌های کلاس بسیار دینامیک ارائه می‌دهد. شما می‌توانید از ابزارهایی مانند `esprima` یا `acorn` (تجزیه‌کننده‌های جاوا اسکریپت) برای تجزیه و تحلیل پایگاه کد خود برای این منظور استفاده کنید. داشتن پوشش تست خوب برای این رویکرد بسیار مهم است.

در اینجا یک مثال ساده از چگونگی پیاده‌سازی این روش آورده شده است:

// build-safelist.js
const fs = require('fs');
const glob = require('glob');

// تابعی برای استخراج کلاس‌های بالقوه‌ی Tailwind از یک رشته (مثال بسیار ساده)
function extractClasses(content) {
  const classRegex = /(?:class(?:Name)?=["'])([^"']*)(?:["'])/g;  // رگولار اکسپرشن بهبود یافته
  let match;
  const classes = new Set();
  while ((match = classRegex.exec(content)) !== null) {
    const classList = match[1].split(/\s+/);
    classList.forEach(cls => {
      // این را بیشتر اصلاح کنید تا بررسی شود که آیا کلاس *شبیه* به کلاس Tailwind است
      if (cls.startsWith('bg-') || cls.startsWith('text-') || cls.startsWith('font-')) {  // بررسی ساده کلاس Tailwind
        classes.add(cls);
      }
    });
  }
  return Array.from(classes);
}


const files = glob.sync('./src/**/*.{js,jsx,ts,tsx}'); // الگوی glob را برای مطابقت با فایل‌های خود تنظیم کنید

let allClasses = [];
files.forEach(file => {
  const content = fs.readFileSync(file, 'utf-8');
  const extractedClasses = extractClasses(content);
   allClasses = allClasses.concat(extractedClasses);
});

const uniqueClasses = [...new Set( allClasses)];

// خواندن کانفیگ Tailwind
const tailwindConfigPath = './tailwind.config.js';
const tailwindConfig = require(tailwindConfigPath);

// به‌روزرسانی safelist
tailwindConfig.safelist = tailwindConfig.safelist || []; // اطمینان از وجود safelist
tailwindConfig.safelist = tailwindConfig.safelist.concat(uniqueClasses);

// نوشتن کانفیگ به‌روز شده در فایل
fs.writeFileSync(tailwindConfigPath, `module.exports = ${JSON.stringify(tailwindConfig, null, 2)}`);

console.log('لیست امن کانفیگ Tailwind با موفقیت به‌روز شد!');

و فایل `package.json` خود را برای اجرای این اسکریپت قبل از مرحله بیلد خود تغییر دهید:

{"scripts": {
  "build": "node build-safelist.js && next build",  // یا دستور بیلد شما
  ...
}}

ملاحظات مهم برای تجزیه کد:

مزایا:

معایب:

۴. استفاده از استایل‌های درون‌خطی به عنوان آخرین راه‌حل (عموماً توصیه نمی‌شود)

اگر استایل‌های بسیار دینامیکی دارید که نمی‌توان به راحتی با هیچ یک از روش‌های فوق آنها را در لیست امن قرار داد، ممکن است استفاده از استایل‌های درون‌خطی (inline styles) را به عنوان آخرین راه‌حل در نظر بگیرید. با این حال، این رویکرد به طور کلی توصیه نمی‌شود زیرا هدف استفاده از یک فریم‌ورک CSS مانند Tailwind CSS را نقض می‌کند.

استایل‌های درون‌خطی مستقیماً به عناصر HTML اعمال می‌شوند، به جای اینکه در یک فایل CSS تعریف شوند. این می‌تواند منجر به چندین مشکل شود:

اگر مجبور به استفاده از استایل‌های درون‌خطی هستید، سعی کنید استفاده از آنها را فقط به پویاترین و غیرقابل پیش‌بینی‌ترین استایل‌ها محدود کنید. استفاده از کتابخانه‌های جاوا اسکریپت را در نظر بگیرید که می‌توانند به شما در مدیریت مؤثرتر استایل‌های درون‌خطی کمک کنند، مانند پراپ `style` در React یا بایندینگ `:style` در Vue.js.

مثال (React):

function MyComponent({ backgroundColor }) {
  return (
    
{/* ... */}
); }

بهترین شیوه‌ها برای لیست امن Tailwind CSS

برای اطمینان از اینکه استراتژی لیست امن Tailwind CSS شما مؤثر و قابل نگهداری است، این بهترین شیوه‌ها را دنبال کنید:

مثال‌هایی از سناریوها با پیامدهای بین‌المللی

لیست امن هنگام در نظر گرفتن برنامه‌هایی با ویژگی‌های بین‌المللی‌سازی (i18n) و بومی‌سازی (l10n) اهمیت بیشتری پیدا می‌کند.

زبان‌های راست-به-چپ (RTL)

برای زبان‌هایی مانند عربی، عبری و فارسی، متن از راست به چپ جریان دارد. Tailwind CSS ابزارهایی برای مدیریت طرح‌بندی‌های RTL، مانند `rtl:text-right` و `ltr:text-left` فراهم می‌کند. با این حال، این ابزارها تنها در صورتی در فایل CSS نهایی گنجانده می‌شوند که به صراحت در لیست امن قرار گیرند یا در کد منبع شما شناسایی شوند.

اگر برنامه شما از زبان‌های RTL پشتیبانی می‌کند، حتماً ابزارهای RTL مربوطه را در لیست امن قرار دهید تا اطمینان حاصل شود که طرح‌بندی‌های شما در محیط‌های RTL به درستی نمایش داده می‌شوند. به عنوان مثال، ممکن است از یک عبارت باقاعده مانند `/^(rtl:|ltr:)/` برای قرار دادن تمام ابزارهای RTL و LTR در لیست امن استفاده کنید.

خانواده‌های فونت مختلف

زبان‌های مختلف برای نمایش صحیح کاراکترها به خانواده‌های فونت متفاوتی نیاز دارند. به عنوان مثال، زبان‌های چینی، ژاپنی و کره‌ای به فونت‌هایی نیاز دارند که از کاراکترهای CJK پشتیبانی کنند. به طور مشابه، زبان‌هایی با کاراکترهای دارای اعراب ممکن است به فونت‌هایی نیاز داشته باشند که آن کاراکترها را شامل شوند.

اگر برنامه شما از چندین زبان پشتیبانی می‌کند، ممکن است نیاز به استفاده از خانواده‌های فونت مختلف برای زبان‌های مختلف داشته باشید. می‌توانید از قاعده‌ی `@font-face` در CSS برای تعریف خانواده‌های فونت سفارشی استفاده کنید و سپس از Tailwind CSS برای اعمال آنها به عناصر خاص استفاده کنید. حتماً نام‌های خانواده فونتی را که در CSS خود استفاده می‌کنید در لیست امن قرار دهید تا اطمینان حاصل شود که در فایل CSS نهایی گنجانده شده‌اند.

مثال:

/* در فایل CSS سراسری شما */
@font-face {
  font-family: 'Noto Sans SC';
  src: url('/fonts/NotoSansSC-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
}

@font-face {
  font-family: 'Noto Sans SC';
  src: url('/fonts/NotoSansSC-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
}

/* در فایل tailwind.config.js شما */
module.exports = {
  // ...
  theme: {
    extend: {
      fontFamily: {
        'sans': ['Noto Sans SC', ...],
      },
    },
  },
  safelist: [
    'font-sans', // اطمینان می‌دهد که font-sans همیشه گنجانده می‌شود
  ],
};

تفاوت‌های فرهنگی در استایل‌دهی

در برخی موارد، ترجیحات استایل‌دهی می‌تواند در فرهنگ‌های مختلف متفاوت باشد. به عنوان مثال، تداعی رنگ‌ها می‌تواند از یک فرهنگ به فرهنگ دیگر به طور قابل توجهی متفاوت باشد. به طور مشابه، استفاده از فضای سفید و تایپوگرافی نیز می‌تواند تحت تأثیر هنجارهای فرهنگی باشد.

اگر برنامه شما به مخاطبان جهانی خدمات ارائه می‌دهد، به این تفاوت‌های فرهنگی توجه داشته باشید و استایل‌دهی خود را بر این اساس تنظیم کنید. این ممکن است شامل استفاده از کلاس‌های CSS مختلف برای زبان‌های مختلف یا اجازه دادن به کاربران برای سفارشی‌سازی ترجیحات استایل‌دهی خود باشد.

نتیجه‌گیری

لیست امن Tailwind CSS یک تکنیک بهینه‌سازی حیاتی برای محیط‌های پروداکشن است. با مشخص کردن صریح نام‌های کلاسی که باید در فایل CSS نهایی گنجانده شوند، می‌توانید به طور قابل توجهی حجم آن را کاهش دهید، که منجر به زمان بارگذاری سریع‌تر صفحه و بهبود عملکرد می‌شود. در حالی که نام‌های کلاس دینامیک چالشی را ایجاد می‌کنند، چندین استراتژی برای قرار دادن آنها در لیست امن وجود دارد، از لیست‌های صریح ساده گرفته تا تولید لیست امن دینامیک پیچیده‌تر. با پیروی از بهترین شیوه‌های ذکر شده در این راهنما، می‌توانید اطمینان حاصل کنید که استراتژی لیست امن Tailwind CSS شما مؤثر، قابل نگهداری و سازگار با نیازهای منحصر به فرد پروژه شما است.

به یاد داشته باشید که در پروژه‌های توسعه وب خود، تجربه کاربری و عملکرد را در اولویت قرار دهید. لیست امن با Tailwind CSS ابزاری قدرتمند برای دستیابی به این اهداف است.