Experiments

التجارب

boolean: false

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

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

  • asyncWebAssembly: يدعم WebAssembly الجديد وفق المواصفة المحدَّثة، فيجعل وحدة WebAssembly وحدةً غير متزامنة. وهو مُفعَّل افتراضياً حين يُضبط experiments.futureDefaults على true.
  • 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

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

  • دعم 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
  • الافتراضي: false

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.

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. عند تفعيل هذا flag، يترجم webpack ملفات .ts و.cts و.mts مباشرة، وكذلك data URIs المطابقة مثل data:text/typescript وdata:application/typescript، بدون أي loader خارجي. داخليًا، يستدعي webpack دالة Node.js المدمجة module.stripTypeScriptTypes.

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

تفعيل هذا flag يضبط أيضًا إعدادات افتراضية مناسبة: rules افتراضية لـ .ts و.cts و.mts، وإضافة .ts إلى extension resolution قبل .js، وضبط extensionAlias بحيث يحاول import "./foo.js" أيضًا استخدام ./foo.ts، وكذلك تحويل .cjs / .mjs إلى .cts / .mts، ودعم tsconfig.json resolution، وإضافة مفتاح conditional exports باسم "typescript" حتى تستطيع packages داخل monorepo نشر مصادر .ts عبر package.json#exports.

لإجراء type checking، استخدم هذا flag مع tsc --noEmit أو fork-ts-checker-webpack-plugin. أما عند استخدام JSX أو صياغات TypeScript غير قابلة للإزالة فقط، فاستمر في استخدام ts-loader أو swc-loader.

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

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

1 مساهم

RlxChap2