CSS الأصلي

يوضح هذا الدليل كيفية استخدام معالجة CSS المدمجة في webpack عبر experiments.css، وكيفية نقل إعداد قائم من css-loader وstyle-loader وmini-css-extract-plugin إلى الحل الأصلي.

البدء

فعّل دعم CSS الأصلي في ملف تخصيص webpack:

webpack.config.js

export default {
  experiments: {
    css: true,
  },
};

عند تفعيل هذا الخيار، يتعامل webpack مع ملفات .css بوصفها وحدات أصلية: يحلل @import وurl()، ويستخرج أوراق الأنماط، وينشئ تجزئات للمحتوى، ويدعم CSS Modules، وكل ذلك من دون css-loader أو style-loader أو mini-css-extract-plugin.

استيراد CSS

بعد تفعيل الميزة التجريبية، استورد ملفات .css مباشرةً من JavaScript:

src/index.js

import "./styles.css";

const element = document.createElement("h1");
element.textContent = "Hello native CSS";
document.body.appendChild(element);

src/styles.css

h1 {
  color: #1f6feb;
}

يعالج webpack ملف CSS ويضمه إلى مخرجات البناء.

أنواع وحدات CSS

يضيف CSS الأصلي أربع قيم للخيار Rule.type. معرفة النوع المناسب أساسية عند الترحيل، لأن كل نوع يقابل وضعًا مختلفًا من modules.mode في css-loader:

النوعنطاق الأسماءما يقابله في css-loader
cssعام، من دون تحليل CSS Modulesmodules: false
css/globalالمحددات عامة، مع احترام :local()modules.mode: 'global'
css/moduleمحلي افتراضيًا، وتتيح :global() الخروج إلى النطاق العامmodules.mode: 'local'
css/autoيختار css/module لملفات *.module.css و*.modules.css، وإلا css/globalmodules.auto: true

القاعدة الافتراضية التي يضيفها webpack للنمط /\.css$/i هي css/auto. لذلك تصبح ملفات *.module.css وحدات CSS، بينما تبقى بقية الملفات عامة، وهو ما يطابق الإعداد الأكثر شيوعًا في css-loader من دون تخصيص إضافي.

CSS Modules

عند استخدام css/auto، سمِّ الملف *.module.css أو *.modules.css لتفعيل CSS Modules له:

src/button.module.css

.button {
  background: #0d6efd;
  color: white;
  border: 0;
  border-radius: 4px;
  padding: 8px 12px;
}

src/index.js

import * as styles from "./button.module.css";

const button = document.createElement("button");
button.className = styles.button;
button.textContent = "Click me";
document.body.appendChild(button);

يمكنك تخصيص سلوك CSS Modules عبر خيارات المحلل والمولد. راجع قسم جميع الخيارات مع أمثلة أدناه:

webpack.config.js

export default {
  experiments: {
    css: true,
  },
  module: {
    parser: {
      "css/auto": {
        namedExports: true,
      },
    },
    generator: {
      "css/auto": {
        exportsConvention: "camel-case-only",
        localIdentName: "[uniqueName]-[id]-[local]",
      },
    },
  },
};

ميزات CSS Modules المدعومة

يدعم CSS Modules الأصلي ميزات التأليف نفسها الموجودة في css-loader، لذا يمكن نقل معظم أوراق الأنماط من دون تعديل:

  • composes — تركيب صنف محلي من صنف آخر، بما في ذلك composes: foo from "./other.module.css". تكون القيمة المصدّرة قائمة أسماء الأصناف مفصولة بمسافات.
  • @value — تعريف قيم قابلة لإعادة الاستخدام واستيرادها، مثل @value primary: #1f6feb; و@value primary from "./vars.module.css".
  • :export — تصدير أزواج مفاتيح وقيم مخصصة إلى JavaScript.
  • :local() و:global() — تبديل نطاق الأسماء داخل أي نوع من الوحدات.
/* button.module.css */
@value brand: #1f6feb;

.base {
  padding: 8px 12px;
}
.primary {
  composes: base;
  background: brand;
}
:export {
  brandColor: brand;
}

أوضاع الإخراج (exportType)

يمكن إخراج وحدة CSS واحدة بأربع طرائق. يحدد خيار المحلل exportType الطريقة المستخدمة، وكل واحدة منها تحل محل جزء مختلف من سلسلة الأدوات التقليدية:

exportTypeالسلوكيحل محل
"link" (الافتراضي)استخراج ملف .css وتحميله عبر <link>mini-css-extract-plugin
"style"حقن عنصر <style> من شيفرة runtimestyle-loader
"text"تصدير CSS كسلسلة نصيةcss-loader مع exportType: 'string'
"css-style-sheet"تصدير كائن CSSStyleSheet قابل للإنشاءcss-loader مع exportType: 'css-style-sheet'

يمكنك ضبطه لجميع الملفات التابعة لنوع وحدة معين:

export default {
  experiments: { css: true },
  module: {
    parser: {
      "css/auto": {
        exportType: "style",
      },
    },
  },
};

أو ضمن قاعدة تطبق على مجموعة فرعية من الملفات:

export default {
  experiments: { css: true },
  module: {
    rules: [
      {
        test: /\.css$/i,
        type: "css/auto",
        parser: { exportType: "style" },
      },
    ],
  },
};

دليل الترحيل

نظرة سريعة

الإعداد التقليديالبديل الأصلي
mini-css-extract-plugin (MiniCssExtractPlugin.loader)الاستخراج المدمج (القيمة الافتراضية exportType: "link")
MiniCssExtractPlugin وخيارا filename وchunkFilenameoutput.cssFilename وoutput.cssChunkFilename
style-loaderexportType: "style"
css-loaderتحليل CSS المدمج، ولا حاجة إلى loader
css-loader وخيارا url وimportmodule.parser.css.url وimport، وكلاهما true افتراضيًا
اكتشاف css-loader التلقائي لـmodulesنوع الوحدة css/auto
css-loader وخيار modules.modeالنوعان css/module وcss/global مع pure
css-loader وخيار modules.localIdentNameخيار المولد localIdentName
css-loader وخيار modules.exportLocalsConventionخيار المولد exportsConvention
css-loader وخيار modules.namedExportmodule.parser.css.namedExports، وقيمته الافتراضية true
css-loader وخيار modules.exportOnlyLocalsخيار المولد exportsOnly
css-loader وخيار esModuleخيار المولد esModule، وقيمته الافتراضية true
css-loader مع exportType: 'string' أو 'css-style-sheet'exportType: "text" أو"css-style-sheet"

انقل loader واحدًا في كل خطوة. رُتبت الأقسام التالية بحيث يبقى البناء سليمًا في أثناء الترحيل.

1. ابدأ من إعداد تقليدي

webpack.config.js

import MiniCssExtractPlugin from "mini-css-extract-plugin";

export default {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
  plugins: [new MiniCssExtractPlugin()],
};

2. فعّل CSS الأصلي

webpack.config.js

export default {
  experiments: {
    css: true,
  },
};

تتولى الآن القاعدة المدمجة /\.css$/icss/auto معالجة استيرادات .css. احذف القاعدة والملحق المخصصين بعد التأكد في الأقسام التالية من وجود بديل لكل خيار تعتمد عليه.

3. استبدل mini-css-extract-plugin

يستخرج CSS الأصلي أوراق الأنماط ويضيف إليها تجزئات المحتوى افتراضيًا (exportType: "link")، لذلك لم تعد بحاجة إلى الملحق أو loader الخاص به:

webpack.config.js

-import MiniCssExtractPlugin from "mini-css-extract-plugin";
-
 export default {
+  experiments: {
+    css: true,
+  },
-  module: {
-    rules: [
-      {
-        test: /\.css$/i,
-        use: [MiniCssExtractPlugin.loader, "css-loader"],
-      },
-    ],
-  },
-  plugins: [new MiniCssExtractPlugin()],
 };

انقل بقية خيارات الملحق إلى البدائل التالية:

خيار mini-css-extract-pluginالبديل الأصلي
filenameoutput.cssFilename
chunkFilenameoutput.cssChunkFilename
خيار loader المسمى publicPathoutput.publicPath
خيار loader المسمى esModuleخيار المولد esModule، وافتراضيًا true
ignoreOrderلا يوجد؛ CSS الأصلي لا يصدر تحذيرات تعارض ترتيب

webpack.config.js

export default {
  experiments: { css: true },
  output: {
    cssFilename: "[name].[contenthash].css",
    cssChunkFilename: "[id].[contenthash].css",
  },
};

4. استبدل css-loader

لمعظم خيارات css-loader مقابل أصلي ضمن module.parser.css وmodule.generator.css. وتطابق القيم الافتراضية الشائعة، مثل تفعيل url وimport وnamedExports، إعداد css-loader المعتاد؛ لذلك لا تحتاج مشاريع كثيرة إلى أي تخصيص للمحلل.

خيار css-loaderالبديل الأصلي
urlmodule.parser.css.url، وقيمته الافتراضية true
importmodule.parser.css.import، وقيمته الافتراضية true
importLoadersلا يوجد؛ تطبق loaders الموجودة في السلسلة تلقائيًا على الملفات المستوردة عبر @import
sourceMapيتحكم به devtool، ويدعم قيمة css خاصة بكل نوع
esModulemodule.generator.css.esModule، وقيمته الافتراضية true
exportType: 'string'خيار المحلل exportType: "text"
exportType: 'css-style-sheet'خيار المحلل exportType: "css-style-sheet"
modules مع الاكتشاف التلقائينوع الوحدة المدمج css/auto
modules.mode: 'local'النوع css/module
modules.mode: 'global'النوع css/global
modules.mode: 'pure'خيار المحلل pure: true
modules.localIdentNameخيار المولد localIdentName
modules.exportLocalsConventionخيار المولد exportsConvention
modules.namedExportخيار المحلل namedExports، وقيمته الافتراضية true
modules.exportOnlyLocalsخيار المولد exportsOnly
modules.localIdentHashSaltخيار المولد localIdentHashSalt
modules.localIdentHashFunctionخيار المولد localIdentHashFunction

على سبيل المثال، إعداد CSS Modules التالي في css-loader:

export default {
  module: {
    rules: [
      {
        test: /\.module\.css$/i,
        use: [
          {
            loader: "css-loader",
            options: {
              modules: {
                localIdentName: "[local]-[hash:base64:6]",
                exportLocalsConvention: "camel-case-only",
                namedExport: true,
              },
            },
          },
        ],
      },
    ],
  },
};

يصبح:

webpack.config.js

export default {
  experiments: { css: true },
  module: {
    parser: {
      "css/auto": {
        namedExports: true,
      },
    },
    generator: {
      "css/auto": {
        localIdentName: "[local]-[hash:base64:6]",
        exportsConvention: "camel-case-only",
      },
    },
  },
};

تختلف بعض خيارات css-loader في طريقة نقلها:

  • getLocalIdent — يستخدم CSS الأصلي قالب localIdentName لتوليد الأسماء بدل دالة مستقلة، ويمكن لهذا القالب نفسه أن يكون دالة.
  • getJSON — تصدّر وحدة CSS خريطة أسماء الأصناف، ويمكن قراءتها من مخطط الوحدات في عملية التصريف. لذلك يستطيع ملحق صغير حفظها في JSON عندما يحتاج إطار العمل إلى ملف فعلي. وفي التصيير من جهة الخادم لا تحتاج إليها غالبًا؛ راجع التصيير من جهة الخادم.
  • لا يوجد بديل أصلي لـlocalIdentRegExp أو دوال التصفية الخاصة بـurl وimport. أبقِ css-loader للملفات المتأثرة، أو استبعد طلبات معينة عبر IgnorePlugin.

5. استبدل style-loader

إذا كنت تستخدم style-loader لحقن الأنماط وقت التشغيل بدل استخراج ملف، فاضبط exportType: "style":

webpack.config.js

export default {
  experiments: { css: true },
  module: {
    parser: {
      "css/auto": {
        exportType: "style",
      },
    },
  },
};

يحقن هذا الإعداد عنصر <style> من شيفرة runtime في webpack، ويغطي الاستخدام الافتراضي لـstyle-loader مع injectType: "styleTag". ويمكنك قصره على قاعدة واحدة إذا أردت حقن بعض الملفات مع استمرار استخراج البقية:

export default {
  experiments: { css: true },
  module: {
    rules: [
      {
        test: /\.inline\.css$/i,
        type: "css/auto",
        parser: { exportType: "style" },
      },
    ],
  },
};

ملاحظات حول خيارات style-loader: يقابل injectType: "linkTag" القيمة الافتراضية exportType: "link" التي تستخرج ملف CSS. ولا توجد بدائل أصلية للخيارات attributes وinsert وstyleTagTransform؛ أبقِ style-loader إذا كنت تعتمد عليها.

6. واصل استخدام المعالجات المسبقة (Sass وLess وPostCSS)

يستبدل CSS الأصلي loaders الخاصة بـCSS، لا loaders الخاصة بالمعالجات المسبقة. أبقِ loader المعالج ضمن use واضبط type في القاعدة على css/auto كي يتعامل webpack مع ناتج loader بوصفه CSS:

webpack.config.js

export default {
  experiments: { css: true },
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: ["postcss-loader", "sass-loader"],
        type: "css/auto",
      },
    ],
  },
};

يحوّل sass-loader المصدر إلى CSS، ثم يعالجه postcss-loader، وبعد ذلك يتولى CSS الأصلي الاستخراج وurl() وCSS Modules. وينطبق النمط نفسه على less-loader وstylus-loader وما شابههما.

7. التصيير من جهة الخادم (node وweb)

في تطبيقات SSR، تُنشئ عادةً حزمتين: حزمة web للمتصفح وحزمة node للخادم. ويجب أن تتطابق أسماء أصناف CSS Modules حتى يُرطّب المتصفح الصفحة المصيّرة على الخادم من دون اختلافات. كان getJSON في css-loader يُستخدم غالبًا لمزامنة هذه الأسماء؛ أما مع CSS الأصلي، فيمكنك الاستغناء عن هذه الخطوة بجعل localIdentName حتميًا في الهدفين.

استخدم قالبًا يعتمد على المسار، من دون تجزئة شاملة لعملية التصريف، كي ينتج اسم الصنف نفسه في كل هدف:

webpack.config.js

const common = {
  experiments: { css: true },
  module: {
    rules: [
      {
        test: /\.module\.css$/i,
        type: "css/module",
        generator: {
          // يبقى `[file]__[local]` ثابتًا بين الأهداف، فلا حاجة إلى مزامنة getJSON.
          localIdentName: "[file]__[local]",
        },
      },
    ],
  },
};

export default [
  { ...common, name: "web", target: "web" },
  { ...common, name: "node", target: "node" },
];

عند استخدام الهدف node، تكون القيمة الافتراضية لـexportsOnly في مولد CSS هي true. لذلك تصدّر حزمة الخادم خريطة أسماء الأصناف فقط، ولا تُخرج ورقة أنماط، وهو المطلوب في SSR. أما حزمة المتصفح فتواصل استخراج CSS الفعلي. وإذا كنت تفضل تخصيصًا واحدًا، فإن target: ["web", "node"] ينشئ حزمة عامة تعمل في البيئتين.

8. أبقِ الاستيرادات كما هي وتحقق من النتيجة

لا تتغير استيرادات JavaScript:

import "./styles.css";
import * as styles from "./button.module.css";

ثم تحقق مما يلي:

  • تُطبق الأنماط بصورة صحيحة في بيئة التطوير.
  • تُخرج ملفات .css المستخرجة في بناء الإنتاج.
  • تتطابق صادرات CSS Modules مع طريقة استخدام مشروعك لها.

جميع الخيارات مع أمثلة

اضبط الخيارات لكل نوع وحدة ضمن module.parser وmodule.generator. المفاتيح هي css وcss/auto وcss/global وcss/module. تستخدم الأمثلة التالية css/auto لأنه النوع المستخدم في القاعدة الافتراضية.

خيارات المحلل

القيمة الافتراضية لجميع خيارات المحلل المنطقية التالية هي true.

الخيارالنوعالقيمة الافتراضيةالوصف
importbooleantrueمعالجة قواعد @import.
urlbooleantrueمعالجة url() وimage-set() وsrc() وimage().
namedExportsbooleantrueتصدير الأسماء المحلية في CSS Modules كصادرات مسماة لوحدة ES.
exportType"link" | "style" | "text" | "css-style-sheet""link"كيفية إخراج CSS؛ راجع أوضاع الإخراج.
purebooleanfalseوضع نقي صارم؛ يجب أن يحتوي كل محدد على صنف أو معرّف محلي. خاص بـcss/module وcss/auto.
as"stylesheet" | "block-contents""stylesheet"تحليل المصدر كورقة أنماط كاملة أو كمحتوى كتلة.
animationbooleantrueإعادة تسمية أسماء @keyframes المحلية.
containerbooleantrueإعادة تسمية أسماء @container المحلية.
customIdentsbooleantrueإعادة تسمية المعرّفات المخصصة.
dashedIdentsbooleantrueإعادة تسمية المعرّفات ذات الشرطات، مثل الخصائص المخصصة.
functionbooleantrueإعادة تسمية أسماء @function المحلية.
gridbooleantrueإعادة تسمية معرّفات خطوط الشبكة ومساحاتها.
export default {
  experiments: { css: true },
  module: {
    parser: {
      "css/auto": {
        import: true,
        url: true,
        namedExports: true,
        exportType: "link",
        pure: false,
        // أعد تسمية @keyframes فقط، واترك معرّفات @container والشبكة كما هي.
        animation: true,
        container: false,
        grid: false,
      },
    },
  },
};

خيارات المولد

الخيارالنوعالقيمة الافتراضيةالوصف
localIdentNamestring | function"[uniqueName]-[id]-[local]" في التطوير و"[fullhash]" في الإنتاجقالب أسماء الأصناف المحلية المولدة.
exportsConvention"as-is" | "camel-case" | "camel-case-only" | "dashes" | "dashes-only" | function"as-is"أسلوب تسمية الأسماء المحلية المصدّرة.
exportsOnlybooleantrue في الأهداف التي لا تملك document مثل node، وإلا falseتصدير الأسماء المحلية فقط من دون إخراج ورقة أنماط.
esModulebooleantrueاستخدام صياغة وحدات ES في JavaScript المولد.
localIdentHashFunctionstringoutput.hashFunctionدالة التجزئة المستخدمة في localIdentName.
localIdentHashDigeststring"base64url"ترميز تجزئة المعرّفات المحلية.
localIdentHashDigestLengthnumber6طول تجزئة المعرّفات المحلية.
localIdentHashSaltstringoutput.hashSaltالملح المستخدم في تجزئة المعرّفات المحلية.
export default {
  experiments: { css: true },
  module: {
    generator: {
      "css/auto": {
        localIdentName: "[uniqueName]-[id]-[local]",
        exportsConvention: "camel-case-only",
        esModule: true,
        exportsOnly: false,
        localIdentHashDigest: "base64url",
        localIdentHashDigestLength: 6,
      },
    },
  },
};

يقبل exportsConvention أيضًا دالة تعيد string أو string[]. وعند إعادة مصفوفة، يُصدّر الاسم المحلي تحت عدة أسماء بديلة، كما يفعل css-loader.

أمثلة شائعة

CSS Modules مع صادرات مسماة

src/app.module.css

.primary {
  color: #1f6feb;
}
.large-text {
  font-size: 2rem;
}

src/index.js

import { largeText, primary } from "./app.module.css";

document.body.classList.add(primary, largeText);

webpack.config.js

export default {
  experiments: { css: true },
  module: {
    generator: {
      "css/auto": {
        exportsConvention: "camel-case-only",
      },
    },
  },
};

استخراج ملفات CSS مجزأة للإنتاج

webpack.config.js

export default {
  mode: "production",
  experiments: { css: true },
  output: {
    cssFilename: "css/[name].[contenthash].css",
    cssChunkFilename: "css/[id].[contenthash].css",
  },
};

حقن عناصر <style> وقت التشغيل كما يفعل style-loader

webpack.config.js

export default {
  experiments: { css: true },
  module: {
    parser: {
      "css/auto": {
        exportType: "style",
      },
    },
  },
};

استيراد ورقة أنماط قابلة للإنشاء

src/index.js

import sheet from "./theme.css" with { type: "css" };

document.adoptedStyleSheets = [sheet];

يحوّل webpack تأكيد الاستيراد with { type: "css" } تلقائيًا إلى exportType: "css-style-sheet"، ويمنحك نسخة من CSSStyleSheet.

استيراد CSS كسلسلة نصية

webpack.config.js

export default {
  experiments: { css: true },
  module: {
    parser: {
      "css/auto": {
        exportType: "text",
      },
    },
  },
};

src/index.js

import css from "./styles.css";

const style = new CSSStyleSheet();
style.replaceSync(css);

استخدام الأنماط العامة والوحدات محدودة النطاق معًا

مع قاعدة css/auto الافتراضية، تكون ملفات *.module.css محدودة النطاق، وتبقى بقية الملفات عامة، من دون تخصيص إضافي:

import "./reset.css"; // عام
import * as card from "./card.module.css"; // محدود النطاق

الحالة التجريبية والقيود المعروفة

experiments.css ميزة تجريبية صراحةً؛ فعّلها باختيارك واختبرها بعناية قبل اعتمادها على نطاق واسع.

  • قد تتغير واجهات API والسلوك قبل أن تصبح الميزة افتراضية في webpack v6.
  • لا تملك بعض خيارات loaders بديلًا مباشرًا، ومنها localIdentRegExp ودوال التصفية في css-loader، والخيارات attributes وinsert وstyleTagTransform في style-loader. أبقِ loader للملفات التي تحتاج إلى هذه الخيارات. يقابل getLocalIdent صيغة الدالة في localIdentName، ويغطي قسم مطابقة أسماء الأصناف بين الأهداف استخدام getJSON وSSR.
  • لا يوجد بديل لـimportLoaders، لأن loaders الموجودة في السلسلة تطبق تلقائيًا على الملفات المستوردة عبر @import.
  • إذا كان مشروعك يعتمد على سلاسل loaders متقدمة، فتحقق من كل جزء قبل الانتقال الكامل.
·تعديل هذه الصفحة

2 مساهمون

phoekersonarabpolice