Polyfill (پلیفیل) — کدی که عملکردهای缺失 (API، متدها، اشیاء) را در محیطهایی که به صورت بومی پیادهسازی نشدهاند شبیهسازی میکند. Polyfill امکان استفاده از قابلیتهای مدرن JavaScript، CSS یا Web API را در مرورگرهای قدیمی و runtimeها فراهم میکند. به گفته MDN Web Docs، پلیفیلها ابزار کلیدی بهبود تدریجی و تضمین سازگاری بین مرورگری هستند.
مهمترین نکات
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 است.
| دستهبندی | قابل پلیفیل | غیرقابل پلیفیل |
|---|---|---|
| متدهای prototype | Array.includes, String.startsWith | — |
| اشیاء سراسری | Promise, Map, Set, Symbol | — |
| متدهای ایستا | Object.assign, Array.from | — |
| نحو زبان | — | Arrow functions, async/await, class |
| Web API | fetch, IntersectionObserver | Service Worker (نیازمند پشتیبانی بومی) |
ترانسپایل نحو جدید را به قدیمی تبدیل میکند (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 متصل میکند.
// بررسی وجود و افزودن پلیفیل
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 — کاملترین کتابخانه پلیفیلهای 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 API — یکی از پرکاربردترین Web APIهایی است که پلیفیل میشود. پیادهسازی بومی fetch در Chrome 42+ (۲۰۱۵)، Safari 10.1+ (۲۰۱۷)، Firefox 39+ (۲۰۱۵) موجود است، اما در Internet Explorer و WebViewهای قدیمی وجود ندارد. پلیفیل whatwg-fetch fetch را از طریق XMLHttpRequest شبیهسازی میکند. جایگزین — استفاده از isomorphic-fetch (پلیفیل برای Node.js و مرورگر) یا کتابخانه universal axios که به پلیفیل نیاز ندارد.
// بارگذاری پلیفیل 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 جایگزین پیادهسازی بومی میشود یا پیادهسازی缺失 را اضافه میکند. این تکنیک بهبود تدریجی است: مرورگرهای مدرن فقط کد بومی دریافت میکنند، مرورگرهای قدیمی — پلیفیل اضافی.
// 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"],
},
}],
],
};# .browserslistrc — مرورگرهای هدف
> 0.5%
last 2 versions
not dead
not op_mini all
ie >= 11
not ios_saf < 12useBuiltIns: «usage» کد را تحلیل میکند و فقط پلیفیلهایی را اضافه میکند که واقعاً استفاده شدهاند. corejs.version نسخه core-js را در پروژه مشخص میکند. targets.browsers سطح حداقل مرورگرها را تعیین میکند — هرچه مرورگرها قدیمیتر باشند، پلیفیلهای بیشتری متصل میشوند. .browserslistrc نه تنها توسط Babel، بلکه توسط Autoprefixer، PostCSS و Stylelint برای هدفگیری سازگار استفاده میشود.
Polyfill.io — سرویس (و کتابخانهای به همین نام) که به صورت پویا تعیین میکند مرورگر کاربر به کدام پلیفیلها نیاز دارد و فقط همانها را برمیگرداند. Polyfill.io از هدر User-Agent برای تعیین نسخه مرورگر استفاده میکند و حداقل مجموعه پلیفیلها را ارائه میدهد. این کار حجم دادههای ارسالی را در مقایسه با باندل universal پلیفیلها کاهش میدهد.
اتصال Polyfill.io از طریق تگ <script> قبل از کد اصلی برنامه انجام میشود. سرویس User-Agent را تحلیل میکند و فایل JavaScript حاوی پلیفیلهای فقط برای این مرورگر را برمیگرداند. Chrome هیچ پلیفیلی دریافت نمیکند، IE 11 مجموعه کامل را دریافت میکند. این رویکرد بهینه برای عملکرد است: مرورگرهای مدرن کد اضافی بارگذاری نمیکنند.
<!-- 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 در برنامههای موبایل (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
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 روی 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 در بیلد کامل ~۸۵ کیلوبایت (gzip) وزن دارد. هنگام استفاده از useBuiltIns: «usage» در Babel فقط پلیفیلهای لازم متصل میشوند که اندازه را بسته به مرورگرهای هدف به ۵–۳۰ کیلوبایت کاهش میدهد. برای مرورگرهای مدرن (Chrome 100+) ممکن است هیچ پلیفیلی لازم نباشد.
جمعبندی
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید