Experiments

التجارب

boolean: false

أُدخل الخيار experiments في webpack 5 ليُتيح للمستخدمين تفعيل الميزات التجريبية وتجربتها.

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

  • asyncWebAssembly: يدعم WebAssembly الحديث وفق المواصفة المحدَّثة، ويعامل وحدة WebAssembly بوصفها وحدة غير متزامنة. بدءًا من webpack 5.109.0، تكون قيمته الافتراضية 'auto'، ما يفعّل الدعم المدمج ما لم يكن هناك loader مسجل لملفات WebAssembly.
  • backCompat
  • buildHttp
  • cacheUnaffected
  • css
  • deferImport
  • futureDefaults
  • html
  • lazyCompilation
  • outputModule
  • typescript
  • sourceImport
  • syncWebAssembly: يدعم WebAssembly القديم كما في webpack 4.
  • layers: يُفعِّل طبقات الوحدات والـ chunks، أُزيل ويعمل بلا خيارات إضافية منذ 5.102.0.
  • topLevelAwait: يُحوِّل الوحدة إلى وحدة async حين يُستعمَل await على المستوى الأعلى. ابتداءً من webpack 5.83.0 (أمّا في الإصدارات السابقة فيمكنك تفعيله بضبط experiments.topLevelAwait على true)، صارت هذه الميزة مُفعَّلة افتراضياً، وأُزيلت وصارت تعمل بلا خيارات إضافية منذ 5.102.0.

webpack.config.js

export default {
  // ...
  experiments: {
    asyncWebAssembly: true,
    buildHttp: true,
    lazyCompilation: true,
    outputModule: true,
    sourceImport: true,
    syncWebAssembly: true,
    topLevelAwait: true,
  },
};

experiments.backCompat

فعِّل طبقة التوافق العكسي مع تحذيرات الإهمال (deprecation warnings) لكثير من واجهات webpack 4 البرمجية.

  • النوع: boolean
export default {
  // ...
  experiments: {
    backCompat: true,
  },
};

experiments.buildHttp

حين يُفعَّل هذا الخيار، يستطيع webpack بناء الموارد البعيدة التي تبدأ بـ http(s):.

  • النوع:

    • (string | RegExp | ((uri: string) => boolean))[]

      اختصارٌ لـ experiments.buildHttp.allowedUris.

    • HttpUriOptions

      {
        allowedUris: (string|RegExp|(uri: string) => boolean)[],
        cacheLocation?: false | string,
        frozen?: boolean,
        lockfileLocation?: string,
        upgrade?: boolean
      }
  • متاح: 5.49.0+

  • مثال

    webpack.config.js

    export default {
      // ...
      experiments: {
        buildHttp: true,
      },
    };
    // src/index.js
    import pMap1 from "https://cdn.skypack.dev/p-map";
    
    // مع تفعيل `buildHttp`، سيبني webpack pMap1 كأنّها وحدة محلية اعتيادية
    console.log(pMap1);

experiments.buildHttp.allowedUris

قائمة بالعناوين المسموح بها (URIs).

  • النوع: (string|RegExp|(uri: string) => boolean)[]

  • مثال

    webpack.config.js

    export default {
      // ...
      experiments: {
        buildHttp: {
          allowedUris: [
            "http://localhost:9990/",
            "https://raw.githubusercontent.com/",
          ],
        },
      },
    };

experiments.buildHttp.cacheLocation

حدِّد موقع التخزين المؤقَّت للموارد البعيدة.

  • النوع

    • string
    • false
  • مثال

    webpack.config.js

    export default {
      // ...
      experiments: {
        buildHttp: {
          cacheLocation: false,
        },
      },
    };

افتراضياً يستعمل webpack <compiler-name.>webpack.lock.data/ للتخزين المؤقَّت، غير أنّ بإمكانك تعطيله بضبط قيمته على false.

لاحظ أنّه ينبغي إيداع الملفّات الموجودة تحت experiments.buildHttp.cacheLocation في نظام التحكّم بالإصدار، إذ لن يجري أيّ طلب شبكي أثناء بناء production.

experiments.buildHttp.frozen

جمِّد الموارد البعيدة وملفّ القفل (lockfile). أيّ تعديل على lockfile أو على محتوى المورد سيُفضي إلى خطأ.

  • النوع: boolean

experiments.buildHttp.lockfileLocation

حدِّد موقع تخزين lockfile.

  • النوع: string

افتراضياً يُولِّد webpack ملفّ <compiler-name.>webpack.lock. تأكّد من إيداعه في نظام التحكّم بالإصدار. وأثناء بناء production، سيبني webpack تلك الوحدات التي تبدأ بـ http(s): انطلاقاً من lockfile ومن الذاكرة المؤقَّتة الموجودة في experiments.buildHttp.cacheLocation.

experiments.buildHttp.proxy

حدِّد خادوم البروكسي المستعمَل لجلب الموارد البعيدة.

  • النوع: string

افتراضياً، سيستنتج webpack خادوم البروكسي من متغيّر البيئة http_proxy (لا يميِّز بين الحالة الصغيرة والكبيرة). كما تستطيع تحديده صراحةً عبر الخيار proxy.

experiments.buildHttp.upgrade

اكتشف التغيّرات في الموارد البعيدة وحدِّثها تلقائياً.

  • النوع: boolean

experiments.css

يُفعِّل دعم CSS الأصلي. لاحظ أنّها ميزة تجريبية لا تزال قيد التطوير، وستُفعَّل افتراضياً في webpack v6، لكن بإمكانك تتبّع تقدّمها على GitHub.

  • النوع: boolean | 'auto'
  • القيمة الافتراضية: 'auto' 5.109.0+

بدءًا من webpack 5.109.0، تكون قيمة الخيار الافتراضية 'auto': يُفعَّل دعم CSS المدمج ما لم توجد قاعدة في module.rules تحتوي على loader أو نوع وحدة صريح يطابق ملفات .css أو .module.css. وبهذا تواصل إعدادات css-loader وmini-css-extract-plugin الحالية عملها من دون تعديل. استخدم true لفرض الدعم الأصلي، أو false لتعطيله تمامًا. عند تفعيل experiments.futureDefaults، تُحسم القيمة إلى true.

الميزات التجريبية:

  • دعم CSS Modules: سيُولِّد webpack اسماً فريداً لكلّ صنف CSS. استعمل الامتداد .module.css لتفعيل CSS Modules.

    5.103.0+

    يدعم webpack بشكل أصلي خاصية composes الخاصة بـ CSS Modules، فيسمح لك بتركيب الأصناف من الملفّ نفسه، أو من وحدات CSS أخرى، أو من أصناف عامة (global):

    /* styles.module.css */
    .base {
      color: blue;
    }
    
    .button {
      composes: base;
      padding: 10px;
    }
    
    .primary {
      composes: button;
      background: blue;
    }
    
    /* تركيب من وحدة CSS أخرى */
    .composed {
      composes: className from "./other.module.css";
    }
    
    /* تركيب من أصناف عامة */
    .globalComposed {
      composes: global-class from global;
    }
  • 5.87.0+ تحليل الحقول الخاصّة بـ style في ملفّات package.json: سيبحث webpack عن حقل style في ملفّات package.json ويستعمله إن وُجد للاستيراد داخل ملفّات CSS.

    فمثلاً، إن أضفت @import 'bootstrap'; إلى ملفّ CSS لديك، فسيبحث webpack عن bootstrap في node_modules ويستعمل حقل style من package.json هناك. وإن لم يجد حقل style، فسيستعمل حقل main بدلاً منه حفاظاً على التوافق العكسي.

  • Content hash لملفّات CSS: سيُولِّد webpack content hash لملفّات CSS ويستعمله في اسم الملفّ، وهذا مفيد للتخزين المؤقَّت طويل الأمد.

  • استخراج CSS: سيستخرج webpack الـ CSS إلى ملفّ منفصل. وتُغني هذه الإمكانية عن الحاجة إلى mini-css-extract-plugin و css-loader، إذ أنّها توفِّر دعماً أصلياً.

  • استيرادات CSS: سيُضمِّن webpack استيرادات CSS داخل ملفّ CSS المُولَّد.

  • إعادة التحميل الساخن (HMR): يدعم webpack الـ HMR لملفّات CSS، أي أنّ التغييرات في ملفّات CSS ستظهر في المتصفّح من دون إعادة تحميل كاملة للصفحة.

  • 5.107.0+ تحسين scope hoisting، أو module concatenation، لـ CSS Modules. حين يُفعَّل optimization.concatenateModules، فإنّ وحدات CSS التي يكون exportType لها text أو css-style-sheet أو style أو link تُدمَج في نسخة واحدة من الوحدة بدلاً من إبقائها نسخاً منفصلة عند الـ runtime. وهذا يُقلِّل الـ overhead ويُنتج مخرَجات أصغر للحزم الثقيلة بـ CSS.

  • 5.107.0+ يمكن استعمال معرّفات @value بوصفها مسارَ معامل لـ @import وداخل مراجع url()، حتى يُعرَّف المسار أو الـ asset المشترك مرّة واحدة ويُعاد استعماله عبر عدّة أوراق أنماط. وتُقبل الصيغة المُغلَّفة بعلامتي اقتباس ("./x", './x') والصيغة المُجرَّدة (./x)، وتُحلّ كلتاهما عبر مسار الـ assets الاعتيادي في webpack.

    @value path: "./other.module.css";
    @import path;
    
    @value bg: "./image.png";
    
    .a {
      background: url(bg);
    }

experiments.cacheUnaffected

يُفعِّل تخزيناً مؤقَّتاً إضافياً في الذاكرة (in-memory) للوحدات التي لم تتغيّر، والتي لا تُشير إلا إلى وحدات لم تتغيّر هي الأخرى.

  • النوع: boolean

القيمة الافتراضية مأخوذة من قيمة futureDefaults.

experiments.deferImport

فعِّل دعم اقتراح tc39 اقتراح import defer. وهو يتيح تأجيل تقييم الوحدة إلى حين أوّل استعمال لها. وهذا مفيد لتأجيل تنفيذ الشيفرة بشكل متزامن حين لا يكون استعمال import() ممكناً بسبب طبيعته غير المتزامنة.

  • النوع: boolean

تستلزم هذه الميزة أن تدعم بيئة الـ runtime Proxy (ES6).

يُفعِّل الصياغات الآتية:

import defer * as module from "module-name";
import * as module2 from /* webpackDefer: true */ "module-name2";

// أو باستعمال الاستيراد الديناميكي
import.defer("module-name3");
import(/* webpackDefer: true */ "module-name4");

export function f() {
  // module-name تُقيَّم بشكل متزامن، ثمّ تُستدعى عليها doSomething().
  module.doSomething();
}

قيود التعليقات السحرية (/* webpackDefer: true */)

يُستحسَن وضع التعليق السحري بعد الكلمة المفتاحية from. قد تعمل المواضع الأخرى، غير أنّها لم تُختبر.

ووضع التعليق السحري بعد الكلمة المفتاحية import غير متوافق مع filesystem cache.

experiments.sourceImport

5.106.0+

فعِّل دعم اقتراح tc39 Source Phase Imports.

يُقدِّم هذا الاقتراح طريقة لاستيراد وحدةٍ في مرحلة المصدر بدلاً من تقييمها فوراً. وفي webpack، هذا الدعم التجريبي مُطبَّق حالياً على وحدات WebAssembly: تحصل أوّلاً على WebAssembly.Module مُصرَّفة، ثمّ تُنشئ منها instance لاحقاً مع imports خاصّة بك. أمّا دعم استيرادات المصدر في JavaScript فمخطَّط له في إصدار قادم.

  • النوع: boolean

فعِّله إلى جانب asyncWebAssembly:

// webpack.config.js
export default {
  // ...
  experiments: {
    asyncWebAssembly: true,
    sourceImport: true,
  },
};

ثمّ استعمل صياغة source-phase الساكنة أو الديناميكية مع استيراد .wasm:

// الصيغة الساكنة
import source wasmModule from "./module.wasm";

// الصيغة الديناميكية
const wasmModule2 = await import.source("./module.wasm");

const instance = await WebAssembly.instantiate(wasmModule);

ثمّة مثال كامل في مستودع webpack: examples/wasm-simple-source-phase.

import /* webpackDefer: true */ * as ns from "..."; // معلوم أنّه لا يعمل
import * as ns from /* webpackDefer: true */ "..."; // الموصى به

تأكّد من أنّ الـ loaders لديك لا تحذف التعليق السحري.

ويمكن ضبط TypeScript و Babel و SWC و Flow.js للحفاظ على التعليق السحري.

أمّا Esbuild فهو غير متوافق مع هذه الميزة (انظر evanw/esbuild#1439 و evanw/esbuild#309)، وإن كان قد يدعمها في المستقبل.

5.105.0+

import.defer() صار مدعوماً الآن لـ ContextModule (حين يكون مسار الاستيراد تعبيراً ديناميكياً). انظر دليل التحميل الكسول للأمثلة.

experiments.futureDefaults

استعمل القيم الافتراضية لإصدار webpack الرئيسي القادم، واعرض تحذيرات في أيّ موضع قد يكون إشكالياً.

webpack.config.js

export default {
  // ...
  experiments: {
    futureDefaults: true,
  },
};

experiments.html

5.107.0+

يفعّل الدعم الأصلي لـ HTML modules. عند استيراد ملف .html من JavaScript، تمر مراجع الوسوم داخل الملف عبر pipeline العادية في webpack، وهذا يستبدل الدور الذي كان يؤديه html-loader لسنوات. يسجل هذا flag نوع module المسمى html داخل NormalModuleFactory ويفعّل سلوكيات HTML الموضحة أدناه.

  • النوع: boolean | 'auto'
  • القيمة الافتراضية: false، وأصبحت 'auto' منذ webpack 5.109.0

بدءًا من webpack 5.109.0، تكون قيمة الخيار الافتراضية 'auto': يُفعّل دعم HTML المدمج ما لم توجد قاعدة في module.rules تحتوي على loader أو نوع وحدة صريح يطابق ملفات .html. وبهذا تستمر إعدادات html-loader الحالية في العمل من دون تعديل. وعند تفعيل experiments.futureDefaults، تُحسم القيمة إلى true.

webpack.config.js

export default {
  // ...
  experiments: {
    html: true,
  },
};

بعد ذلك، استورد ملف HTML من JavaScript. يكون default export هو HTML المعالج كنص، مع حل كل مراجع assets عبر webpack:

// src/index.js
import page from "./page.html";

document.documentElement.innerHTML = page;

Inline <style> tags

يتم تمرير كتل <style> المضمنة داخل HTML module عبر CSS pipeline في webpack كـ CSS modules افتراضية باستخدام exportType: "text". تُحل مراجع url() و@import نسبة إلى ملف HTML، ثم يُكتب نص CSS المعالج مرة أخرى داخل وسم <style> الأصلي في نص HTML الناتج.

<!-- src/page.html -->
<!doctype html>
<html>
  <head>
    <style>
      @import "./reset.css";

      body {
        background: url("./bg.png");
      }
    </style>
  </head>
  <body>
    ...
  </body>
</html>

تتم معالجة <style type="text/css"> و<style> الذي لا يحتوي على الخاصية type. أما أي وسم يحمل type غير خاص بـ CSS فيمر بدون تغيير.

Inline <script> tags

يتم تمرير محتوى وسوم <script> المضمنة عبر entry pipeline نفسها المستخدمة مع <script src>. يصبح كل محتوى داخل <script> عبارة عن webpack entry مستقل: scripts الكلاسيكية المضمنة تُحزّم كـ CommonJS، أما محتوى <script type="module"> فيُحزّم كـ ESM. في HTML الناتج، يُعاد كتابة الوسم إلى <script src="…"> يشير إلى chunk المولّد، مع تفريغ المحتوى الداخلي.

<!-- src/page.html -->
<!doctype html>
<html>
  <body>
    <script type="module">
      import { greet } from "./lib.js";
      greet("world");
    </script>

    <script>
      console.log("classic inline script");
    </script>
  </body>
</html>

تنطبق هنا السلوكيات نفسها الخاصة بـ <script src> الخارجي:

  • عند تفعيل output.module، تتم ترقية وسوم <script> الكلاسيكية المضمنة تلقائيًا إلى type="module"، مثل الترقية التلقائية في <script src>.
  • يعمل webpackIgnore أيضًا مع وسوم <script> المضمنة، ويترك المحتوى الأصلي كما هو.
  • قيم type غير الخاصة بـ JS، مثل application/ld+json وimportmap، تمر بدون تغيير.

<script src> and <link rel="modulepreload">

تصبح مراجع <script src> و<link rel="modulepreload"> داخل HTML module عبارة عن webpack entries حقيقية. ثم يُعاد كتابة URL الخاص بالـ chunk الناتج داخل نص HTML، لذلك تعمل أسماء الملفات التي تحتوي على hash بالطريقة نفسها التي تعمل بها مع JavaScript imports.

<!-- src/page.html -->
<!doctype html>
<html>
  <head>
    <link rel="modulepreload" href="./preloaded.js" />
  </head>
  <body>
    <script src="./entry.js"></script>
    <script src="./second.js"></script>
  </body>
</html>

هناك بعض السلوكيات التي يجب الانتباه لها:

  • وسوم <script src> المتعددة في الصفحة نفسها تشارك runtime واحدًا. داخل كل مجموعة، سواء كانت classic أو type="module"، يحمل العنصر الرئيسي runtime وتعلن بقية العناصر dependOn عليه.
  • تبقى entries الخاصة بـ <link rel="modulepreload"> مستقلة ولا يتم استيرادها من scripts المجاورة، مما يحافظ على معنى "preload without execute".
  • عند تفعيل output.module، تتم ترقية وسوم <script src> الكلاسيكية تلقائيًا إلى <script type="module" src> حتى تُحمّل chunks الخاصة بـ ES modules بالوضع الصحيح.
  • أنواع scripts غير الخاصة بـ JS، مثل application/ld+json وimportmap وdata URIs، تمر بدون تغيير ولا تُحزّم كـ JS.

webpackIgnore magic comment

وضع تعليق HTML بالشكل <!-- webpackIgnore: true --> مباشرة قبل وسم معيّن يخبر webpack بتجاوز URL resolution لذلك الوسم في خصائص مثل src وhref وsrcset وما يشبهها. راجع الشرح الكامل ضمن magic comments.

HTML as the default entry

5.108.0+

When experiments.html is enabled, .html is added to the default resolve.extensions ahead of the JavaScript extensions, so a directory entry like entry: "./src" resolves ./src/index.html even when ./src/index.js also exists. This makes the build HTML-first, similar to Vite or Parcel.

export default {
  experiments: { html: true },
  entry: "./src", // resolves to ./src/index.html
};

When experiments.css is enabled, .css is likewise appended to the default extensions, so the default entry can fall back to ./src/index.css when no HTML or JS match is found. These extensions are only added when the respective experiment is on, so default builds are unchanged.

Hot Module Replacement

5.108.0+

HTML modules support Hot Module Replacement. No extra configuration is needed. It activates automatically when HMR is enabled (for example via devServer.hot).

For a page extracted to a real .html file, each hot update patches document.body.innerHTML and document.title in place instead of triggering a full reload. Changes to <head> beyond the <title> (a new <meta>, a swapped <link rel="icon">, …) cannot be safely DOM-patched, so the shim falls back to a full page reload.

HtmlModulesPlugin hooks

5.109.0+

Plugins can inject and transform the emitted HTML through webpack.html.HtmlModulesPlugin, which exposes the injectTags, transformTags, transformHtml and htmlEmitted compilation hooks. See HtmlModulesPlugin.getCompilationHooks in the API documentation.

experiments.lazyCompilation

صرِّف نقاط الدخول و import الديناميكية فقط حين تكون مستعملة. يمكن استعماله للويب أو لـ Node.js.

  • النوع

    • boolean

    • object

      {
        // عرِّف backend مخصَّصاً
        backend?: ((
          compiler: Compiler,
          callback: (err?: Error, api?: BackendApi) => void
        ) => void)
          | ((compiler: Compiler) => Promise<BackendApi>)
          | {
            /**
             * عميل مخصَّص.
             */
            client?: string;
      
            /**
             * حدِّد المنفذ الذي يستمع إليه الخادوم.
             */
            listen?: number | ListenOptions | ((server: Server) => void);
      
            /**
             * حدِّد البروتوكول الذي يستعمله العميل للاتصال بالخادوم.
             */
            protocol?: "http" | "https";
      
            /**
             * حدِّد طريقة إنشاء الخادوم الذي يُعالج طلبات EventSource.
             */
            server?: ServerOptionsImport | ServerOptionsHttps | (() => Server);
          },
        entries?: boolean,
        imports?: boolean,
        test?: string | RegExp | ((module: Module) => boolean)
      }
      • backend: خصِّص الـ backend.
      • entries: فعِّل التصريف الكسول لنقاط الدخول.
      • imports 5.20.0+: فعِّل التصريف الكسول للاستيرادات الديناميكية.
      • test 5.20.0+: حدِّد أيّ الوحدات المستوردة ينبغي تصريفها كسولياً.
  • متاح: 5.17.0+

  • مثال 1:

    export default {
      // …
      experiments: {
        lazyCompilation: true,
      },
    };
  • مثال 2:

    export default {
      // …
      experiments: {
        lazyCompilation: {
          // عطِّل التصريف الكسول للاستيرادات الديناميكية
          imports: false,
    
          // عطِّل التصريف الكسول لنقاط الدخول
          entries: false,
    
          // لا تُصرِّف moduleB كسولياً
          test: (module) => !/moduleB/.test(module.nameForCondition()),
        },
      },
    };

experiments.outputModule

boolean

حين يُفعَّل هذا الخيار، سيُخرج webpack صياغة وحدات ECMAScript كلّما كان ذلك ممكناً. فعلى سبيل المثال، يستعمل import() لتحميل الـ chunks، و ESM exports لكشف بيانات الـ chunk، وغير ذلك.

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

experiments.typescript

5.107.0+

يُفعّل دعم TypeScript الأصلي. عند تفعيل الراية، يصرّف webpack ملفات .ts و.cts و.mts مباشرةً، إضافةً إلى روابط البيانات المطابقة من نوعَي data:text/typescript وdata:application/typescript، من دون loader خارجي. ويستخدم داخليًا الدالة المدمجة في Node.js‏ module.stripTypeScriptTypes.

  • النوع: boolean | 'auto'
  • القيمة الافتراضية: false، وأصبحت 'auto' منذ webpack 5.109.0

بدءًا من webpack 5.109.0، تكون قيمة الخيار الافتراضية 'auto'. يُفعَّل دعم TypeScript المدمج عندما يوفر إصدار Node.js المستخدم module.stripTypeScriptTypes، أي 22.6 أو أحدث، ولا توجد قاعدة في module.rules تستخدم loader مثل ts-loader أوswc-loader لمطابقة ملفات .ts أو.mts أو.cts. وعند تفعيل experiments.futureDefaults، تُحسم القيمة إلى true.

export default {
  experiments: {
    typescript: true,
  },
  entry: "./src/index.ts",
};

يضيف تفعيل الراية أيضًا مجموعة قيم افتراضية مناسبة: قواعد افتراضية لملفات .ts و.cts و.mts، وإضافة .ts إلى قائمة الامتدادات التي يجري حلها قبل .js، وضبط extensionAlias كي يحاول الاستيراد import "./foo.js" تحميل ./foo.ts أيضًا، وبالمثل تحويل .cjs و.mjs إلى .cts و.mts. كما يفعّل حل tsconfig.json ومفتاح الصادرات الشرطية "typescript"، لتتمكن حزم monorepo من نشر مصادر .ts عبر package.json#exports.

للتحقق من الأنواع، استخدم الراية مع tsc --noEmit أوfork-ts-checker-webpack-plugin. أما JSX وصياغات TypeScript غير القابلة للمحو، فواصل استخدام ts-loader أوswc-loader.

يوفر مستودع webpack مثالين مرجعيين:

·تعديل هذه الصفحة
السابق ›
Stats
‹ التالي
InfrastructureLogging

1 مساهم

RlxChap2