Polyfill: o que é, princípio de funcionamento e bibliotecas para emular API

Autor: IT Sectr Publicado: 2026-05-19 Tempo de leitura: 9 min

Polyfill é um código que emula funcionalidades ausentes (API, métodos, objetos) em ambientes onde elas não são implementadas nativamente. Polyfill permite usar recursos modernos de JavaScript, CSS ou Web API em navegadores antigos e runtimes. De acordo com MDN Web Docs, os polyfills são uma ferramenta chave para melhoria progressiva e garantia de compatibilidade entre navegadores.

Pontos principais

  • Polyfill é uma emulação de software de uma API ausente em um ambiente de execução onde essa API não está implementada
  • core-js é a biblioteca padrão de polyfills para JavaScript moderno com suporte a todas as propostas stage-4
  • Polyfill.io é um serviço que fornece polyfills dinamicamente apenas para o navegador do usuário
  • Transpilação vs polyfill: a transpilação transforma a sintaxe (arrow function → function), o polyfill adiciona novos métodos (Array.includes, Promise)
  • Detecção de recursos verifica a existência de uma implementação nativa antes de carregar um polyfill para evitar conflitos

O que é Polyfill?

Polyfill é um fragmento de código (geralmente JavaScript) que implementa funcionalidades que o ambiente de execução não suporta nativamente. O termo foi cunhado por Remy Sharp em 2009 como um jogo de palavras: Polyfill é análogo ao Polyfilla, um enchimento que preenche rachaduras em uma parede. Polyfill preenche as lacunas entre o padrão e seu suporte em um navegador ou runtime específico.

Polyfill não modifica o código existente — ele estende o ambiente de execução. Se um navegador não suporta Array.prototype.includes, o polyfill adiciona este método ao protótipo Array antes da execução do código principal. Polyfills podem emular novos objetos globais (Promise, Map, Set, Symbol), métodos estáticos (Array.from, Object.assign) e métodos de protótipo.

Detecção de recursos é um mecanismo obrigatório antes de instalar um polyfill. Em vez de verificar o user-agent (qual navegador), deve-se verificar a existência do método: if (!Array.prototype.includes) { Array.prototype.includes = ... }. Isso garante que o polyfill não sobrescreva a implementação nativa se ela já existir. Google Analytics e outros serviços coletam dados de suporte de API para análise.

Quando os polyfills surgiram

Os primeiros polyfills surgiram na era do Internet Explorer 6–8 (2005–2009), quando os desenvolvedores descobriram uma lacuna entre os padrões W3C e as implementações dos navegadores. O termo foi introduzido por Remy Sharp em 2009 no BarCamp London. O primeiro polyfill em massa foi html5shiv (2009) — uma biblioteca que adiciona suporte para tags HTML5 (<section>, <article>, <nav>) no Internet Explorer.

Com o advento do ES6 (2015) e do ciclo anual de atualizações do ECMAScript, o número de polyfills necessários cresceu. A cada ano o padrão adiciona novos métodos (Array.includes, String.padStart, Object.fromEntries, Promise.allSettled) que não são suportados por navegadores antigos. core-js, iniciado como es6-shim em 2014, tornou-se uma solução universal. Em 2026, core-js contém mais de 5.000 módulos de polyfill para ES5–ES2025.

O que pode e o que não pode ser polyfill

CategoriaPode ser polyfillNão pode ser polyfill
Métodos de protótipoArray.includes, String.startsWith
Objetos globaisPromise, Map, Set, Symbol
Métodos estáticosObject.assign, Array.from
Sintaxe da linguagemArrow functions, async/await, class
Web APIfetch, IntersectionObserverService Worker (requer suporte nativo)

Polyfill vs transpilação: diferenças e interação

Transpilação converte sintaxe nova em sintaxe antiga (const → var, () => {} → function() {}). Polyfill adiciona métodos e objetos ausentes (Promise, Array.includes). Esses dois mecanismos se complementam: a transpilação torna o código sintaticamente compatível, os polyfills garantem a completude da API. Babel + core-js é a combinação padrão para suporte completo.

Babel @babel/preset-env com a opção useBuiltIns determina quais polyfills são necessários com base nos navegadores alvo. useBuiltIns: "usage" analisa quais APIs são usadas no código e importa apenas os polyfills necessários do core-js. useBuiltIns: "entry" importa todos os polyfills para os navegadores alvo através de uma única importação core-js/stable.

Exemplo: polyfill para Array.prototype.includes

js
// Verificação de existência e adição de 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,
  });
}

// Uso — agora seguro em qualquer navegador
const arr = [1, 2, 3, 4, 5];
console.log(arr.includes(3)); // true

Polyfill para Array.prototype.includes verifica se o método está definido no protótipo Array. Se não estiver, cria a propriedade via Object.defineProperty com as flags writable: true, configurable: true. A implementação segue a especificação ES2016: verificação de null/undefined, conversão para objeto, manipulação de fromIndex negativo. Após adicionar o polyfill, a chamada arr.includes(3) funciona em todos os navegadores, incluindo Internet Explorer 11.

core-js: a biblioteca padrão de polyfills

core-js é a biblioteca de polyfills JavaScript mais abrangente, suportando todas as propostas stage-4 do TC39 (padrão ECMAScript). core-js inclui polyfills para Promise, Symbol, Map, Set, WeakMap, WeakSet, métodos Array, métodos String, métodos Object, métodos Number, métodos Math, Reflect, globalThis e todas as propostas stage-4. A versão atual core-js 3.38+ cobre ES5–ES2025.

core-js integra-se com Babel através do @babel/preset-env e da opção useBuiltIns. Sem essa integração, os desenvolvedores teriam que importar manualmente cada polyfill: import "core-js/stable/array/includes". O @babel/preset-env adiciona automaticamente as importações necessárias com base nos navegadores alvo do .browserslistrc. Isso reduz o tamanho do bundle — apenas os polyfills necessários são incluídos.

Exemplo: polyfill para fetch

Fetch API é uma das Web APIs mais frequentemente polyfilled. A implementação nativa do fetch está disponível em Chrome 42+ (2015), Safari 10.1+ (2017), Firefox 39+ (2015), mas está ausente no Internet Explorer e WebViews antigos. O polyfill whatwg-fetch emula fetch via XMLHttpRequest. Alternativa — usar isomorphic-fetch (um polyfill para Node.js e navegador) ou a biblioteca universal axios, que não requer polyfills.

js
// Carregar polyfill fetch apenas para navegadores antigos
if (typeof self.fetch !== "function") {
  import("whatwg-fetch").then(module => {
    self.fetch = module.fetch;
    console.log("fetch polyfill loaded");
  });
}

// Usar fetch (funciona tanto com polyfill quanto com API nativa)
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 dinâmico do polyfill fetch via import() garante que navegadores modernos não carreguem código desnecessário. O polyfill carrega de forma assíncrona e não bloqueia a thread principal. Após o carregamento, self.fetch substitui a implementação nativa ou adiciona a ausente. Esta é uma técnica de melhoria progressiva: navegadores modernos recebem apenas código nativo, os antigos recebem o polyfill adicional.

Integração do core-js com 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 — navegadores alvo
> 0.5%
last 2 versions
not dead
not op_mini all
ie >= 11
not ios_saf < 12

useBuiltIns: "usage" analisa o código e adiciona apenas os polyfills que são realmente usados. corejs.version especifica a versão do core-js no projeto. targets.browsers define o nível mínimo de navegadores — quanto mais antigos os navegadores alvo, mais polyfills serão incluídos. .browserslistrc é usado não apenas pelo Babel, mas também pelo Autoprefixer, PostCSS e Stylelint para segmentação consistente.

Polyfill.io e carregamento dinâmico de polyfills

Polyfill.io é um serviço (e uma biblioteca de mesmo nome) que determina dinamicamente quais polyfills o navegador do usuário precisa e retorna apenas esses. Polyfill.io usa o cabeçalho User-Agent para determinar a versão do navegador e fornece um conjunto mínimo de polyfills. Isso reduz a quantidade de dados transferidos em comparação com um bundle universal de polyfills.

A conexão do Polyfill.io é feita através de uma tag <script> antes do código principal da aplicação. O serviço analisa o User-Agent e retorna um arquivo JavaScript com polyfills apenas para aquele navegador. Chrome não receberá nenhum polyfill, IE 11 receberá o conjunto completo. Esta é uma abordagem ideal para desempenho: navegadores modernos não carregam código desnecessário.

Conexão do Polyfill.io

html
<!-- Polyfill.io: carregamento dinâmico -->
<script src="https://cdn.polyfill.io/v3/polyfill.min.js?features=Promise%2CArray.prototype.includes%2CObject.assign%2Cfetch"></script>

<!-- Versão local do Polyfill.io -->
<script src="/js/polyfill.js"></script>
<script>
  // feature detection for fetch
  if (!self.fetch) {
    loadScript("/js/fetch-polyfill.js");
  }
</script>

O parâmetro features na URL do Polyfill.io especifica quais polyfills carregar. Valores possíveis: nomes de métodos (Array.prototype.includes), objetos globais (Promise) ou flags (es6, es2016). A flag "default" carrega um conjunto básico para JavaScript moderno. Para projetos em produção, recomenda-se hospedar o Polyfill.io em seu próprio CDN ou usar uma versão local da biblioteca para controle de disponibilidade.

Polyfills em aplicativos móveis e WebView

WebView em aplicativos móveis (Android WebView, WKWebView no iOS) é um ambiente especial para polyfills. A versão do WebView depende da versão do SO e da atualização instalada do Chrome System WebView (Android) ou WKWebView do iOS Safari. Em versões antigas do Android (4.4, 5.0), o WebView é baseado no Chromium 30–37 — sem suporte para fetch, Promise, IntersectionObserver.

React Native usa JavaScriptCore (iOS) ou Hermes (Android) — esses motores implementam ES6+ de forma diferente. JavaScriptCore no iOS suporta a maioria dos recursos ES6, mas pode não ter algumas propostas stage-3. Hermes (usado por padrão no React Native 0.70+) suporta um conjunto limitado do padrão ES — polyfills são obrigatórios para ele.

Verificação de suporte no WebView

js
// feature detection para WebView
const polyfills = [];

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

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

// IntersectionObserver (necessário para lazy loading)
if (typeof IntersectionObserver === "undefined") {
  polyfills.push("IntersectionObserver");
}

// Carregamento dinâmico de 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);
}

Detecção de recursos para WebView verifica a presença de APIs críticas (Promise, fetch, IntersectionObserver) e carrega dinamicamente polyfills apenas para as ausentes. Isso garante que WebViews modernos (Chrome 100+ no Android 12) não carreguem código desnecessário, enquanto WebViews antigos (Android 5.0) obtenham o suporte necessário.

Perguntas frequentes

Polyfills são necessários para React Native?

React Native no Hermes requer polyfills para alguns métodos ES: Array.flat, Array.flatMap, globalThis, TextEncoder. Recomenda-se incluir core-js ou react-native-polyfill-globals para builds de produção. JavaScriptCore no iOS suporta mais recursos, mas também pode exigir polyfills para propostas stage-3.

Polyfills afetam o desempenho?

Polyfills reduzem o desempenho em 1–5%, já que a implementação em JavaScript é mais lenta que a implementação nativa em C++ no motor. Por exemplo, um polyfill de Promise em JS puro é mais lento que um Promise nativo no V8. No entanto, para a maioria das aplicações, a diferença é imperceptível. Para código crítico, recomenda-se verificar a implementação nativa através de detecção de recursos.

Como o polyfill difere da transpilação?

Transpilação converte a sintaxe: const → var, funções flecha → function. Polyfill adiciona novos objetos/métodos: Promise, Array.includes, fetch. A transpilação funciona em tempo de compilação, o polyfill carrega em tempo de execução. Ambos os mecanismos são necessários para suporte completo de código moderno em ambientes antigos.

É possível evitar polyfills em 2026?

Sim, se seu público-alvo usa apenas navegadores modernos (Chrome 90+, Safari 15+, Firefox 90+). Para projetos com suporte a dispositivos antigos ou usuários corporativos (Internet Explorer 11 ainda é usado no setor governamental), polyfills são obrigatórios. Analise as estatísticas de navegadores do seu público através do Google Analytics.

Qual o tamanho do bundle de polyfills core-js?

core-js em uma build completa pesa ~85 KB (gzip). Ao usar useBuiltIns: "usage" no Babel, apenas os polyfills necessários são incluídos, reduzindo o tamanho para 5–30 KB dependendo dos navegadores alvo. Para navegadores modernos (Chrome 100+), pode não ser necessário nenhum polyfill.

Resumo

  • Polyfill é uma emulação de uma API ausente em um ambiente de execução, garantindo compatibilidade do código moderno com ambientes antigos
  • core-js é a biblioteca padrão de polyfills para ES5–ES2025, integrada com Babel via @babel/preset-env
  • Polyfill.io é um serviço de carregamento dinâmico de polyfills baseado no User-Agent do navegador
  • Transpilação + polyfills é uma solução abrangente: Babel transforma a sintaxe, core-js adiciona APIs ausentes
  • Detecção de recursos verifica a implementação nativa antes de carregar um polyfill para desempenho
  • WebView e Hermes exigem polyfills obrigatórios para fetch, Promise e IntersectionObserver em versões antigas

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também