Shimming — een techniek om de compatibiliteit te waarborgen van modules die bepaalde globale variabelen of API's verwachten. In het Webpack-ecosysteem wordt shimming geïmplementeerd via ProvidePlugin, imports-loader en exports-loader, waardoor legacy-bibliotheken kunnen worden aangesloten zonder hun broncode te wijzigen. Volgens Webpack Documentation (2026) blijft shimming een belangrijk hulpmiddel voor de integratie van jQuery-plugins en andere afhankelijkheden die geen modulesysteem ondersteunen.
Belangrijkste punten
Shimming is een softwaretechniek die een compatibiliteitslaag tussen code en omgeving inbouwt, zonder de broncode van de module te wijzigen. In de context van JavaScript-bundling lost shimming het probleem op wanneer een module verwijst naar globale variabelen (window.$, global.process) die niet bestaan in de modulaire omgeving.
Polyfill implementeert ontbrekende functionaliteit vanaf nul en voegt nieuwe mogelijkheden toe aan de omgeving. core-js voegt bijvoorbeeld Array.prototype.flatMap toe voor oudere browsers. Shim verwijst bestaande aanroepen echter door naar beschikbare implementaties of vervangt verwachte globale objecten. In Webpack voegt ProvidePlugin automatisch import $ from 'jquery' toe overal waar een verwijzing naar de globale variabele $ voorkomt, zonder dat wijzigingen in de code nodig zijn.
Het belangrijkste verschil zit in het doel. Polyfill voegt toe wat ontbreekt, terwijl shim bestaande code compatibel maakt met de omgeving waarin deze wordt uitgevoerd. De keuze tussen beide hangt af van het probleem dat wordt opgelost: het ontbreken van een API of de incompatibiliteit van interfaces.
Webpack behandelt elke module als een geïsoleerde eenheid met een eigen bereik. Als een bibliotheek naar de globale variabele jQuery verwijst als window.$, eindigt de build met een fout, omdat deze variabele in de modulaire context niet bestaat. ProvidePlugin lost het probleem op tijdens het compileren: zodra de identifier $ in de code wordt gedetecteerd, voegt de plugin automatisch import $ from 'jquery' toe aan het begin van het bestand.
// Broncode (legacy-module verwijst naar globale jQuery)
$('.element').hide();
// Na verwerking door ProvidePlugin (Webpack voegt import toe)
import $ from 'jquery';
$('.element').hide();
Daarnaast stelt imports-loader je in staat om expliciet aan te geven welke afhankelijkheden de module moet ontvangen. Dit is handig wanneer een bibliotheek this op het hoogste niveau gebruikt en verwacht dat this verwijst naar window in plaats van module.exports.
ProvidePlugin is een ingebouwde Webpack-plugin die modules automatisch laadt wanneer een verwijzing naar opgegeven identifiers wordt gedetecteerd. De configuratie is een object waarin de sleutel de naam van de variabele is en de waarde het pad naar de module en het geëxporteerde veld.
// webpack.config.js
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
_: 'lodash',
'window.$': 'jquery',
}),
],
};
ProvidePlugin ondersteunt gerichte import via arraysyntaxis. Zo importeert [lodash, debounce] alleen de functie debounce uit lodash, waardoor de omvang van het uiteindelijke bundelbestand afneemt. Dit is vooral belangrijk voor mobiele projecten, waar elke kilobyte de laadtijd beïnvloedt.
imports-loader voegt de benodigde imports toe aan het begin van de module, terwijl exports-loader de geëxporteerde waarden vaststelt voor modules die module.exports niet expliciet gebruiken. Deze loaders werken op het niveau van afzonderlijke bestanden, niet globaal zoals ProvidePlugin.
// webpack.config.js — configuratie van imports-loader
module.exports = {
module: {
rules: [
{
test: /legacy-module\.js$/,
use: [
{
loader: 'imports-loader',
options: {
imports: [
'jquery',
'$',
],
},
},
],
},
],
},
};
exports-loader wordt gebruikt wanneer een bibliotheek een waarde toewijst aan een globale variabele, maar deze niet via het modulesysteem exporteert. De loader haalt de waarde op en zet deze om in een modulaire export, zodat andere modules deze via import kunnen importeren.
Shimming wordt in webpack.config.js geconfigureerd via een combinatie van plugins en loaders. Een typisch scenario omvat ProvidePlugin voor globale variabelen en imports-loader voor specifieke modules die een wijziging van het bereik vereisen.
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',
}),
],
};
Het veld globalObject in output stelt de context vast voor verwijzingen naar this op het hoogste niveau. Voor browseromgevingen verwijst de waarde 'this' naar window, en voor React Native of Node.js naar global. Het kiezen van de juiste waarde voorkomt runtime-fouten in de doelomgeving.
Shimming is een krachtig maar gevaarlijk hulpmiddel. Onjuiste configuratie leidt tot dubbele code in het bundelbestand, naamconflicten en onverwachte runtime-fouten. Ontwikkelaars vergeten vaak dat ProvidePlugin tijdens het compileren werkt en dynamische verwijzingen naar variabelen niet kan verwerken.
Als twee plugins verschillende versies van jQuery gebruiken, voegt ProvidePlugin slechts een van beide toe, namelijk de versie die als eerste in de configuratie wordt genoemd. De tweede bibliotheek krijgt een incompatibele versie, wat moeilijk te debuggen fouten veroorzaakt. De oplossing is om exports-loader te gebruiken voor elke bibliotheek met een expliciete vermelding van de versie, of webpack.IgnorePlugin toe te passen om dubbele modules uit te sluiten.
Een andere veelgemaakte fout is de poging om modules te shimmen die synchrone CommonJS-aanroepen require in een dynamische context gebruiken. ProvidePlugin verwerkt alleen statische identifiers, dus dynamische verwijzingen moeten handmatig worden vervangen of er kan NormalModuleReplacementPlugin worden gebruikt.
Onjuiste configuratie van shimming kan leiden tot een aanzienlijke toename van de bundelgrootte. Als ProvidePlugin is geconfigureerd voor tientallen globale variabelen, voegt Webpack de bijbehorende imports toe aan alle bestanden van het project, ongeacht of deze variabelen in elk specifiek bestand worden gebruikt. Dit creëert overbodige code, vooral in grote projecten met duizenden modules.
Gebruik webpack-bundle-analyzer — een tool voor de visualisatie van de bundelsamenstelling — om problemen met shimming te diagnosticeren. Als jQuery of een andere bibliotheek meerdere keren in het bundelbestand verschijnt, conflicteren er waarschijnlijk verschillende versies of is ProvidePlugin geconfigureerd voor meerdere identifiers die naar verschillende versies van het pakket leiden. De oplossing is om de versies van afhankelijkheden te verenigen via resolve.alias en te controleren of alle geshimde identifiers naar dezelfde module verwijzen.
Evalueer vóór het toepassen van shimming de mogelijkheid om de bibliotheek bij te werken naar een versie die het modulesysteem ondersteunt. Veel legacy-pakketten hebben moderne alternatieven die geen shimming vereisen. Zo kunnen jQuery-plugins worden vervangen door native browser-API's: $.ajax → fetch, $.each → Array.forEach. Refactoring levert op de lange termijn winst op bij het onderhoud, terwijl shimming een tijdelijke oplossing is die de configuratie compliceert.
Als bijwerken niet mogelijk is, overweeg dan NormalModuleReplacementPlugin, waarmee de ene module door de andere kan worden vervangen op het niveau van het resolveren, zonder de broncode te wijzigen. Deze plugin werkt in de fase van het bouwen van de afhankelijkheidsgrafiek, vóór het toepassen van loaders, en verwerkt alle verwijzingen naar de module ongeacht de context. Dit is een schonere oplossing voor het vervangen van complete bibliotheken dan gerichte loaders.
Met de ontwikkeling van native ES-modules in browsers en de opkomst van import maps kunnen sommige shimming-scenario's zonder Webpack worden opgelost. Import maps maken het mogelijk om modulenamen ter plekke op browserniveau te hertoewijzen, zonder buildfase. Deze aanpak wordt echter niet ondersteund in React Native en andere omgevingen zonder browser-ESM, dus shimming via Webpack blijft relevant voor productie-builds waar volledige controle over afhankelijkheden en hun versies vereist is. De keuze tussen import maps en Webpack-shims hangt af van het doelplatform en de vereisten voor compatibiliteit met oudere browsers.
Veelgestelde vragen
Shimming voegt code toe voor compatibiliteit, terwijl tree shaking ongebruikte code verwijdert. Deze technieken hebben tegengestelde doelen: shimming vergroot de bundel, tree shaking verkleint deze. In productie-builds worden beide achtereenvolgens toegepast.
Ja, shimming bestaat als techniek onafhankelijk van Webpack — bijvoorbeeld via globale scripts in HTML of via ES-modules met re-export. Webpack biedt echter de handigste automatiseringshulpmiddelen: ProvidePlugin en loaders die geen handmatige wijzigingen in de code vereisen.
ProvidePlugin heeft geen invloed op de buildsnelheid, omdat het werkt tijdens de AST-compilatie. imports-loader en exports-loader voegen een kleine verwerkingstijd toe per bestand. Bij gebruik op honderden bestanden kan het verschil 5–15% van de volledige buildtijd bedragen.
Als alle afhankelijkheden ES-modules en het modulesysteem ondersteunen, is shimming overbodig. Afzien van shimming vereenvoudigt de configuratie, verkleint de bundel en verlaagt het risico op naamconflicten. Het wordt aanbevolen om afhankelijkheden te controleren op caniuse.com.
TypeScript vereist extra typeverklaringen voor geshimde variabelen. Je moet declare const $: any toevoegen of de typen installeren via @types/jquery. ProvidePlugin voegt imports toe op JavaScript-niveau na de TypeScript-compilatie, dus typen worden afzonderlijk gecontroleerd.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook