Shimming — en teknik för att säkerställa kompatibilitet hos moduler som förväntar sig vissa globala variabler eller API:er. I Webpack-ekosystemet implementeras shimming genom ProvidePlugin, imports-loader och exports-loader, vilket gör det möjligt att koppla in legacy-bibliotek utan att ändra deras källkod. Enligt Webpack Documentation (2026) förblir shimming ett nyckelverktyg för integrering av jQuery-plugin-program och andra beroenden som inte stöder modulsystemet.
Viktigaste punkterna
Shimming är en programvaruteknik som bygger in ett kompatibilitetslager mellan kod och miljö utan att ändra modulens källkod. I samband med JavaScript-bundling löser shimming problemet när en modul refererar till globala variabler (window.$, global.process) som saknas i den modulära miljön.
Polyfill implementerar den saknade funktionaliteten från grunden och lägger till nya möjligheter i miljön. Till exempel lägger core-js till Array.prototype.flatMap för äldre webbläsare. Shim vidarebefordrar däremot befintliga anrop till tillgängliga implementeringar eller ersätter förväntade globala objekt. I Webpack infogar ProvidePlugin automatiskt import $ from 'jquery' överallt där en referens till den globala variabeln $ förekommer, utan att det krävs ändringar i koden.
Den viktigaste skillnaden ligger i syftet. Polyfill lägger till det som saknas, medan shim gör befintlig kod kompatibel med den miljö där den körs. Valet mellan dem beror på vilket problem som löses: avsaknaden av ett API eller inkompatibilitet mellan gränssnitt.
Webpack behandlar varje modul som en isolerad enhet med eget synlighetsomfång. Om ett bibliotek refererar till den globala variabeln jQuery som window.$ avslutas bygget med ett fel, eftersom denna variabel inte finns i den modulära kontexten. ProvidePlugin löser problemet i kompileringsfasen: när identifieraren $ upptäcks i koden infogar plugin-programmet automatiskt import $ from 'jquery' i början av filen.
// Källkod (legacy-modulen refererar till global jQuery)
$('.element').hide();
// Efter bearbetning av ProvidePlugin (Webpack infogar import)
import $ from 'jquery';
$('.element').hide();
Dessutom gör imports-loader det möjligt att explicit ange vilka beroenden modulen ska få. Detta är användbart när ett bibliotek använder this på den översta nivån och förväntar sig att this refererar till window i stället för module.exports.
ProvidePlugin — en inbyggd Webpack-plugin som automatiskt laddar moduler när en referens till angivna identifierare upptäcks. Konfigurationen är ett objekt där nyckeln är variabelns namn och värdet är sökvägen till modulen och det exporterade fältet.
// webpack.config.js
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
_: 'lodash',
'window.$': 'jquery',
}),
],
};
ProvidePlugin stöder riktad import genom arraysyntax. Till exempel importerar [lodash, debounce] endast funktionen debounce från lodash, vilket minskar storleken på det slutliga paketet. Detta är särskilt viktigt för mobilprojekt där varje kilobyte påverkar laddningstiden.
imports-loader lägger till nödvändiga importer i början av modulen, medan exports-loader anger exporterade värden för moduler som inte explicit använder module.exports. Dessa loaders arbetar på nivån för enskilda filer, inte globalt som ProvidePlugin.
// webpack.config.js — konfiguration av imports-loader
module.exports = {
module: {
rules: [
{
test: /legacy-module\.js$/,
use: [
{
loader: 'imports-loader',
options: {
imports: [
'jquery',
'$',
],
},
},
],
},
],
},
};
exports-loader används när ett bibliotek tilldelar ett värde till en global variabel men inte exporterar det via modulsystemet. Loadern extraherar värdet och omvandlar det till en modulär export, vilket gör att andra moduler kan importera det via import.
Shimming konfigureras i webpack.config.js genom en kombination av plugin-program och loaders. Ett typiskt scenario omfattar ProvidePlugin för globala variabler och imports-loader för specifika moduler som kräver ändring av synlighetsomfånget.
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',
}),
],
};
Fältet globalObject i output anger kontexten för referenser till this på den översta nivån. För webbläsarmiljön refererar värdet 'this' till window och för React Native eller Node.js — till global. Att välja rätt värde förhindrar körtidsfel i målmiljön.
Shimming är ett kraftfullt men farligt verktyg. Felaktig konfiguration leder till duplicerad kod i paketet, namnkonflikter och oväntade körtidsfel. Utvecklare glömmer ofta att ProvidePlugin arbetar i kompileringsfasen och inte kan bearbeta dynamiska referenser till variabler.
Om två plugin-program använder olika versioner av jQuery infogar ProvidePlugin endast den som anges först i konfigurationen. Det andra biblioteket får en inkompatibel version, vilket orsakar fel som är svåra att felsöka. Lösningen är att använda exports-loader för varje bibliotek med explicit angivande av versionen eller att tillämpa webpack.IgnorePlugin för att utesluta duplicerade moduler.
Ett annat vanligt fel är att försöka shimma moduler som använder synkrona CommonJS-anrop require i en dynamisk kontext. ProvidePlugin bearbetar endast statiska identifierare, därför måste dynamiska referenser ersättas manuellt eller så kan NormalModuleReplacementPlugin användas.
Felaktig konfiguration av shimming kan leda till en betydande ökning av paketstorleken. Om ProvidePlugin är konfigurerat för dussintals globala variabler infogar Webpack motsvarande importer i alla projektets filer, oavsett om dessa variabler används i varje specifik fil. Detta skapar onödig kod, särskilt i stora projekt med tusentals moduler.
För att diagnostisera problem med shimming, använd webpack-bundle-analyzer — ett verktyg för att visualisera paketets sammansättning. Om jQuery eller ett annat bibliotek förekommer flera gånger i paketet konflikterar troligen olika versioner, eller så är ProvidePlugin konfigurerat för flera identifierare som leder till olika versioner av paketet. Lösningen är att förena beroendenas versioner via resolve.alias och kontrollera att alla shimmade identifierare pekar på samma modul.
Innan du tillämpar shimming bör du utvärdera möjligheten att uppdatera biblioteket till en version som stöder modulsystemet. Många legacy-paket har moderna alternativ som inte kräver shimming. Till exempel kan jQuery-plugin-program ersättas med webbläsarens inbyggda API:er: $.ajax → fetch, $.each → Array.forEach. Refaktorisering ger en långsiktig fördel i underhållet, medan shimming är en tillfällig lösning som komplicerar konfigurationen.
Om uppdatering inte är möjlig, överväg NormalModuleReplacementPlugin, som gör det möjligt att ersätta en modul med en annan på upplösningsnivån utan att ändra källkoden. Detta plugin-program arbetar i fasen då beroendegrafen byggs, före att loaders tillämpas, och bearbetar alla referenser till modulen oavsett kontext. Det är en renare lösning för att ersätta hela bibliotek än riktade loaders.
Med utvecklingen av inbyggda ES-moduler i webbläsare och framväxten av import maps kan vissa shimming-scenarier lösas utan Webpack. Import maps gör det möjligt att tilldela om modulnamn direkt på webbläsarnivå, utan byggfas. Detta tillvägagångssätt stöds dock inte i React Native och andra miljöer utan webbläsar-ESM, därför förblir shimming via Webpack relevant för produktionsbyggen där full kontroll över beroenden och deras versioner krävs. Valet mellan import maps och Webpack-shims beror på målplattformen och kraven på kompatibilitet med äldre webbläsare.
Vanliga frågor
Shimming lägger till kod för att säkerställa kompatibilitet, medan tree shaking tar bort oanvänd kod. Dessa tekniker är motsatta till syftet: shimming ökar paketstorleken, tree shaking minskar den. I produktionsbyggen tillämpas båda i följd.
Ja, shimming finns som en teknik oberoende av Webpack — till exempel genom globala skript i HTML eller genom ES-moduler med re-export. Webpack erbjuder dock de mest bekväma automatiseringsverktygen: ProvidePlugin och loaders som inte kräver manuella kodändringar.
ProvidePlugin påverkar inte bygghastigheten eftersom det arbetar i AST-kompileringsfasen. imports-loader och exports-loader lägger till lite bearbetningstid för varje fil. När de används på hundratals filer kan skillnaden uppgå till 5–15 % av den totala byggtiden.
Om alla beroenden stöder ES-moduler och modulsystemet är shimming överflödigt. Att avstå från shimming förenklar konfigurationen, minskar paketstorleken och sänker risken för namnkonflikter. Det rekommenderas att kontrollera beroenden på caniuse.com.
TypeScript kräver ytterligare typdeklarationer för shimmade variabler. Du måste lägga till declare const $: any eller installera typerna via @types/jquery. ProvidePlugin infogar importerna på JavaScript-nivå efter TypeScript-kompileringen, därför kontrolleras typerna separat.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också