Shimming: essenza, approcci e principio di funzionamento

Autore: IT Sectr Pubblicato: 2026-05-19 Tempo di lettura: 8 min

Shimming è una tecnica per garantire la compatibilità di moduli che si aspettano determinate variabili globali o API. Nell'ecosistema Webpack, lo shimming viene implementato tramite ProvidePlugin, imports-loader ed exports-loader, consentendo di collegare librerie legacy senza modificarne il codice sorgente. Secondo la Webpack Documentation (2026), lo shimming rimane uno strumento chiave per l'integrazione di plugin jQuery e di altre dipendenze che non supportano il sistema modulare.

Punti chiave

  • Shimming è una tecnica di sostituzione di variabili globali e API per garantire la compatibilità dei moduli nel build.
  • ProvidePlugin importa automaticamente un modulo quando rileva un riferimento a una variabile globale nel codice.
  • imports-loader ed exports-loader gestiscono l'ambito dei moduli, aggiungendo o modificando le loro interfacce.
  • Shim si differenzia dal polyfill perché non implementa la funzionalità mancante, ma reindirizza le chiamate esistenti.
  • Webpack fornisce meccanismi di shimming integrati senza la necessità di installare pacchetti aggiuntivi.

Cos'è lo Shimming?

Shimming è una tecnica software che incorpora un livello di compatibilità tra il codice e l'ambiente senza modificare il codice sorgente del modulo. Nel contesto di un build JavaScript, lo shimming risolve il problema quando un modulo accede a variabili globali (window.$, global.process) che sono assenti nell'ambiente modulare.

Shim e polyfill: differenze principali

Polyfill implementa la funzionalità mancante da zero, aggiungendo nuove capacità all'ambiente. Ad esempio, core-js aggiunge Array.prototype.flatMap per i browser più vecchi. Shim, invece, reindirizza le chiamate esistenti verso implementazioni disponibili o sostituisce gli oggetti globali attesi. In Webpack, ProvidePlugin inserisce automaticamente import $ from 'jquery' ovunque venga trovato un riferimento alla variabile globale $, senza richiedere modifiche al codice.

La differenza principale sta nell'obiettivo. Polyfill aggiunge ciò che non esiste, mentre shim rende il codice esistente compatibile con l'ambiente in cui viene eseguito. La scelta tra loro dipende dal problema da risolvere: assenza di API o incompatibilità delle interfacce.

Come funziona lo Shimming in Webpack

Webpack tratta ogni modulo come un'unità isolata con il proprio ambito. Se una libreria accede alla variabile globale jQuery come window.$, il build fallirà con un errore, poiché questa variabile non esiste nel contesto modulare. ProvidePlugin risolve il problema in fase di compilazione: quando rileva l'identificatore $ nel codice, il plugin inserisce automaticamente import $ from 'jquery' all'inizio del file.

js
// Codice sorgente (il modulo legacy accede a jQuery globale)
$('.element').hide();

// Dopo l'elaborazione di ProvidePlugin (Webpack inserisce l'import)
import $ from 'jquery';
$('.element').hide();

Inoltre, imports-loader consente di specificare esplicitamente quali dipendenze deve ricevere un modulo. Ciò è utile quando una libreria usa this a livello superiore, aspettandosi che this faccia riferimento a window e non a module.exports.

ProvidePlugin: variabili globali per i moduli

ProvidePlugin è un plugin integrato di Webpack che carica automaticamente i moduli quando rileva riferimenti a identificatori specificati. La configurazione è un oggetto in cui la chiave è il nome della variabile e il valore è il percorso del modulo e il campo esportato.

Configurazione del plugin

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

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

ProvidePlugin supporta l'importazione parziale tramite la sintassi degli array. Ad esempio, [lodash, debounce] importa solo la funzione debounce da lodash, riducendo le dimensioni del bundle finale. Ciò è particolarmente importante per i progetti mobile, dove ogni kilobyte influisce sui tempi di caricamento.

imports-loader ed exports-loader

imports-loader aggiunge gli import necessari all'inizio di un modulo, mentre exports-loader definisce i valori esportati per i moduli che non usano module.exports esplicitamente. Questi loader lavorano a livello di singoli file, non globalmente come ProvidePlugin.

Correzione delle dipendenze con imports-loader

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

exports-loader viene utilizzato quando una libreria assegna un valore a una variabile globale ma non lo esporta tramite il sistema di moduli. Il loader estrae il valore e lo trasforma in un export di modulo, consentendo ad altri moduli di importarlo tramite import.

Configurazione dello shimming nella configurazione Webpack

Shimming viene configurato in webpack.config.js tramite una combinazione di plugin e loader. Uno scenario tipico include ProvidePlugin per le variabili globali e imports-loader per i moduli specifici che richiedono un cambio di ambito.

Configurazione Webpack di base per lo 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',
    }),
  ],
};

Il campo globalObject in output definisce il contesto per i riferimenti a this a livello superiore. Per un ambiente browser, il valore 'this' fa riferimento a window, mentre per React Native o Node.js fa riferimento a global. Scegliere il valore corretto previene errori di esecuzione nell'ambiente di destinazione.

Errori tipici durante lo shimming

Shimming è uno strumento potente ma pericoloso. Una configurazione errata porta alla duplicazione del codice nel bundle, a conflitti di nomi e a errori di esecuzione imprevisti. Gli sviluppatori dimenticano spesso che ProvidePlugin lavora in fase di compilazione e non può gestire riferimenti dinamici alle variabili.

Conflitti di variabili globali

Se due plugin usano versioni diverse di jQuery, ProvidePlugin sostituirà solo una di esse, quella specificata per prima nella configurazione. La seconda libreria riceverà una versione incompatibile, causando errori difficili da debuggare. La soluzione è usare exports-loader per ogni libreria con una versione esplicita oppure applicare webpack.IgnorePlugin per escludere i moduli duplicati.

Un altro errore comune è tentare di shimare moduli che usano chiamate require sincrone di CommonJS in un contesto dinamico. ProvidePlugin elabora solo identificatori statici, quindi i riferimenti dinamici devono essere sostituiti manualmente o con NormalModuleReplacementPlugin.

Problemi di prestazioni con shimming errato

Una configurazione errata dello shimming può portare a un aumento significativo delle dimensioni del bundle. Se ProvidePlugin è configurato per decine di variabili globali, Webpack inserirà gli import corrispondenti in tutti i file del progetto, indipendentemente dal fatto che quelle variabili siano usate in ogni singolo file. Questo crea codice ridondante, soprattutto in progetti di grandi dimensioni con migliaia di moduli.

Per diagnosticare i problemi con lo shimming, usa webpack-bundle-analyzer — uno strumento per visualizzare la composizione del bundle. Se jQuery o un'altra libreria appare più volte nel bundle, probabilmente versioni diverse sono in conflitto o ProvidePlugin è configurato per più identificatori che portano a versioni diverse del pacchetto. La soluzione è unificare le versioni delle dipendenze tramite resolve.alias e verificare che tutti gli identificatori shimmati puntino allo stesso modulo.

Alternative allo shimming: refactoring e aggiornamento delle dipendenze

Prima di applicare lo shimming, valuta la possibilità di aggiornare la libreria a una versione che supporti il sistema modulare. Molti pacchetti legacy hanno alternative moderne che non richiedono shimming. Ad esempio, i plugin jQuery possono essere sostituiti con API native del browser: $.ajaxfetch, $.eachArray.forEach. Il refactoring offre un vantaggio a lungo termine nella manutenzione, mentre lo shimming è una soluzione temporanea che complica la configurazione.

Se l'aggiornamento non è possibile, considera NormalModuleReplacementPlugin, che consente di sostituire un modulo con un altro a livello di risoluzione senza modificare il codice sorgente. Questo plugin lavora nella fase di costruzione del grafo delle dipendenze, prima dell'applicazione dei loader, e gestisce tutti i riferimenti al modulo indipendentemente dal contesto. È una soluzione più pulita per sostituire intere librerie rispetto ai loader puntuali.

Shimming nel JavaScript moderno: ESM e import maps

Con lo sviluppo dei moduli ES nativi nei browser e l'avvento degli import maps, alcuni scenari di shimming possono essere risolti senza Webpack. Gli import maps consentono di riassegnare i nomi dei moduli al volo a livello di browser, senza fase di build. Tuttavia, questo approccio non è supportato in React Native e in altri ambienti senza ESM del browser, quindi lo shimming tramite Webpack rimane rilevante per i build di produzione che richiedono il controllo completo sulle dipendenze e le loro versioni. La scelta tra import maps e shim di Webpack dipende dalla piattaforma di destinazione e dai requisiti di compatibilità con i browser più vecchi.

Domande frequenti

In cosa lo shimming differisce dal tree shaking?

Shimming aggiunge codice per garantire la compatibilità, mentre tree shaking rimuove il codice inutilizzato. Queste tecniche hanno obiettivi opposti: lo shimming aumenta le dimensioni del bundle, il tree shaking le riduce. In un build di produzione, entrambe vengono applicate in sequenza.

Si può usare lo shimming senza Webpack?

Sì, lo shimming esiste come tecnica indipendente da Webpack — ad esempio, tramite script globali nell'HTML o tramite moduli ES con riesportazione. Tuttavia, Webpack fornisce gli strumenti di automazione più convenienti: ProvidePlugin e loader che non richiedono modifiche manuali al codice.

Come influisce lo shimming sulle prestazioni del build?

ProvidePlugin non influisce sulla velocità del build perché lavora nella fase di compilazione dell'AST. imports-loader ed exports-loader aggiungono un piccolo tempo di elaborazione per ogni file. Quando usati su centinaia di file, la differenza può essere del 5–15% del tempo totale del build.

Quando bisogna rinunciare allo shimming?

Se tutte le dipendenze supportano i moduli ES e il sistema modulare, lo shimming è superfluo. Rinunciare allo shimming semplifica la configurazione, riduce le dimensioni del bundle e diminuisce il rischio di conflitti di nomi. Si consiglia di verificare le dipendenze su caniuse.com.

Come funziona lo shimming con TypeScript?

TypeScript richiede dichiarazioni di tipo aggiuntive per le variabili shimmate. È necessario aggiungere declare const $: any o installare i tipi tramite @types/jquery. ProvidePlugin inserisce gli import a livello JavaScript dopo la compilazione TypeScript, quindi i tipi vengono verificati separatamente.

Sintesi

  • Shimming è una tecnica per garantire la compatibilità dei moduli con l'ambiente sostituendo variabili globali e API.
  • ProvidePlugin importa automaticamente i moduli quando rileva riferimenti a identificatori specificati nel codice.
  • imports-loader aggiunge import all'inizio di file specifici, mentre exports-loader definisce i valori esportati.
  • Shim si differenzia dal polyfill perché non implementa la funzionalità, ma reindirizza le chiamate a implementazioni esistenti.
  • ProvidePlugin lavora in fase di compilazione e non gestisce i riferimenti dinamici alle variabili.
  • Il campo globalObject in output definisce il contesto corretto per il livello superiore nell'ambiente di destinazione.
  • Usa lo shimming solo per i moduli che non supportano il sistema modulare moderno e rinuncia quando i moduli ES sono completamente supportati.

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche