ModuleFederationPlugin

يسمح ModuleFederationPlugin لعملية build أن توفّر modules لتطبيقات مستقلة أخرى، أو تستهلك modules منها، وقت التشغيل.

import webpack from "webpack";

const { ModuleFederationPlugin } = webpack.container;

export default {
  plugins: [
    new ModuleFederationPlugin({
      // أنواع الخيارات في TypeScript
      runtime: string | false,
    }),
  ],
};

الخيارات

runtime

ينشئ runtime chunk جديدًا بالاسم الذي تحدده.

webpack.config.js

import webpack from "webpack";

const { ModuleFederationPlugin } = webpack.container;

export default {
  plugins: [
    new ModuleFederationPlugin({
      runtime: "my-runtime-name",
    }),
  ],
};

مشاركة المكتبات

باستخدام المفتاح shared في الإعدادات، يمكنك تحديد المكتبات التي ستتم مشاركتها بين modules التابعة لـ Module Federation. اسم الحزمة هو نفسه الموجود في قسم dependencies داخل ملف package.json. لكن webpack، بشكل افتراضي، يشارك المستوى الجذري فقط من المكتبة.

import webpack from "webpack";

const { ModuleFederationPlugin } = webpack.container;

export default {
  plugins: [
    new ModuleFederationPlugin({
      // يضيف date-fns كـ shared module
      shared: ["date-fns"],
    }),
  ],
};

في تطبيقك، يمكن أن تكتب شيئًا مثل:

import { format } from "date-fns";

format(new Date(2014, 1, 11), "MM/dd/yyyy");

وسيشارك webpack مكتبة date-fns تلقائيًا بين كل modules التابعة لـ Module Federation التي تعرّف date-fns كمكتبة مشتركة.

لكن إذا أردت الوصول إلى ملف ليس في جذر الحزمة، مثل date-fns/locale/en-GB/index.js، فأضف / إلى اسم الحزمة داخل إعداد shared:

import webpack from "webpack";

const { ModuleFederationPlugin } = webpack.container;

export default {
  plugins: [
    new ModuleFederationPlugin({
      // يضيف date-fns كـ shared module
      // ستتم مشاركة كل ملفات الحزمة
      shared: ["date-fns/"],
    }),
  ],
};

صيغة / تسمح لك بالوصول إلى كل ملفات الحزمة. استخدمها فقط عند الحاجة، لأنها قد تؤثر في الأداء، خصوصًا في وضع development.

تحديد إصدارات الحزم

توجد ثلاث طرق لتحديد إصدارات المكتبات المشتركة.

صيغة Array

هذه الصيغة تسمح لك بمشاركة المكتبات باسم الحزمة فقط. هي مناسبة للتجارب السريعة، لكنها لا تكفي عادةً عند التوسع إلى بيئة production كبيرة، لأن مكتبات مثل react وreact-dom تحتاج شروطًا إضافية.

import webpack from "webpack";

const { ModuleFederationPlugin } = webpack.container;

export default {
  plugins: [
    new ModuleFederationPlugin({
      // يضيف lodash كـ shared module
      // يتم استنتاج الإصدار من package.json
      // لا يوجد فحص للإصدار المطلوب
      // لذلك سيستخدم دائمًا أعلى إصدار يجده
      shared: ["lodash"],
    }),
  ],
};
صيغة Object

هذه الصيغة تعطيك تحكمًا أكبر في كل مكتبة مشتركة؛ تضع اسم الحزمة كمفتاح، وتضع الإصدار بصيغة semver كقيمة.

export default {
  plugins: [
    new ModuleFederationPlugin({
      shared: {
        // يضيف lodash كـ shared module
        // يتم استنتاج الإصدار من package.json
        // سيستخدم أعلى إصدار من lodash يطابق >= 4.17 و < 5
        lodash: "^4.17.0",
      },
    }),
  ],
};
صيغة Object مع تلميحات المشاركة

هذه الصيغة تسمح لك بإضافة تلميحات لكل حزمة مشتركة. تضع اسم الحزمة كمفتاح، وتكون القيمة object يحتوي على تلميحات تغيّر سلوك المشاركة.

import { readFileSync } from "node:fs";

const deps = JSON.parse(
  readFileSync(new URL("./package.json", import.meta.url)),
).dependencies;

export default {
  plugins: [
    new ModuleFederationPlugin({
      shared: {
        // يضيف react كـ shared module
        react: {
          requiredVersion: deps.react,
          singleton: true,
        },
      },
    }),
  ],
};

تلميحات المشاركة

eager

boolean

هذا التلميح يجعل webpack يضمّن module المقدّم وfallback مباشرة بدل جلب المكتبة بطلب غير متزامن. بمعنى آخر، يتيح استخدام هذا shared module داخل initial chunk. انتبه أيضًا إلى أن كل modules المقدّمة وfallback ستُحمّل دائمًا عند تفعيل هذا التلميح.

import

false | string

الـ module المقدّم الذي يجب وضعه في shared scope. يعمل هذا module أيضًا كـ fallback إذا لم يُعثر على shared module داخل shared scope، أو إذا كان الإصدار غير صالح. القيمة الافتراضية لهذا التلميح هي اسم الخاصية نفسها.

packageName

string

اسم الحزمة المستخدم لمعرفة الإصدار المطلوب من ملف الوصف. تحتاجه فقط عندما لا يمكن تحديد اسم الحزمة تلقائيًا من request.

requiredVersion

false string

يحدد هذا الحقل الإصدار المطلوب من الحزمة. يقبل semantic versioning مثل "^1.2.3". ويمكنه أيضًا استخراج الإصدار إذا كان موجودًا ضمن URL، مثل: "git+ssh://git@github.com:foo/bar.git#v1.0.0".

shareKey

string

يُبحث عن shared module المطلوب تحت هذا المفتاح داخل shared scope.

shareScope

string

اسم shared scope.

singleton

boolean

هذا التلميح يسمح بوجود إصدار واحد فقط من shared module داخل shared scope، وهو معطّل افتراضيًا. بعض المكتبات تستخدم حالة داخلية عامة، مثل react وreact-dom، لذلك من المهم أن تعمل نسخة واحدة فقط من المكتبة في الوقت نفسه.

إذا وجدت عدة إصدارات من الاعتماد نفسه داخل shared scope، فسيُستخدم أعلى إصدار semantic.

strictVersion

boolean

هذا التلميح يجعل webpack يرفض shared module إذا كان الإصدار غير صالح. القيمة الافتراضية تكون true عندما يكون local fallback module متاحًا والـ shared module ليس singleton، وإلا تكون false. ولا يكون له تأثير إذا لم تحدد إصدارًا مطلوبًا. إذا لم يُعثر على الإصدار المطلوب، فسيتم رمي runtime error.

version

false | string

إصدار module المقدّم. يسمح لـ webpack باستبدال الإصدارات المطابقة الأقل، لكن لا يستبدل الإصدارات الأعلى.

افتراضيًا، يستخدم webpack الإصدار الموجود في ملف package.json الخاص بالاعتماد.

أمثلة إضافية

export default {
  plugins: [
    new ModuleFederationPlugin({
      // يضيف vue كـ shared module
      // يتم استنتاج الإصدار من package.json
      // سيستخدم دائمًا الإصدار المشترك، لكنه يطبع تحذيرًا إذا كان vue المشترك < 2.6.5 أو >= 3
      shared: {
        vue: {
          requiredVersion: "^2.6.5",
          singleton: true,
        },
      },
    }),
  ],
};
export default {
  plugins: [
    new ModuleFederationPlugin({
      // يضيف vue كـ shared module
      // لا يوجد إصدار محلي مقدّم
      // سيصدر تحذيرًا إذا كان vue المشترك < 2.6.5 أو >= 3
      shared: {
        vue: {
          import: false,
          requiredVersion: "^2.6.5",
        },
      },
    }),
  ],
};
export default {
  plugins: [
    new ModuleFederationPlugin({
      // يضيف vue كـ shared module
      // لا يوجد إصدار محلي مقدّم
      // سيرمي خطأ إذا كان vue المشترك < 2.6.5 أو >= 3
      shared: {
        vue: {
          import: false,
          requiredVersion: "^2.6.5",
          strictVersion: true,
        },
      },
    }),
  ],
};
export default {
  plugins: [
    new ModuleFederationPlugin({
      shared: {
        "my-vue": {
          // يمكن الإشارة إليه عبر import "my-vue"
          import: "vue", // ستُستخدم حزمة "vue" كـ module مقدّم وfallback
          shareKey: "shared-vue", // بهذا الاسم سيُوضع shared module داخل share scope
          shareScope: "default", // سيُستخدم share scope بهذا الاسم
          singleton: true, // يُسمح بإصدار واحد فقط من shared module
          strictVersion: true, // لا تستخدم الإصدار المشترك إذا كان غير صالح. يرمي Singleton أو modules بدون fallback خطأ، وإلا يُستخدم fallback
          version: "1.2.3", // إصدار shared module
          requiredVersion: "^1.0.0", // الإصدار المطلوب من shared module
        },
      },
    }),
  ],
};

قراءات إضافية

·تعديل هذه الصفحة
‹ التالي
NoEmitOnErrorsPlugin

1 مساهم

RlxChap2