Polyfill: چیست، اصل کار و کتابخانه‌های شبیه‌سازی API

نویسنده: IT Sectr منتشر شده: 2026-05-19 زمان مطالعه: 9 دقیقه

Polyfill (پلی‌فیل) — کدی که عملکردهای缺失 (API، متدها، اشیاء) را در محیط‌هایی که به صورت بومی پیاده‌سازی نشده‌اند شبیه‌سازی می‌کند. Polyfill امکان استفاده از قابلیت‌های مدرن JavaScript، CSS یا Web API را در مرورگرهای قدیمی و runtimeها فراهم می‌کند. به گفته MDN Web Docs، پلی‌فیل‌ها ابزار کلیدی بهبود تدریجی و تضمین سازگاری بین مرورگری هستند.

مهم‌ترین نکات

  • Polyfill — شبیه‌سازی نرم‌افزاری API缺失 در محیط اجرایی که این API در آن پیاده‌سازی نشده است
  • core-js — کتابخانه استاندارد پلی‌فیل‌ها برای JavaScript مدرن با پشتیبانی از تمام پیشنهادهای stage-4
  • Polyfill.io — سرویسی که پلی‌فیل‌ها را فقط برای مرورگر کاربر به صورت پویا ارائه می‌کند
  • ترانسپایل در مقابل polyfill: ترانسپایل نحو را تبدیل می‌کند (arrow function → function)، polyfill متدهای جدید اضافه می‌کند (Array.includes, Promise)
  • Feature detection — بررسی وجود پیاده‌سازی بومی قبل از بارگذاری پلی‌فیل برای جلوگیری از تداخل

Polyfill چیست؟

Polyfill — قطعه کدی (معمولاً JavaScript) که عملکردی را پیاده‌سازی می‌کند که محیط اجرا به صورت بومی از آن پشتیبانی نمی‌کند. این اصطلاح توسط رمی شارپ در سال ۲۰۰۹ به عنوان یک بازی کلامی پیشنهاد شد: Polyfill — مشابه بتونه (Polyfilla) که ترک‌های دیوار را پر می‌کند. Polyfill شکاف‌های بین استاندارد و پشتیبانی در مرورگر یا runtime خاص را پر می‌کند.

Polyfill کد موجود را تغییر نمی‌دهد — آن محیط اجرا را گسترش می‌دهد. اگر مرورگر از Array.prototype.includes پشتیبانی نمی‌کند، پلی‌فیل این متد را قبل از اجرای کد اصلی به prototype Array اضافه می‌کند. پلی‌فیل‌ها می‌توانند اشیاء سراسری جدید (Promise, Map, Set, Symbol)، متدهای ایستا (Array.from, Object.assign) و متدهای prototype را شبیه‌سازی کنند.

Feature detection — مکانیسم اجباری قبل از نصب پلی‌فیل. به جای بررسی user-agent (چه مرورگری)، باید وجود متد را بررسی کرد: if (!Array.prototype.includes) { Array.prototype.includes = ... }. این تضمین می‌کند که پلی‌فیل پیاده‌سازی بومی را در صورت وجود بازنویسی نمی‌کند. Google Analytics و سایر سرویس‌ها داده‌هایی درباره پشتیبانی API برای تحلیل جمع‌آوری می‌کنند.

پلی‌فیل‌ها چه زمانی ظهور کردند

اولین پلی‌فیل‌ها در عصر Internet Explorer 6–8 (۲۰۰۵–۲۰۰۹) ظاهر شدند، زمانی که توسعه‌دهندگان شکاف بین استانداردهای W3C و پیاده‌سازی در مرورگرها را کشف کردند. این اصطلاح توسط رمی شارپ در سال ۲۰۰۹ در کنفرانس BarCamp London معرفی شد. اولین پلی‌فیل گسترده html5shiv (۲۰۰۹) بود — کتابخانه‌ای که پشتیبانی از تگ‌های HTML5 (<section>, <article>, <nav>) را به Internet Explorer اضافه می‌کرد.

با ظهور ES6 (۲۰۱۵) و چرخه به‌روزرسانی سالانه ECMAScript، تعداد پلی‌فیل‌های مورد نیاز افزایش یافت. هر سال استاندارد متدهای جدیدی (Array.includes, String.padStart, Object.fromEntries, Promise.allSettled) اضافه می‌کند که توسط مرورگرهای قدیمی پشتیبانی نمی‌شوند. core-js که در سال ۲۰۱۴ به عنوان es6-shim شروع شد، به راه‌حلی جهانی تبدیل گردید. تا سال ۲۰۲۶، core-js حاوی بیش از ۵۰۰۰ ماژول پلی‌فیل برای ES5–ES2025 است.

چه چیزی را می‌توان و نمی‌توان پلی‌فیل کرد

دسته‌بندیقابل پلی‌فیلغیرقابل پلی‌فیل
متدهای prototypeArray.includes, String.startsWith
اشیاء سراسریPromise, Map, Set, Symbol
متدهای ایستاObject.assign, Array.from
نحو زبانArrow functions, async/await, class
Web APIfetch, IntersectionObserverService Worker (نیازمند پشتیبانی بومی)

Polyfill در مقابل ترانسپایل: تفاوت‌ها و تعامل

ترانسپایل نحو جدید را به قدیمی تبدیل می‌کند (const → var, () => {} → function() {}). Polyfill متدها و اشیاء缺失 را اضافه می‌کند (Promise, Array.includes). این دو مکانیسم مکمل یکدیگرند: ترانسپایل سازگاری نحوی را فراهم می‌کند، پلی‌فیل‌ها کامل بودن API را تضمین می‌کنند. Babel + core-js — ترکیب استاندارد برای پشتیبانی کامل.

Babel @babel/preset-env با گزینه useBuiltIns تعیین می‌کند که بر اساس مرورگرهای هدف به چه پلی‌فیل‌هایی نیاز است. useBuiltIns: «usage» تحلیل می‌کند که از کدام API‌ها در کد استفاده شده و فقط پلی‌فیل‌های لازم را از core-js متصل می‌کند. useBuiltIns: «entry» تمام پلی‌فیل‌های مرورگرهای هدف را از طریق یک import واحد core-js/stable متصل می‌کند.

مثال: پلی‌فیل برای Array.prototype.includes

js
// بررسی وجود و افزودن پلی‌فیل
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

پلی‌فیل برای Array.prototype.includes بررسی می‌کند که آیا متد در prototype Array تعریف شده است یا خیر. اگر نه — با Object.defineProperty و پرچم‌های writable: true, configurable: true یک ویژگی ایجاد می‌کند. پیاده‌سازی مطابق با مشخصات ES2016 است: بررسی null/undefined، تبدیل به شیء، کار با fromIndex منفی. پس از افزودن پلی‌فیل، فراخوانی arr.includes(3) در تمام مرورگرها از جمله Internet Explorer 11 کار می‌کند.

core-js: کتابخانه استاندارد پلی‌فیل‌ها

core-js — کامل‌ترین کتابخانه پلی‌فیل‌های JavaScript که از تمام پیشنهادهای stage-4 TC39 (استاندارد ECMAScript) پشتیبانی می‌کند. core-js شامل پلی‌فیل‌هایی برای Promise, Symbol, Map, Set, WeakMap, WeakSet, متدهای Array, متدهای String, متدهای Object, متدهای Number, متدهای Math, Reflect, globalThis و تمام stage-4 proposals است. نسخه فعلی core-js 3.38+ ES5–ES2025 را پوشش می‌دهد.

core-js با Babel از طریق @babel/preset-env و گزینه useBuiltIns یکپارچه می‌شود. بدون این یکپارچه‌سازی، توسعه‌دهنده باید هر پلی‌فیل را به صورت دستی import کند: import «core-js/stable/array/includes». @babel/preset-env به صورت خودکار importهای لازم را بر اساس مرورگرهای هدف از .browserslistrc اضافه می‌کند. این کار اندازه باندل را کاهش می‌دهد — فقط پلی‌فیل‌های لازم متصل می‌شوند.

مثال: پلی‌فیل برای fetch

Fetch API — یکی از پرکاربردترین Web API‌هایی است که پلی‌فیل می‌شود. پیاده‌سازی بومی fetch در Chrome 42+ (۲۰۱۵)، Safari 10.1+ (۲۰۱۷)، Firefox 39+ (۲۰۱۵) موجود است، اما در Internet Explorer و WebViewهای قدیمی وجود ندارد. پلی‌فیل whatwg-fetch fetch را از طریق XMLHttpRequest شبیه‌سازی می‌کند. جایگزین — استفاده از isomorphic-fetch (پلی‌فیل برای Node.js و مرورگر) یا کتابخانه universal axios که به پلی‌فیل نیاز ندارد.

js
// بارگذاری پلی‌فیل fetch فقط برای مرورگرهای قدیمی
if (typeof self.fetch !== "function") {
  import("whatwg-fetch").then(module => {
    self.fetch = module.fetch;
    console.log("fetch polyfill loaded");
  });
}

// استفاده از fetch (هم با پلی‌فیل و هم با 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);
  }
}

import پویا پلی‌فیل fetch از طریق import() تضمین می‌کند که مرورگرهای مدرن کد اضافی بارگذاری نمی‌کنند. پلی‌فیل به صورت ناهمگام بارگذاری می‌شود و ترد اصلی را مسدود نمی‌کند. پس از بارگذاری، self.fetch جایگزین پیاده‌سازی بومی می‌شود یا پیاده‌سازی缺失 را اضافه می‌کند. این تکنیک بهبود تدریجی است: مرورگرهای مدرن فقط کد بومی دریافت می‌کنند، مرورگرهای قدیمی — پلی‌فیل اضافی.

یکپارچه‌سازی 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» کد را تحلیل می‌کند و فقط پلی‌فیل‌هایی را اضافه می‌کند که واقعاً استفاده شده‌اند. corejs.version نسخه core-js را در پروژه مشخص می‌کند. targets.browsers سطح حداقل مرورگرها را تعیین می‌کند — هرچه مرورگرها قدیمی‌تر باشند، پلی‌فیل‌های بیشتری متصل می‌شوند. .browserslistrc نه تنها توسط Babel، بلکه توسط Autoprefixer، PostCSS و Stylelint برای هدف‌گیری سازگار استفاده می‌شود.

Polyfill.io و بارگذاری پویای پلی‌فیل‌ها

Polyfill.io — سرویس (و کتابخانه‌ای به همین نام) که به صورت پویا تعیین می‌کند مرورگر کاربر به کدام پلی‌فیل‌ها نیاز دارد و فقط همان‌ها را برمی‌گرداند. Polyfill.io از هدر User-Agent برای تعیین نسخه مرورگر استفاده می‌کند و حداقل مجموعه پلی‌فیل‌ها را ارائه می‌دهد. این کار حجم داده‌های ارسالی را در مقایسه با باندل universal پلی‌فیل‌ها کاهش می‌دهد.

اتصال Polyfill.io از طریق تگ <script> قبل از کد اصلی برنامه انجام می‌شود. سرویس User-Agent را تحلیل می‌کند و فایل JavaScript حاوی پلی‌فیل‌های فقط برای این مرورگر را برمی‌گرداند. Chrome هیچ پلی‌فیلی دریافت نمی‌کند، 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>
  // تشخیص ویژگی برای fetch
  if (!self.fetch) {
    loadScript("/js/fetch-polyfill.js");
  }
</script>

پارامتر features در URL Polyfill.io مشخص می‌کند کدام پلی‌فیل‌ها بارگذاری شوند. مقادیر ممکن: نام متدها (Array.prototype.includes)، اشیاء سراسری (Promise)، یا پرچم‌ها (es6, es2016). پرچم «default» مجموعه پایه را برای JavaScript مدرن متصل می‌کند. برای پروژه‌های تولیدی توصیه می‌شود Polyfill.io را روی CDN خود میزبانی کنید یا از نسخه محلی کتابخانه برای کنترل در دسترس بودن استفاده کنید.

پلی‌فیل‌ها در برنامه‌های موبایل و WebView

WebView در برنامه‌های موبایل (Android WebView, WKWebView در iOS) — محیطی ویژه برای پلی‌فیل‌ها است. نسخه 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 پشتیبانی می‌کند، اما ممکن است برخی پیشنهادهای stage-3 را نداشته باشد. Hermes (استفاده پیش‌فرض در React Native 0.70+) از مجموعه محدودی از استاندارد ES پشتیبانی می‌کند — برای آن پلی‌فیل‌ها اجباری هستند.

بررسی پشتیبانی در WebView

js
// تشخیص ویژگی برای 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");
}

// بارگذاری پویای پلی‌فیل‌ها
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) را بررسی می‌کند و پلی‌فیل‌ها را فقط برای موارد缺失 به صورت پویا بارگذاری می‌کند. این تضمین می‌کند که WebView مدرن (Chrome 100+ در Android 12) کد اضافی بارگذاری نمی‌کند، و WebView قدیمی (Android 5.0) پشتیبانی لازم را دریافت می‌کند.

سؤالات متداول

آیا پلی‌فیل‌ها برای React Native ضروری هستند؟

React Native روی Hermes برای برخی متدهای ES به پلی‌فیل نیاز دارد: Array.flat, Array.flatMap, globalThis, TextEncoder. توصیه می‌شود برای بیلدهای تولیدی core-js یا react-native-polyfill-globals متصل شود. JavaScriptCore در iOS از ویژگی‌های بیشتری پشتیبانی می‌کند، اما ممکن است برای پیشنهادهای stage-3 به پلی‌فیل نیاز داشته باشد.

آیا پلی‌فیل‌ها روی عملکرد تأثیر می‌گذارند؟

پلی‌فیل‌ها عملکرد را ۱–۵٪ کاهش می‌دهند، زیرا پیاده‌سازی JavaScript از پیاده‌سازی بومی C++ در موتور کندتر است. مثلاً پلی‌فیل Promise در JS خالص از Promise بومی در V8 کندتر است. با این حال برای اکثر برنامه‌ها تفاوت نامحسوس است. برای کد حیاتی توصیه می‌شود وجود پیاده‌سازی بومی را از طریق feature detection بررسی کنید.

تفاوت پلی‌فیل و ترانسپایل چیست؟

ترانسپایل نحو را تبدیل می‌کند: const → var, arrow functions → function. پلی‌فیل اشیاء/متدهای جدید اضافه می‌کند: Promise, Array.includes, fetch. ترانسپایل در مرحله build کار می‌کند، پلی‌فیل در runtime بارگذاری می‌شود. هر دو مکانیسم برای پشتیبانی کامل از کد مدرن در محیط‌های قدیمی ضروری هستند.

آیا می‌توان در سال ۲۰۲۶ از پلی‌فیل استفاده نکرد؟

می‌توان، اگر مخاطب هدف فقط از مرورگرهای مدرن (Chrome 90+, Safari 15+, Firefox 90+) استفاده کند. برای پروژه‌هایی که از دستگاه‌های قدیمی یا کاربران سازمانی (Internet Explorer 11 هنوز در بخش دولتی استفاده می‌شود) پشتیبانی می‌کنند، پلی‌فیل‌ها اجباری هستند. آمار مرورگرهای مخاطبان خود را از طریق Google Analytics تحلیل کنید.

اندازه پلی‌فیل‌های core-js چقدر است؟

core-js در بیلد کامل ~۸۵ کیلوبایت (gzip) وزن دارد. هنگام استفاده از useBuiltIns: «usage» در Babel فقط پلی‌فیل‌های لازم متصل می‌شوند که اندازه را بسته به مرورگرهای هدف به ۵–۳۰ کیلوبایت کاهش می‌دهد. برای مرورگرهای مدرن (Chrome 100+) ممکن است هیچ پلی‌فیلی لازم نباشد.

جمع‌بندی

  • Polyfill — شبیه‌سازی API缺失 در محیط اجرا، تضمین‌کننده سازگاری کد مدرن با محیط‌های قدیمی
  • core-js — کتابخانه استاندارد پلی‌فیل‌ها برای ES5–ES2025، قابل یکپارچه‌سازی با Babel از طریق @babel/preset-env
  • Polyfill.io — سرویس بارگذاری پویای پلی‌فیل‌ها بر اساس User-Agent مرورگر
  • ترانسپایل + پلی‌فیل‌ها — راه‌حل جامع: Babel نحو را تبدیل می‌کند، core-js APIهای缺失 را اضافه می‌کند
  • Feature detection — بررسی وجود پیاده‌سازی بومی قبل از بارگذاری پلی‌فیل برای بهبود عملکرد
  • WebView و Hermes در نسخه‌های قدیمی به پلی‌فیل‌های اجباری برای fetch, Promise و IntersectionObserver نیاز دارند

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید