Shimming — olyan technika, amely biztosítja azoknak a moduloknak a kompatibilitását, amelyek bizonyos globális változókat vagy API-kat várnak. A Webpack ökoszisztémájában a shimming a ProvidePlugin, az imports-loader és az exports-loader segítségével valósul meg, lehetővé téve a legacy könyvtárak csatlakoztatását a forráskódjuk módosítása nélkül. A Webpack Documentation (2026) szerint a shimming továbbra is kulcsfontosságú eszköz a jQuery-bővítmények és más, a modulrendszert nem támogató függőségek integrálásához.
Főbb pontok
Shimming egy szoftveres technika, amely kompatibilitási réteget épít be a kód és a környezet közé anélkül, hogy módosítaná a modul forráskódját. A JavaScript-csomagolás kontextusában a shimming azt a problémát oldja meg, amikor egy modul olyan globális változókhoz (window.$, global.process) fér hozzá, amelyek hiányoznak a moduláris környezetből.
Polyfill a hiányzó funkciót a nulláról valósítja meg, új képességeket adva a környezethez. Például a core-js Array.prototype.flatMap-et ad hozzá a régi böngészőkhöz. A shim viszont a meglévő hívásokat irányítja át az elérhető implementációkra, vagy lecseréli a várt globális objektumokat. A Webpackben a ProvidePlugin automatikusan beszúrja az import $ from 'jquery' sort mindenhol, ahol a $ globális változóra történő hivatkozás fordul elő, anélkül hogy módosításra lenne szükség a kódban.
A fő különbség a célban van. A polyfill azt adja hozzá, ami nincs, a shim pedig a meglévő kódot teszi kompatibilissé azzal a környezettel, amelyben fut. A kettő közötti választás attól függ, hogy milyen problémát oldunk meg: hiányzik egy API, vagy az interfészek nem kompatibilisek.
Webpack minden modult elszigetelt egységként kezel, saját láthatósági tartománnyal. Ha egy könyvtár a jQuery globális változóhoz window.$ formában fér hozzá, a csomagolás hibával ér véget, mivel ez a változó nem létezik a moduláris kontextusban. A ProvidePlugin a fordítási fázisban oldja meg a problémát: amikor a kódban észleli a $ azonosítót, a bővítmény automatikusan beszúrja az import $ from 'jquery' sort a fájl elejére.
// Forráskód (a legacy modul a globális jQuery-hez fér hozzá)
$('.element').hide();
// A ProvidePlugin általi feldolgozás után (a Webpack importot illeszt be)
import $ from 'jquery';
$('.element').hide();
Emellett az imports-loader lehetővé teszi annak egyértelmű megadását, hogy a modul mely függőségeket kapja meg. Ez akkor hasznos, ha egy könyvtár a legfelső szinten használja a this-t, és azt várja, hogy a this a window-ra vonatkozzon, nem pedig a module.exports-re.
ProvidePlugin — a Webpack beépített bővítménye, amely automatikusan betölti a modulokat, amikor a megadott azonosítókra való hivatkozást észlel. A konfiguráció egy objektum, amelyben a kulcs a változó neve, az érték pedig a modulhoz vezető út és az exportált mező.
// webpack.config.js
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
_: 'lodash',
'window.$': 'jquery',
}),
],
};
ProvidePlugin támogatja a célzott importálást a tömb szintaxis révén. Például a [lodash, debounce] csak a debounce függvényt importálja a lodash-ból, ami csökkenti a végső csomag méretét. Ez különösen fontos a mobil projekteknél, ahol minden kilobájt befolyásolja a betöltési időt.
imports-loader a szükséges importokat adja hozzá a modul elejéhez, az exports-loader pedig az exportált értékeket határozza meg azokhoz a modulokhoz, amelyek nem használják kifejezetten a module.exports-et. Ezek a loaderek az egyes fájlok szintjén működnek, nem globálisan, mint a ProvidePlugin.
// webpack.config.js — az imports-loader konfigurációja
module.exports = {
module: {
rules: [
{
test: /legacy-module\.js$/,
use: [
{
loader: 'imports-loader',
options: {
imports: [
'jquery',
'$',
],
},
},
],
},
],
},
};
exports-loader akkor használatos, ha egy könyvtár értéket rendel egy globális változóhoz, de nem exportálja azt a modulrendszeren keresztül. A loader kinyeri az értéket, és moduláris exporttá alakítja, így más modulok az import révén importálhatják.
Shimming a webpack.config.js fájlban, a bővítmények és loaderek kombinációjával állítható be. Egy tipikus forgatókönyv tartalmazza a ProvidePlugin-t a globális változókhoz és az imports-loader-t azokhoz a konkrét modulokhoz, amelyek a láthatósági tartomány módosítását igénylik.
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',
}),
],
};
A globalObject mező az output-ban meghatározza a legfelső szintű this hivatkozások kontextusát. Böngészős környezetben a 'this' érték a window-ra, React Native vagy Node.js esetén pedig a global-ra vonatkozik. A megfelelő érték kiválasztása megelőzi a futásidejű hibákat a célkörnyezetben.
Shimming egy hatékony, de veszélyes eszköz. A hibás beállítás a kód megkettőződéséhez, névütközésekhez és váratlan futásidejű hibákhoz vezet a csomagban. A fejlesztők gyakran elfelejtik, hogy a ProvidePlugin a fordítási fázisban működik, és nem tudja feldolgozni a változókra való dinamikus hivatkozásokat.
Ha két bővítmény eltérő jQuery-verziót használ, a ProvidePlugin csak az egyiket szúrja be, mégpedig azt, amelyik elsőként szerepel a konfigurációban. A második könyvtár nem kompatibilis verziót kap, ami nehezen megtalálható hibákat okoz. A megoldás az exports-loader használata minden könyvtárhoz a verzió egyértelmű megadásával, vagy a webpack.IgnorePlugin alkalmazása a duplikált modulok kizárásához.
Egy másik gyakori hiba, ha olyan modulokat próbálnak shimmelni, amelyek dinamikus kontextusban használnak CommonJS szinkron require hívásokat. A ProvidePlugin csak statikus azonosítókat dolgoz fel, ezért a dinamikus hivatkozásokat manuálisan kell lecserélni, vagy a NormalModuleReplacementPlugin-t kell használni.
A shimming hibás beállítása a csomag méretének jelentős növekedéséhez vezethet. Ha a ProvidePlugin tucatnyi globális változóra van beállítva, a Webpack a megfelelő importokat a projekt összes fájljába beszúrja, függetlenül attól, hogy ezeket a változókat az adott fájlban használják-e. Ez felesleges kódot hoz létre, különösen a több ezer modult tartalmazó nagy projektekben.
A shimming problémáinak diagnosztizálásához használja a webpack-bundle-analyzer eszközt, amely a csomag összetételét vizualizálja. Ha a jQuery vagy egy másik könyvtár többször is megjelenik a csomagban, valószínűleg különböző verziók ütköznek, vagy a ProvidePlugin olyan több azonosítóra van beállítva, amelyek a csomag különböző verzióihoz vezetnek. A megoldás a függőségi verziók egységesítése a resolve.alias révén, valamint annak ellenőrzése, hogy minden shimmelt azonosító ugyanarra a modulra mutat.
A shimming alkalmazása előtt mérlegelje a könyvtár olyan verzióra való frissítésének lehetőségét, amely támogatja a modulrendszert. Sok legacy csomagnak van olyan modern alternatívája, amely nem igényel shimmelést. Például a jQuery-bővítmények lecserélhetők a böngésző natív API-jaira: $.ajax → fetch, $.each → Array.forEach. A refaktorálás hosszú távú előnyt jelent a karbantartásban, míg a shimming átmeneti megoldás, amely bonyolítja a konfigurációt.
Ha a frissítés nem lehetséges, fontolja meg a NormalModuleReplacementPlugin-t, amely lehetővé teszi az egyik modul másikkal való lecserélését a feloldás szintjén, a forráskód módosítása nélkül. Ez a bővítmény a függőségi gráf felépítésének fázisában működik, a loaderek alkalmazása előtt, és a kontextustól függetlenül feldolgozza a modulra való összes hivatkozást. Ez tisztább megoldás teljes könyvtárak lecserélésére, mint a célzott loaderek.
A natív ES modulok böngészőkben való fejlődésével és az import maps megjelenésével néhány shimming forgatókönyv Webpack nélkül is megoldható. Az import maps lehetővé teszi a modulnevek menet közbeni átnevezését a böngésző szintjén, csomagolási fázis nélkül. Ez a megközelítés azonban nem támogatott a React Native és más, böngésző ESM nélküli környezetekben, ezért a Webpacken keresztüli shimming továbbra is releváns azoknál a production csomagoknál, ahol teljes ellenőrzésre van szükség a függőségek és azok verziói felett. Az import maps és a Webpack-shimek közötti választás a célplatformtól és a régi böngészőkkel való kompatibilitás követelményeitől függ.
Gyakran ismételt kérdések
Shimming kódot ad hozzá a kompatibilitás biztosításához, a tree shaking pedig eltávolítja a nem használt kódot. Ez a két technika ellentétes célú: a shimming növeli a csomag méretét, a tree shaking csökkenti. A production csomagban mindkettőt egymás után alkalmazzák.
Igen, a shimming a Webpacktől független technikaként is létezik — például HTML-beli globális szkripteken vagy re-exportos ES modulokon keresztül. A Webpack azonban a legkényelmesebb automatizálási eszközöket kínálja: a ProvidePlugin-t és azokat a loadereket, amelyek nem igényelnek kézi kódmódosítást.
ProvidePlugin nem befolyásolja a csomagolás sebességét, mivel az AST-fordítás fázisában működik. Az imports-loader és az exports-loader kis feldolgozási időt adnak hozzá minden fájlhoz. Több száz fájlnál a különbség a teljes csomagolási idő 5–15%-a lehet.
Ha minden függőség támogatja az ES modulokat és a modulrendszert, a shimming felesleges. A shimmingről való lemondás egyszerűsíti a konfigurációt, csökkenti a csomag méretét és a névütközések kockázatát. Javasolt a függőségek ellenőrzése a caniuse.com oldalon.
TypeScript további típusdeklarációkat igényel a shimmelt változókhoz. Hozzá kell adni a declare const $: any sort, vagy telepíteni kell a típusokat a @types/jquery révén. A ProvidePlugin az importokat a TypeScript-fordítás után, JavaScript-szinten szúrja be, ezért a típusokat külön ellenőrzi.
Összegzés
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is