Shimming: Wesen, Ansätze und Funktionsprinzip

Autor: IT Sectr Veröffentlicht: 2026-05-19 Lesezeit: 8 Min.

Shimming ist eine Technik zur Sicherstellung der Kompatibilität von Modulen, die bestimmte globale Variablen oder APIs erwarten. Im Webpack-Ökosystem wird Shimming über ProvidePlugin, imports-loader und exports-loader umgesetzt, wodurch Legacy-Bibliotheken ohne Änderung ihres Quellcodes eingebunden werden können. Laut Webpack Documentation (2026) bleibt Shimming ein zentrales Werkzeug zur Integration von jQuery-Plugins und anderer Abhängigkeiten, die kein modulares System unterstützen.

Das Wichtigste

  • Shimming ist eine Technik zur Ersetzung globaler Variablen und APIs, um die Modulkompatibilität im Build zu gewährleisten.
  • ProvidePlugin importiert ein Modul automatisch, wenn im Code ein Zugriff auf eine globale Variable erkannt wird.
  • imports-loader und exports-loader verwalten den Gültigkeitsbereich von Modulen, indem sie deren Schnittstellen ergänzen oder verändern.
  • Shim unterscheidet sich vom polyfill dadurch, dass es keine fehlende Funktionalität implementiert, sondern vorhandene Aufrufe umleitet.
  • Webpack bietet integrierte Shimming-Mechanismen ohne die Notwendigkeit, zusätzliche Pakete zu installieren.

Was ist Shimming?

Shimming ist eine Softwaretechnik, die eine Kompatibilitätsschicht zwischen Code und Umgebung einbettet, ohne den Quellcode des Moduls zu verändern. Im Kontext eines JavaScript-Builds löst Shimming das Problem, wenn ein Modul auf globale Variablen (window.$, global.process) zugreift, die in der modularen Umgebung nicht vorhanden sind.

Shim und polyfill: die wichtigsten Unterschiede

Polyfill implementiert fehlende Funktionalität von Grund auf und fügt der Umgebung neue Fähigkeiten hinzu. Beispielsweise fügt core-js Array.prototype.flatMap für ältere Browser hinzu. Shim hingegen leitet vorhandene Aufrufe an verfügbare Implementierungen weiter oder ersetzt die erwarteten globalen Objekte. In Webpack fügt ProvidePlugin automatisch import $ from 'jquery' überall dort ein, wo ein Zugriff auf die globale Variable $ vorkommt, ohne dass Codeänderungen erforderlich sind.

Der Hauptunterschied liegt im Ziel. Polyfill fügt hinzu, was nicht existiert, während shim vorhandenen Code kompatibel mit der Umgebung macht, in der er ausgeführt wird. Die Wahl zwischen ihnen hängt davon ab, welches Problem gelöst wird: fehlende API oder Inkompatibilität der Schnittstellen.

Wie Shimming in Webpack funktioniert

Webpack behandelt jedes Modul als isolierte Einheit mit eigenem Gültigkeitsbereich. Wenn eine Bibliothek auf die globale Variable jQuery als window.$ zugreift, schlägt der Build mit einem Fehler fehl, da diese Variable im modularen Kontext nicht existiert. ProvidePlugin löst das Problem in der Kompilierungsphase: Wird der Bezeichner $ im Code erkannt, fügt das Plugin automatisch import $ from 'jquery' am Anfang der Datei ein.

js
// Ursprünglicher Code (Legacy-Modul greift auf globales jQuery zu)
$('.element').hide();

// Nach der Verarbeitung durch ProvidePlugin (Webpack fügt Import ein)
import $ from 'jquery';
$('.element').hide();

Zusätzlich ermöglicht imports-loader, explizit anzugeben, welche Abhängigkeiten ein Modul erhalten soll. Dies ist nützlich, wenn eine Bibliothek auf oberster Ebene this verwendet und erwartet, dass this auf window und nicht auf module.exports verweist.

ProvidePlugin: globale Variablen für Module

ProvidePlugin ist ein integriertes Webpack-Plugin, das Module automatisch lädt, wenn Zugriffe auf festgelegte Bezeichner erkannt werden. Die Konfiguration ist ein Objekt, in dem der Schlüssel der Variablenname und der Wert der Pfad zum Modul sowie das exportierte Feld ist.

Konfiguration des Plugins

js
// webpack.config.js
const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      _: 'lodash',
      'window.$': 'jquery',
    }),
  ],
};

ProvidePlugin unterstützt punktgenauen Import über die Array-Syntax. Beispielsweise importiert [lodash, debounce] nur die Funktion debounce aus lodash, wodurch die Größe des endgültigen Bundles reduziert wird. Dies ist besonders wichtig für mobile Projekte, in denen jedes Kilobyte die Ladezeit beeinflusst.

imports-loader und exports-loader

imports-loader fügt die erforderlichen Imports am Anfang eines Moduls hinzu, während exports-loader die exportierten Werte für Module festlegt, die module.exports nicht explizit verwenden. Diese Loader arbeiten auf der Ebene einzelner Dateien und nicht global wie ProvidePlugin.

Behebung von Abhängigkeiten mit imports-loader

js
// webpack.config.js — Konfiguration von imports-loader
module.exports = {
  module: {
    rules: [
      {
        test: /legacy-module\.js$/,
        use: [
          {
            loader: 'imports-loader',
            options: {
              imports: [
                'jquery',
                '$',
              ],
            },
          },
        ],
      },
    ],
  },
};

exports-loader wird verwendet, wenn eine Bibliothek einer globalen Variablen einen Wert zuweist, ihn aber nicht über das modulare System exportiert. Der Loader extrahiert den Wert und macht daraus einen Modul-Export, sodass andere Module ihn über import importieren können.

Shimming in der Webpack-Konfiguration einrichten

Shimming wird in webpack.config.js über eine Kombination aus Plugins und Loadern konfiguriert. Ein typisches Szenario umfasst ProvidePlugin für globale Variablen und imports-loader für bestimmte Module, die eine Änderung des Gültigkeitsbereichs erfordern.

Basis-Konfiguration von Webpack für Shimming

js
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',
    }),
  ],
};

Das Feld globalObject in output legt den Kontext für this-Zugriffe auf oberster Ebene fest. Für eine Browser-Umgebung verweist der Wert 'this' auf window, für React Native oder Node.js auf global. Die Wahl des richtigen Werts verhindert Laufzeitfehler in der Zielumgebung.

Typische Fehler beim Shimming

Shimming ist ein mächtiges, aber gefährliches Werkzeug. Eine falsche Konfiguration führt zu dupliziertem Code im Bundle, Namenskonflikten und unerwarteten Laufzeitfehlern. Entwickler vergessen oft, dass ProvidePlugin in der Kompilierungsphase arbeitet und dynamische Zugriffe auf Variablen nicht verarbeiten kann.

Konflikte bei globalen Variablen

Wenn zwei Plugins unterschiedliche Versionen von jQuery verwenden, ersetzt ProvidePlugin nur eine von ihnen — diejenige, die zuerst in der Konfiguration angegeben ist. Die zweite Bibliothek erhält eine inkompatible Version, was schwer zu debuggende Fehler verursacht. Die Lösung besteht darin, für jede Bibliothek exports-loader mit expliziter Version zu verwenden oder webpack.IgnorePlugin anzuwenden, um doppelte Module auszuschließen.

Ein weiterer häufiger Fehler ist der Versuch, Module zu shimmen, die im dynamischen Kontext synchrone require-Aufrufe von CommonJS verwenden. ProvidePlugin verarbeitet nur statische Bezeichner, daher müssen dynamische Zugriffe manuell oder mit NormalModuleReplacementPlugin ersetzt werden.

Leistungsprobleme bei falschem Shimming

Eine falsche Konfiguration von Shimming kann zu einer erheblichen Vergrößerung des Bundles führen. Wenn ProvidePlugin für Dutzende globaler Variablen konfiguriert ist, fügt Webpack die entsprechenden Imports in alle Projektdateien ein, unabhängig davon, ob diese Variablen in der jeweiligen Datei verwendet werden. Das erzeugt redundanten Code, insbesondere in großen Projekten mit Tausenden von Modulen.

Verwenden Sie zur Diagnose von Shimming-Problemen webpack-bundle-analyzer — ein Werkzeug zur Visualisierung der Bundle-Zusammensetzung. Wenn jQuery oder eine andere Bibliothek mehrfach im Bundle auftaucht, kollidieren wahrscheinlich unterschiedliche Versionen oder ProvidePlugin ist für mehrere Bezeichner konfiguriert, die zu unterschiedlichen Versionen des Pakets führen. Die Lösung besteht darin, die Versionsabhängigkeiten über resolve.alias zu vereinheitlichen und zu prüfen, dass alle geshimten Bezeichner auf dasselbe Modul verweisen.

Alternativen zum Shimming: Refactoring und Aktualisierung von Abhängigkeiten

Bevor Sie Shimming anwenden, prüfen Sie, ob die Bibliothek auf eine Version aktualisiert werden kann, die das modulare System unterstützt. Viele Legacy-Pakete haben moderne Alternativen, die kein Shimming erfordern. Beispielsweise können jQuery-Plugins durch native Browser-APIs ersetzt werden: $.ajaxfetch, $.eachArray.forEach. Refactoring bringt langfristige Vorteile bei der Wartung, während Shimming eine temporäre Lösung ist, die die Konfiguration erschwert.

Wenn eine Aktualisierung nicht möglich ist, ziehen Sie NormalModuleReplacementPlugin in Betracht, das es ermöglicht, ein Modul auf der Auflösungsebene durch ein anderes zu ersetzen, ohne den Quellcode zu ändern. Dieses Plugin arbeitet in der Phase der Erstellung des Abhängigkeitsgraphen, vor Anwendung der Loader, und verarbeitet alle Zugriffe auf das Modul unabhängig vom Kontext. Es ist eine sauberere Lösung für den Austausch ganzer Bibliotheken als punktgenaue Loader.

Shimming im modernen JavaScript: ESM und import maps

Mit der Entwicklung nativer ES-Module in Browsern und dem Aufkommen von import maps können einige Shimming-Szenarien ohne Webpack gelöst werden. Import maps ermöglichen es, Modulnamen zur Laufzeit auf Browser-Ebene neu zuzuordnen, ohne Build-Phase. Dieser Ansatz wird jedoch in React Native und anderen Umgebungen ohne Browser-ESM nicht unterstützt, daher bleibt Shimming über Webpack für Produktions-Builds relevant, die volle Kontrolle über Abhängigkeiten und ihre Versionen erfordern. Die Wahl zwischen import maps und Webpack-Shims hängt von der Zielplattform und den Anforderungen an die Kompatibilität mit älteren Browsern ab.

Häufig gestellte Fragen

Worin unterscheidet sich Shimming von Tree Shaking?

Shimming fügt Code zur Sicherstellung der Kompatibilität hinzu, während Tree Shaking ungenutzten Code entfernt. Diese Techniken verfolgen gegensätzliche Ziele: Shimming vergrößert das Bundle, Tree Shaking verkleinert es. Im Produktions-Build werden beide nacheinander angewendet.

Kann Shimming ohne Webpack verwendet werden?

Ja, Shimming existiert als Technik unabhängig von Webpack — etwa über globale Skripte in HTML oder über ES-Module mit Re-Export. Allerdings bietet Webpack die bequemsten Automatisierungswerkzeuge: ProvidePlugin und Loader, die keine manuelle Codeänderung erfordern.

Wie beeinflusst Shimming die Build-Leistung?

ProvidePlugin beeinflusst die Build-Geschwindigkeit nicht, da es in der AST-Kompilierungsphase arbeitet. imports-loader und exports-loader fügen pro Datei eine geringe Verarbeitungszeit hinzu. Bei der Verwendung auf Hunderten von Dateien kann der Unterschied 5–15 % der gesamten Build-Zeit betragen.

Wann sollte man auf Shimming verzichten?

Wenn alle Abhängigkeiten ES-Module und das modulare System unterstützen, ist Shimming überflüssig. Der Verzicht auf Shimming vereinfacht die Konfiguration, verkleinert das Bundle und senkt das Risiko von Namenskonflikten. Es wird empfohlen, Abhängigkeiten auf caniuse.com zu prüfen.

Wie funktioniert Shimming mit TypeScript?

TypeScript erfordert zusätzliche Typdeklarationen für geshimte Variablen. Es ist notwendig, declare const $: any hinzuzufügen oder Typen über @types/jquery zu installieren. ProvidePlugin fügt Imports nach der TypeScript-Kompilierung auf JavaScript-Ebene ein, daher werden Typen separat geprüft.

Fazit

  • Shimming ist eine Technik zur Sicherstellung der Modulkompatibilität mit der Umgebung durch Ersetzung globaler Variablen und APIs.
  • ProvidePlugin importiert Module automatisch, wenn Zugriffe auf festgelegte Bezeichner im Code erkannt werden.
  • imports-loader fügt Imports am Anfang bestimmter Dateien hinzu, während exports-loader die exportierten Werte festlegt.
  • Shim unterscheidet sich vom polyfill dadurch, dass es keine Funktionalität implementiert, sondern Aufrufe an vorhandene Implementierungen weiterleitet.
  • ProvidePlugin arbeitet in der Kompilierungsphase und verarbeitet keine dynamischen Variablenzugriffe.
  • Das Feld globalObject in output legt den korrekten Kontext für die oberste Ebene in der Zielumgebung fest.
  • Verwenden Sie Shimming nur für Module, die kein modernes modulares System unterstützen, und verzichten Sie darauf, sobald ES-Module vollständig unterstützt werden.

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch