Shimming é uma técnica para garantir a compatibilidade de módulos que esperam determinadas variáveis globais ou APIs. No ecossistema do Webpack, o shimming é implementado por meio do ProvidePlugin, imports-loader e exports-loader, permitindo conectar bibliotecas legadas sem alterar o código-fonte delas. Segundo a Webpack Documentation (2026), o shimming continua sendo uma ferramenta essencial para integrar plugins de jQuery e outras dependências que não suportam sistema modular.
Principais pontos
Shimming é uma técnica de software que insere uma camada de compatibilidade entre o código e o ambiente sem alterar o código-fonte do módulo. No contexto do build de JavaScript, o shimming resolve o problema quando um módulo acessa variáveis globais (window.$, global.process) que não existem no ambiente modular.
Polyfill implementa a funcionalidade ausente do zero, adicionando novos recursos ao ambiente. Por exemplo, o core-js adiciona Array.prototype.flatMap para navegadores antigos. O Shim, por sua vez, redireciona chamadas existentes para implementações disponíveis ou substitui os objetos globais esperados. No Webpack, o ProvidePlugin insere automaticamente import $ from 'jquery' em todos os lugares onde é encontrada uma referência à variável global $, sem exigir alterações no código.
A principal diferença está no objetivo. Polyfill adiciona o que não existe, enquanto shim torna o código existente compatível com o ambiente em que é executado. A escolha entre eles depende do problema que está sendo resolvido: ausência de API ou incompatibilidade de interfaces.
Webpack trata cada módulo como uma unidade isolada com escopo próprio. Se uma biblioteca acessa a variável global jQuery como window.$, o build falhará com erro, pois essa variável não existe no contexto modular. O ProvidePlugin resolve o problema na etapa de compilação: ao detectar o identificador $ no código, o plugin insere automaticamente import $ from 'jquery' no início do arquivo.
// Código-fonte (o módulo legado acessa o jQuery global)
$('.element').hide();
// Após o processamento do ProvidePlugin (o Webpack insere o import)
import $ from 'jquery';
$('.element').hide();
Além disso, o imports-loader permite especificar explicitamente quais dependências um módulo deve receber. Isso é útil quando uma biblioteca usa this no nível superior, esperando que this se refira a window e não a module.exports.
ProvidePlugin é um plugin integrado do Webpack que carrega automaticamente módulos ao detectar referências a identificadores especificados. A configuração é um objeto em que a chave é o nome da variável e o valor é o caminho para o módulo e o campo exportado.
// webpack.config.js
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
_: 'lodash',
'window.$': 'jquery',
}),
],
};
ProvidePlugin suporta importação parcial por meio da sintaxe de array. Por exemplo, [lodash, debounce] importa apenas a função debounce do lodash, o que reduz o tamanho do bundle final. Isso é especialmente importante em projetos móveis, em que cada kilobyte afeta o tempo de carregamento.
imports-loader adiciona as importações necessárias ao início de um módulo, enquanto o exports-loader define os valores exportados para módulos que não usam module.exports explicitamente. Esses loaders trabalham no nível de arquivos individuais, não globalmente como o ProvidePlugin.
// webpack.config.js — configuração do imports-loader
module.exports = {
module: {
rules: [
{
test: /legacy-module\.js$/,
use: [
{
loader: 'imports-loader',
options: {
imports: [
'jquery',
'$',
],
},
},
],
},
],
},
};
exports-loader é usado quando uma biblioteca atribui um valor a uma variável global, mas não o exporta pelo sistema de módulos. O loader extrai o valor e o transforma em uma exportação de módulo, permitindo que outros módulos o importem por meio de import.
Shimming é configurado no webpack.config.js por meio de uma combinação de plugins e loaders. Um cenário típico inclui ProvidePlugin para variáveis globais e imports-loader para módulos específicos que exigem alteração de escopo.
const webpack = require('webpack');
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
globalObject: 'this',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules\/(?!legacy-lib)/,
use: [
{
loader: 'imports-loader',
options: {
type: 'commonjs',
imports: ['jquery', '$'],
},
},
],
},
],
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
}),
],
};
O campo globalObject em output define o contexto para referências a this no nível superior. Para um ambiente de navegador, o valor 'this' se refere a window, enquanto para React Native ou Node.js se refere a global. Escolher o valor correto previne erros de execução no ambiente de destino.
Shimming é uma ferramenta poderosa, porém perigosa. Uma configuração incorreta leva à duplicação de código no bundle, conflitos de nomes e erros de execução inesperados. Os desenvolvedores frequentemente esquecem que o ProvidePlugin funciona na etapa de compilação e não pode processar referências dinâmicas a variáveis.
Se dois plugins usam versões diferentes de jQuery, o ProvidePlugin substituirá apenas uma delas, a especificada primeiro na configuração. A segunda biblioteca receberá uma versão incompatível, o que causará erros difíceis de depurar. A solução é usar exports-loader para cada biblioteca com versão explícita ou aplicar webpack.IgnorePlugin para excluir módulos duplicados.
Outro erro comum é tentar fazer shimming em módulos que usam chamadas require síncronas de CommonJS em contexto dinâmico. O ProvidePlugin processa apenas identificadores estáticos, portanto referências dinâmicas devem ser substituídas manualmente ou com NormalModuleReplacementPlugin.
Uma configuração incorreta de shimming pode levar a um aumento significativo do tamanho do bundle. Se o ProvidePlugin estiver configurado para dezenas de variáveis globais, o Webpack inserirá as importações correspondentes em todos os arquivos do projeto, independentemente de essas variáveis serem usadas em cada arquivo específico. Isso cria código redundante, especialmente em projetos grandes com milhares de módulos.
Para diagnosticar problemas com shimming, use o webpack-bundle-analyzer — uma ferramenta para visualizar a composição do bundle. Se o jQuery ou outra biblioteca aparecer no bundle várias vezes, provavelmente versões diferentes estão em conflito ou o ProvidePlugin está configurado para vários identificadores que apontam para versões diferentes do pacote. A solução é unificar as versões das dependências via resolve.alias e verificar se todos os identificadores com shim apontam para o mesmo módulo.
Antes de aplicar o shimming, avalie a possibilidade de atualizar a biblioteca para uma versão que suporte o sistema modular. Muitos pacotes legados têm alternativas modernas que não exigem shimming. Por exemplo, plugins de jQuery podem ser substituídos por APIs nativas do navegador: $.ajax → fetch, $.each → Array.forEach. A refatoração traz benefício de longo prazo na manutenção, enquanto o shimming é uma solução temporária que complica a configuração.
Se a atualização não for possível, considere o NormalModuleReplacementPlugin, que permite substituir um módulo por outro no nível de resolução sem alterar o código-fonte. Esse plugin funciona na etapa de construção do grafo de dependências, antes da aplicação dos loaders, e processa todas as referências ao módulo independentemente do contexto. É uma solução mais limpa para substituir bibliotecas inteiras do que loaders pontuais.
Com o desenvolvimento dos ES modules nativos nos navegadores e o surgimento dos import maps, alguns cenários de shimming podem ser resolvidos sem Webpack. Import maps permitem remapear nomes de módulos dinamicamente no nível do navegador, sem etapa de build. No entanto, essa abordagem não é suportada no React Native e em outros ambientes sem ESM de navegador, portanto o shimming via Webpack permanece relevante para builds de produção que exigem controle total sobre as dependências e suas versões. A escolha entre import maps e shims do Webpack depende da plataforma de destino e dos requisitos de compatibilidade com navegadores antigos.
Perguntas frequentes
Shimming adiciona código para garantir compatibilidade, enquanto o tree shaking remove código não utilizado. Essas técnicas são opostas em propósito: o shimming aumenta o tamanho do bundle, o tree shaking o reduz. Em um build de produção, ambas são aplicadas em sequência.
Sim, o shimming existe como técnica independente do Webpack — por exemplo, por meio de scripts globais no HTML ou por meio de ES modules com reexportação. No entanto, o Webpack fornece as ferramentas de automação mais convenientes: ProvidePlugin e loaders que não exigem alterações manuais no código.
ProvidePlugin não afeta a velocidade do build porque trabalha na etapa de compilação do AST. imports-loader e exports-loader adicionam um pequeno tempo de processamento para cada arquivo. Quando usados em centenas de arquivos, a diferença pode ser de 5–15% do tempo total do build.
Se todas as dependências suportam ES modules e o sistema modular, o shimming é redundante. Abrir mão do shimming simplifica a configuração, reduz o tamanho do bundle e diminui o risco de conflitos de nomes. Recomenda-se verificar as dependências no caniuse.com.
TypeScript exige declarações de tipos adicionais para variáveis com shim. É necessário adicionar declare const $: any ou instalar os tipos via @types/jquery. O ProvidePlugin insere as importações no nível de JavaScript após a compilação do TypeScript, portanto os tipos são verificados separadamente.
Resumo
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.
Leia também