Polyfill: ما هو، مبدأ العمل والمكتبات لمحاكاة API

المؤلف: IT Sectr نُشر: 2026-05-19 وقت القراءة: 9 دق

Polyfill هو كود يحاكي الوظائف المفقودة (API، طرق، كائنات) في البيئات التي لا تحتوي على تطبيق أصلي لها. يتيح Polyfill استخدام ميزات JavaScript أو CSS أو Web API الحديثة في المتصفحات القديمة وبيئات التشغيل. وفقًا لـ MDN Web Docs، تعتبر polyfills أداة رئيسية للتحسين التدريجي وضمان التوافق عبر المتصفحات.

النقاط الرئيسية

  • Polyfill هو محاكاة برمجية لواجهة برمجة تطبيقات (API) مفقودة في بيئة تشغيل لا تحتوي على هذه API
  • core-js هي المكتبة القياسية للـ polyfills لجافا سكريبت الحديث مع دعم جميع مقترحات المرحلة 4 (stage-4)
  • Polyfill.io هي خدمة توفر polyfills ديناميكيًا فقط لمتصفح المستخدم
  • التجميع (transpilation) مقابل polyfill: التجميع يحول الصياغة (arrow function → function)، polyfill يضيف طرقًا جديدة (Array.includes, Promise)
  • كشف الميزات (Feature detection) يتحقق من وجود تطبيق أصلي قبل تحميل polyfill لتجنب التعارضات

ما هو Polyfill؟

Polyfill هو جزء من الكود (عادة JavaScript) يطبق وظائف لا تدعمها بيئة التشغيل بشكل أصلي. صاغ المصطلح ريمي شارب في عام 2009 كلعبة كلمات: Polyfill مشابه لـ Polyfilla، وهي مادة حشو تملأ الشقوق في الجدار. يملأ Polyfill الفجوات بين المعيار ودعمه في متصفح أو بيئة تشغيل محددة.

Polyfill لا يعدل الكود الموجود — بل يوسع بيئة التشغيل. إذا كان المتصفح لا يدعم Array.prototype.includes، يضيف polyfill هذه الطريقة إلى النموذج الأولي Array قبل تنفيذ الكود الرئيسي. يمكن للـ polyfills محاكاة كائنات عامة جديدة (Promise، Map، Set، Symbol)، طرق ثابتة (Array.from، Object.assign) وطرق النماذج الأولية.

كشف الميزات (Feature detection) هو آلية إلزامية قبل تثبيت polyfill. بدلاً من التحقق من user-agent (أي متصفح)، يجب التحقق من وجود الطريقة: if (!Array.prototype.includes) { Array.prototype.includes = ... }. يضمن ذلك عدم استبدال polyfill للتطبيق الأصلي إذا كان موجودًا بالفعل. تجمع Google Analytics وخدمات أخرى بيانات دعم API للتحليل.

متى ظهرت الـ polyfills

ظهرت أول polyfills في عصر Internet Explorer 6–8 (2005–2009)، عندما اكتشف المطورون فجوة بين معايير W3C وتطبيقات المتصفحات. قدم المصطلح ريمي شارب في عام 2009 في BarCamp London. كان أول polyfill جماهيري هو html5shiv (2009) — مكتبة تضيف دعمًا لعلامات HTML5 (<section>، <article>، <nav>) في Internet Explorer.

مع ظهور ES6 (2015) ودورة التحديث السنوية لـ ECMAScript، زاد عدد polyfills المطلوبة. كل عام يضيف المعيار طرقًا جديدة (Array.includes، String.padStart، Object.fromEntries، Promise.allSettled) لا تدعمها المتصفحات القديمة. أصبح core-js، الذي بدأ كـ es6-shim في 2014، حلاً عالميًا. في عام 2026، يحتوي core-js على أكثر من 5000 وحدة polyfill لـ ES5–ES2025.

ما يمكن وما لا يمكن عمل polyfill له

الفئةيمكن عمل polyfillلا يمكن عمل polyfill
طرق النماذج الأوليةArray.includes, String.startsWith
كائنات عامةPromise, Map, Set, Symbol
طرق ثابتةObject.assign, Array.from
صياغة اللغةArrow functions, async/await, class
Web APIfetch, IntersectionObserverService Worker (يتطلب دعمًا أصليًا)

Polyfill مقابل التجميع: الاختلافات والتفاعل

التجميع (Transpilation) يحول الصياغة الجديدة إلى صياغة قديمة (const → var، () => {} → function() {}). Polyfill يضيف طرقًا وكائنات مفقودة (Promise، Array.includes). تكمل هاتان الآليتان بعضهما البعض: التجميع يجعل الكود متوافقًا نحويًا، وتضمن polyfills اكتمال API. Babel + core-js هو المزيج القياسي للدعم الكامل.

يحدد Babel @babel/preset-env مع خيار useBuiltIns أي polyfills مطلوبة بناءً على المتصفحات المستهدفة. useBuiltIns: "usage" يحلل أي API تُستخدم في الكود ويستورد فقط polyfills الضرورية من core-js. useBuiltIns: "entry" يستورد جميع polyfills للمتصفحات المستهدفة من خلال استيراد واحد core-js/stable.

مثال: polyfill لـ Array.prototype.includes

js
// التحقق من الوجود وإضافة polyfill
if (typeof Array.prototype.includes !== "function") {
  Object.defineProperty(Array.prototype, "includes", {
    value: function(searchElement, fromIndex) {
      if (this == null) {
        throw new TypeError("Array.prototype.includes called on null or undefined");
      }
      var arr = Object(this);
      var len = arr.length >>> 0;
      if (len === 0) { return false; }
      var start = fromIndex | 0;
      var k = Math.max(start >= 0 ? start : len + start, 0);

      while (k < len) {
        if (arr[k] === searchElement) { return true; }
        k++;
      }
      return false;
    },
    writable: true,
    configurable: true,
  });
}

// الاستخدام — الآن آمن في أي متصفح
const arr = [1, 2, 3, 4, 5];
console.log(arr.includes(3)); // true

Polyfill لـ Array.prototype.includes يتحقق مما إذا كانت الطريقة محددة في النموذج الأولي Array. إذا لم تكن كذلك، ينشئ الخاصية عبر Object.defineProperty مع الأعلام writable: true، configurable: true. يتبع التنفيذ مواصفات ES2016: التحقق من null/undefined، التحويل إلى كائن، التعامل مع fromIndex السالب. بعد إضافة polyfill، يعمل استدعاء arr.includes(3) في جميع المتصفحات، بما في ذلك Internet Explorer 11.

core-js: المكتبة القياسية للـ polyfills

core-js هي أشمل مكتبة polyfills لجافا سكريبت، تدعم جميع مقترحات TC39 المرحلة 4 (معيار ECMAScript). تتضمن core-js polyfills لـ Promise، Symbol، Map، Set، WeakMap، WeakSet، طرق Array، طرق String، طرق Object، طرق Number، طرق Math، Reflect، globalThis وجميع مقترحات المرحلة 4. الإصدار الحالي core-js 3.38+ يغطي ES5–ES2025.

تتكامل core-js مع Babel من خلال @babel/preset-env وخيار useBuiltIns. بدون هذا التكامل، كان على المطورين استيراد كل polyfill يدويًا: import "core-js/stable/array/includes". يضيف @babel/preset-env تلقائيًا الواردات الضرورية بناءً على المتصفحات المستهدفة من .browserslistrc. هذا يقلل حجم الحزمة — يتم تضمين polyfills الضرورية فقط.

مثال: polyfill لـ fetch

Fetch API هي واحدة من أكثر Web API شيوعًا لعمل polyfill لها. التطبيق الأصلي لـ fetch متاح في Chrome 42+ (2015)، Safari 10.1+ (2017)، Firefox 39+ (2015)، لكنه غائب في Internet Explorer و WebViews القديمة. يحاكي polyfill whatwg-fetch fetch عبر XMLHttpRequest. بديل — استخدام isomorphic-fetch (polyfill لـ Node.js والمتصفح) أو المكتبة العالمية axios التي لا تتطلب polyfills.

js
// تحميل polyfill fetch فقط للمتصفحات القديمة
if (typeof self.fetch !== "function") {
  import("whatwg-fetch").then(module => {
    self.fetch = module.fetch;
    console.log("fetch polyfill loaded");
  });
}

// استخدام fetch (يعمل مع كل من polyfill و API الأصلي)
async function loadData() {
  try {
    const response = await fetch("https://api.example.com/data");
    const json = await response.json();
    return json;
  } catch (error) {
    console.error("Failed to load:", error);
  }
}

الاستيراد الديناميكي لـ polyfill fetch عبر import() يضمن أن المتصفحات الحديثة لا تحمل كودًا غير ضروري. يتم تحميل polyfill بشكل غير متزامن ولا يعوق الخيط الرئيسي. بعد التحميل، يستبدل self.fetch التطبيق الأصلي أو يضيف المفقود. هذه تقنية تحسين تدريجي: المتصفحات الحديثة تحصل على كود أصلي فقط، القديمة تحصل على polyfill إضافي.

دمج core-js مع Babel

js
// babel.config.js — core-js + preset-env
module.exports = {
  presets: [
    ["@babel/preset-env", {
      useBuiltIns: "usage",
      corejs: {
        version: "3.38",
        proposals: true,
      },
      targets: {
        browsers: ["> 0.5%", "not dead", "not op_mini all"],
      },
    }],
  ],
};
none
# .browserslistrc — المتصفحات المستهدفة
> 0.5%
last 2 versions
not dead
not op_mini all
ie >= 11
not ios_saf < 12

useBuiltIns: "usage" يحلل الكود ويضيف فقط polyfills المستخدمة فعليًا. corejs.version يحدد إصدار core-js في المشروع. targets.browsers يحدد المستوى الأدنى للمتصفحات — كلما كانت المتصفحات المستهدفة أقدم، زادت polyfills المضمنة. يتم استخدام .browserslistrc ليس فقط بواسطة Babel ولكن أيضًا بواسطة Autoprefixer و PostCSS و Stylelint للاستهداف المتناسق.

Polyfill.io والتحميل الديناميكي للـ polyfills

Polyfill.io هي خدمة (ومكتبة بنفس الاسم) تحدد ديناميكيًا polyfills التي يحتاجها متصفح المستخدم وتعيد فقط تلك. يستخدم Polyfill.io رأس User-Agent لتحديد إصدار المتصفح ويقدم مجموعة أدنى من polyfills. هذا يقلل حجم البيانات المنقولة مقارنة بحزمة polyfills الشاملة.

يتم توصيل Polyfill.io عبر علامة <script> قبل الكود الرئيسي للتطبيق. تحلل الخدمة User-Agent وتعيد ملف JavaScript مع polyfills فقط لذلك المتصفح. لن يحصل Chrome على أي polyfill، بينما سيحصل IE 11 على المجموعة الكاملة. هذا نهج أمثل للأداء: المتصفحات الحديثة لا تحمل كودًا غير ضروري.

توصيل Polyfill.io

html
<!-- Polyfill.io: تحميل ديناميكي -->
<script src="https://cdn.polyfill.io/v3/polyfill.min.js?features=Promise%2CArray.prototype.includes%2CObject.assign%2Cfetch"></script>

<!-- الإصدار المحلي من Polyfill.io -->
<script src="/js/polyfill.js"></script>
<script>
  // feature detection for fetch
  if (!self.fetch) {
    loadScript("/js/fetch-polyfill.js");
  }
</script>

المعامل features في عنوان URL لـ Polyfill.io يحدد polyfills المطلوب تحميلها. القيم الممكنة: أسماء الطرق (Array.prototype.includes)، الكائنات العامة (Promise)، أو أعلام (es6، es2016). العلم "default" يحمل مجموعة أساسية لجافا سكريبت الحديث. لمشاريع الإنتاج، يُوصى باستضافة Polyfill.io على CDN خاص أو استخدام إصدار محلي من المكتبة للتحكم في التوفر.

Polyfills في التطبيقات المحمولة و WebView

WebView في التطبيقات المحمولة (Android WebView، WKWebView على iOS) هو بيئة خاصة للـ polyfills. يعتمد إصدار WebView على إصدار نظام التشغيل وتحديث Chrome System WebView المثبت (Android) أو WKWebView من iOS Safari. في الإصدارات القديمة من Android (4.4، 5.0)، يعتمد WebView على Chromium 30–37 — بدون دعم fetch، Promise، IntersectionObserver.

React Native يستخدم JavaScriptCore (iOS) أو Hermes (Android) — هذه المحركات تنفذ ES6+ بشكل مختلف. يدعم JavaScriptCore على iOS معظم ميزات ES6 لكنه قد يفتقد بعض مقترحات المرحلة 3. Hermes (المستخدم افتراضيًا في React Native 0.70+) يدعم مجموعة محدودة من معيار ES — polyfills إلزامية له.

التحقق من الدعم في WebView

js
// feature detection لـ WebView
const polyfills = [];

// Promise
if (typeof Promise === "undefined") {
  polyfills.push("Promise");
}

// Fetch API
if (typeof self.fetch === "undefined") {
  polyfills.push("fetch");
}

// IntersectionObserver (مطلوب للتحميل البطيء)
if (typeof IntersectionObserver === "undefined") {
  polyfills.push("IntersectionObserver");
}

// تحميل ديناميكي للـ polyfills
if (polyfills.length > 0) {
  const script = document.createElement("script");
  script.src = "https://cdn.polyfill.io/v3/polyfill.min.js"
    + "?features=" + polyfills.join(",");
  document.head.appendChild(script);
}

كشف الميزات (Feature detection) لـ WebView يتحقق من وجود API حرجة (Promise، fetch، IntersectionObserver) ويحمل polyfills ديناميكيًا فقط للمفقودة. يضمن ذلك أن WebViews الحديثة (Chrome 100+ على Android 12) لا تحمل كودًا غير ضروري، بينما تحصل WebViews القديمة (Android 5.0) على الدعم المطلوب.

الأسئلة الشائعة

هل هناك حاجة إلى polyfills لـ React Native؟

React Native على Hermes يتطلب polyfills لبعض طرق ES: Array.flat، Array.flatMap، globalThis، TextEncoder. يُوصى بتضمين core-js أو react-native-polyfill-globals لإصدارات الإنتاج. يدعم JavaScriptCore على iOS ميزات أكثر، لكنه قد يتطلب أيضًا polyfills لمقترحات المرحلة 3.

هل تؤثر polyfills على الأداء؟

Polyfills تقلل الأداء بنسبة 1–5%، لأن تطبيق JavaScript أبطأ من تطبيق C++ الأصلي في المحرك. على سبيل المثال، polyfill لـ Promise في JS الخالص أبطأ من Promise الأصلي في V8. ومع ذلك، بالنسبة لمعظم التطبيقات، الفرق غير ملحوظ. للكود الحرج، يُوصى بالتحقق من وجود التطبيق الأصلي من خلال كشف الميزات.

كيف يختلف polyfill عن التجميع (transpilation)؟

التجميع (Transpilation) يحول الصياغة: const → var، دوال الأسهم → function. Polyfill يضيف كائنات/طرق جديدة: Promise، Array.includes، fetch. يعمل التجميع في وقت البناء، بينما يُحمَّل polyfill في وقت التشغيل. كلا الآليتين ضروريتان للدعم الكامل للكود الحديث في البيئات القديمة.

هل يمكن تجنب polyfills في 2026؟

نعم، إذا كان جمهورك المستهدف يستخدم فقط المتصفحات الحديثة (Chrome 90+، Safari 15+، Firefox 90+). للمشاريع التي تدعم الأجهزة القديمة أو المستخدمين في المؤسسات (Internet Explorer 11 لا يزال مستخدمًا في القطاع الحكومي)، الـ polyfills إلزامية. حلل إحصائيات متصفحات جمهورك عبر Google Analytics.

ما حجم حزمة polyfills core-js؟

core-js في build كامل يزن ~85 كيلوبايت (gzip). عند استخدام useBuiltIns: "usage" في Babel، يتم تضمين polyfills الضرورية فقط، مما يقلل الحجم إلى 5–30 كيلوبايت حسب المتصفحات المستهدفة. للمتصفحات الحديثة (Chrome 100+)، قد لا تكون هناك حاجة لأي polyfill.

الخلاصة

  • Polyfill هو محاكاة لـ API مفقودة في بيئة تشغيل، تضمن توافق الكود الحديث مع البيئات القديمة
  • core-js هي المكتبة القياسية للـ polyfills لـ ES5–ES2025، مدمجة مع Babel عبر @babel/preset-env
  • Polyfill.io هي خدمة تحميل ديناميكي للـ polyfills بناءً على User-Agent للمتصفح
  • التجميع + polyfills هو حل شامل: Babel يحول الصياغة، core-js يضيف API المفقودة
  • كشف الميزات يتحقق من التطبيق الأصلي قبل تحميل polyfill لتحسين الأداء
  • WebView و Hermes يتطلبان polyfills إلزامية لـ fetch و Promise و IntersectionObserver في الإصدارات القديمة

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا