Shimming : essence, approches et principe de fonctionnement

Auteur : IT Sectr Publié le : 2026-05-19 Temps de lecture : 8 min

Shimming est une technique permettant d'assurer la compatibilité de modules qui attendent certaines variables globales ou certaines APIs. Dans l'écosystème Webpack, le shimming est implémenté via ProvidePlugin, imports-loader et exports-loader, permettant de connecter des bibliothèques legacy sans modifier leur code source. Selon la Webpack Documentation (2026), le shimming reste un outil clé pour l'intégration de plugins jQuery et d'autres dépendances qui ne prennent pas en charge le système modulaire.

L'essentiel

  • Shimming est une technique de remplacement de variables globales et d'APIs pour assurer la compatibilité des modules dans le build.
  • ProvidePlugin importe automatiquement un module lorsqu'il détecte une référence à une variable globale dans le code.
  • imports-loader et exports-loader gèrent la portée des modules en ajoutant ou en modifiant leurs interfaces.
  • Shim diffère du polyfill en ce qu'il n'implémente pas la fonctionnalité manquante, mais redirige les appels existants.
  • Webpack fournit des mécanismes de shimming intégrés sans nécessiter l'installation de paquets supplémentaires.

Qu'est-ce que le Shimming ?

Shimming est une technique logicielle qui intègre une couche de compatibilité entre le code et l'environnement sans modifier le code source du module. Dans le contexte d'un build JavaScript, le shimming résout le problème lorsqu'un module accède à des variables globales (window.$, global.process) qui sont absentes de l'environnement modulaire.

Shim et polyfill : principales différences

Polyfill implémente la fonctionnalité manquante à partir de zéro, en ajoutant de nouvelles capacités à l'environnement. Par exemple, core-js ajoute Array.prototype.flatMap pour les anciens navigateurs. Shim, quant à lui, redirige les appels existants vers des implémentations disponibles ou remplace les objets globaux attendus. Dans Webpack, ProvidePlugin insère automatiquement import $ from 'jquery' partout où une référence à la variable globale $ est rencontrée, sans exiger de modifications du code.

La différence principale réside dans l'objectif. Polyfill ajoute ce qui n'existe pas, tandis que shim rend le code existant compatible avec l'environnement dans lequel il s'exécute. Le choix entre eux dépend du problème à résoudre : absence d'API ou incompatibilité des interfaces.

Comment le Shimming fonctionne dans Webpack

Webpack traite chaque module comme une unité isolée avec sa propre portée. Si une bibliothèque accède à la variable globale jQuery comme window.$, le build échouera avec une erreur, car cette variable n'existe pas dans le contexte modulaire. ProvidePlugin résout le problème à l'étape de compilation : lorsqu'il détecte l'identifiant $ dans le code, le plugin insère automatiquement import $ from 'jquery' au début du fichier.

js
// Code source (le module legacy accède à jQuery global)
$('.element').hide();

// Après le traitement de ProvidePlugin (Webpack insère l'import)
import $ from 'jquery';
$('.element').hide();

En outre, imports-loader permet de spécifier explicitement quelles dépendances un module doit recevoir. Cela est utile lorsqu'une bibliothèque utilise this au niveau supérieur, en s'attendant à ce que this fasse référence à window plutôt qu'à module.exports.

ProvidePlugin : variables globales pour les modules

ProvidePlugin est un plugin intégré de Webpack qui charge automatiquement les modules lorsqu'il détecte des références à des identifiants spécifiés. La configuration est un objet où la clé est le nom de la variable et la valeur est le chemin vers le module et le champ exporté.

Configuration du plugin

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

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

ProvidePlugin prend en charge l'importation partielle via la syntaxe de tableau. Par exemple, [lodash, debounce] importe uniquement la fonction debounce de lodash, ce qui réduit la taille du bundle final. C'est particulièrement important pour les projets mobiles, où chaque kilo-octet affecte le temps de chargement.

imports-loader et exports-loader

imports-loader ajoute les imports nécessaires au début d'un module, tandis que exports-loader définit les valeurs exportées pour les modules qui n'utilisent pas module.exports explicitement. Ces loaders travaillent au niveau de fichiers individuels, et non globalement comme ProvidePlugin.

Correction des dépendances avec imports-loader

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

exports-loader est utilisé lorsqu'une bibliothèque assigne une valeur à une variable globale mais ne l'exporte pas via le système de modules. Le loader extrait la valeur et la transforme en export de module, permettant à d'autres modules de l'importer via import.

Configuration du shimming dans la configuration Webpack

Shimming est configuré dans webpack.config.js via une combinaison de plugins et de loaders. Un scénario typique inclut ProvidePlugin pour les variables globales et imports-loader pour les modules spécifiques qui nécessitent un changement de portée.

Configuration de base de Webpack pour le 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',
    }),
  ],
};

Le champ globalObject dans output définit le contexte pour les références à this au niveau supérieur. Pour un environnement navigateur, la valeur 'this' fait référence à window, tandis que pour React Native ou Node.js, elle fait référence à global. Choisir la bonne valeur prévient les erreurs d'exécution dans l'environnement cible.

Erreurs typiques lors du shimming

Shimming est un outil puissant mais dangereux. Une configuration incorrecte entraîne la duplication du code dans le bundle, des conflits de noms et des erreurs d'exécution inattendues. Les développeurs oublient souvent que ProvidePlugin travaille à l'étape de compilation et ne peut pas traiter les références dynamiques aux variables.

Conflits de variables globales

Si deux plugins utilisent des versions différentes de jQuery, ProvidePlugin ne remplacera que l'une d'elles, celle spécifiée en premier dans la configuration. La deuxième bibliothèque recevra une version incompatible, ce qui provoquera des erreurs difficiles à déboguer. La solution consiste à utiliser exports-loader pour chaque bibliothèque avec une version explicite ou à appliquer webpack.IgnorePlugin pour exclure les modules en double.

Une autre erreur courante consiste à tenter de shim des modules qui utilisent des appels require synchrones de CommonJS dans un contexte dynamique. ProvidePlugin ne traite que les identifiants statiques, donc les références dynamiques doivent être remplacées manuellement ou avec NormalModuleReplacementPlugin.

Problèmes de performance en cas de shimming incorrect

Une configuration incorrecte du shimming peut entraîner une augmentation significative de la taille du bundle. Si ProvidePlugin est configuré pour des dizaines de variables globales, Webpack insérera les imports correspondants dans tous les fichiers du projet, indépendamment de l'utilisation de ces variables dans chaque fichier particulier. Cela crée du code redondant, surtout dans les grands projets avec des milliers de modules.

Pour diagnostiquer les problèmes de shimming, utilisez webpack-bundle-analyzer — un outil de visualisation de la composition du bundle. Si jQuery ou une autre bibliothèque apparaît plusieurs fois dans le bundle, des versions différentes entrent probablement en conflit ou ProvidePlugin est configuré pour plusieurs identifiants menant à des versions différentes du paquet. La solution consiste à unifier les versions des dépendances via resolve.alias et à vérifier que tous les identifiants shimmés pointent vers le même module.

Alternatives au shimming : refactorisation et mise à jour des dépendances

Avant d'appliquer le shimming, évaluez la possibilité de mettre à jour la bibliothèque vers une version prenant en charge le système modulaire. De nombreux paquets legacy ont des alternatives modernes qui ne nécessitent pas de shimming. Par exemple, les plugins jQuery peuvent être remplacés par des APIs natives du navigateur : $.ajaxfetch, $.eachArray.forEach. La refactorisation apporte un bénéfice à long terme en matière de maintenance, tandis que le shimming est une solution temporaire qui complique la configuration.

Si la mise à jour n'est pas possible, envisagez NormalModuleReplacementPlugin, qui permet de remplacer un module par un autre au niveau de la résolution sans modifier le code source. Ce plugin fonctionne à l'étape de construction du graphe des dépendances, avant l'application des loaders, et traite toutes les références au module indépendamment du contexte. C'est une solution plus propre pour remplacer des bibliothèques entières que des loaders ponctuels.

Shimming en JavaScript moderne : ESM et import maps

Avec le développement des ES modules natifs dans les navigateurs et l'apparition des import maps, certains scénarios de shimming peuvent être résolus sans Webpack. Les import maps permettent de réaffecter les noms de modules à la volée au niveau du navigateur, sans étape de build. Cependant, cette approche n'est pas prise en charge dans React Native et dans d'autres environnements sans ESM navigateur, donc le shimming via Webpack reste pertinent pour les builds de production qui exigent un contrôle total sur les dépendances et leurs versions. Le choix entre les import maps et les shims Webpack dépend de la plateforme cible et des exigences de compatibilité avec les anciens navigateurs.

Questions fréquentes

En quoi le shimming diffère-t-il du tree shaking ?

Shimming ajoute du code pour assurer la compatibilité, tandis que tree shaking supprime le code inutilisé. Ces techniques ont des objectifs opposés : le shimming augmente la taille du bundle, le tree shaking la réduit. Dans un build de production, les deux sont appliquées successivement.

Peut-on utiliser le shimming sans Webpack ?

Oui, le shimming existe comme technique indépendante de Webpack — par exemple, via des scripts globaux dans le HTML ou via des ES modules avec réexportation. Cependant, Webpack fournit les outils d'automatisation les plus pratiques : ProvidePlugin et des loaders qui ne nécessitent pas de modification manuelle du code.

Comment le shimming affecte-t-il les performances du build ?

ProvidePlugin n'affecte pas la vitesse du build car il travaille à l'étape de compilation de l'AST. imports-loader et exports-loader ajoutent un léger temps de traitement pour chaque fichier. Utilisés sur des centaines de fichiers, la différence peut représenter 5 à 15 % du temps total du build.

Quand faut-il renoncer au shimming ?

Si toutes les dépendances prennent en charge les ES modules et le système modulaire, le shimming est superflu. Renoncer au shimming simplifie la configuration, réduit la taille du bundle et diminue le risque de conflits de noms. Il est recommandé de vérifier les dépendances sur caniuse.com.

Comment le shimming fonctionne avec TypeScript ?

TypeScript exige des déclarations de types supplémentaires pour les variables shimmées. Il est nécessaire d'ajouter declare const $: any ou d'installer les types via @types/jquery. ProvidePlugin insère les imports au niveau JavaScript après la compilation TypeScript, donc les types sont vérifiés séparément.

Résumé

  • Shimming est une technique visant à assurer la compatibilité des modules avec l'environnement en remplaçant les variables globales et les APIs.
  • ProvidePlugin importe automatiquement les modules lorsqu'il détecte des références à des identifiants spécifiés dans le code.
  • imports-loader ajoute des imports au début de fichiers spécifiques, tandis que exports-loader définit les valeurs exportées.
  • Shim diffère du polyfill en ce qu'il n'implémente pas la fonctionnalité, mais redirige les appels vers des implémentations existantes.
  • ProvidePlugin travaille à l'étape de compilation et ne traite pas les références dynamiques aux variables.
  • Le champ globalObject dans output définit le contexte correct pour le niveau supérieur dans l'environnement cible.
  • Utilisez le shimming uniquement pour les modules qui ne prennent pas en charge le système modulaire moderne, et renoncez-y lorsque les ES modules sont entièrement pris en charge.

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi