Webpack: einzelne node_modules ausschließen

Für einen Kunden habe ich eine Software geschrieben, die möglichst klein deployed werden muss; klingt schon mal stark nach einem Job für webpack.

Das odbc-Modul hat allerdings Probleme gemacht, wenn dieses mitgepackt wurde – also musste nur dieses ausgeschlossen werden. Da das händische Pflegen einer Liste von Modulen, die gepackt oder nicht gepackt werden sollen, allerdings super nervig klingt, habe ich mir da in der webpack.config.js beholfen.

Das, was ich hier zeige, ist vermutlich alles andere als best practise.

In meiner webpack.config.js habe ich ein Array mit Modulen, von denen ich möchte, dass sie nicht gebundelt werden. Die webpack.config.js liest die package.json aus, löscht alle Elemente die sie bundelt (also logischerweise alles außer das in dem Array), nimmt den type-Key raus da es das Programm zu CommonJS umwandelt und schreibt eine neue package.json in das Zielverzeichnis.

Nach dem Build muss in dem Zielverzeichnis noch npm run install ausgeführt werden, um die nicht gebundelten Elemente wieder reinzuinstallieren.

Meine webpack.config.js sieht wie folgt aus (Achtung: ES6)

import path from 'path';
import fs from 'fs';
import * as url from 'url';

// Helfervariable: da ES6 kein __dirname kennt, lösen wir das selber auf
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));

// Zielverzeichnis für den Build
const targetPath = path.join(__dirname, '..', 'build');

/**
 * Hier pflegen wir alle Module, die raus sollen
 */
var excludeThisModules = [
    '.bin',
    'odbc'
];

/**
 * Umwandeln für webpack
 */
var externals = {};
for(var i = 0; i < excludeThisModules.length; i++)
    externals[excludeThisModules[i]] = 'commonjs '+ excludeThisModules[i];

/**
 * Da wir einige Module übernehmen, andere nicht, patchen wir nun aus der package.json
 * die Module, die webpack mit bundelt. Das sind logischerweise alle, die nicht in dem
 * Array oben genannt werden
 */
// Wir lesen die package.json
var s = fs.readFileSync("./package.json") + "";
s = JSON.parse(s);
// Ich habe das Modul als ES6 geschrieben; webpack wandelt das zu commonjs um.
// Also muss der type-Key aus der package.json gelöscht werden
delete s.type;
// Wir packen für release, also weg mit den devDependencies
delete s.devDependencies;
// Ebenfalls weg mit den Scripten
delete s.scripts;
// Module, die gebundelt werden, rauslöschen
Object.keys(s.dependencies).forEach(function (key) {
    if(excludeThisModules.indexOf(key) !== -1) return;
    delete s.dependencies[key];
});
// Und die package.json in das Ziel-Verzeichnis schreiben
fs.writeFileSync(path.join(targetPath, "package.json"), JSON.stringify(s, null, 2));

export default {
    entry: './'+ s.main, // Lesen wir aus der package.json aus
    target: 'node',
    mode: "production",
    output: {
        path: targetPath,
        filename: s.main // Lesen wir aus der package.json aus
    },
    externals
};

Folgender Befehl startet den Build:

npx webpack --config webpack.config.js

Und im dem Zeilverzeichnis sind dann nur die index.js sowie unsere gepatchte package.json

Wie oben gesagt: noch mal in dem build-Verzeichnis npm run install, sonst fehlen die Module, die wir explizit ausgeschlossen haben.

Kategorie: Javascript

tino-ruge.de wird tino-kuptz.de

Im Laufe des Jahres 2024 wird dieser Blog umziehen. Alle Inhalte werden 1:1 weitergeleitet, nix geht verloren. Neue Domain, alter Autor, alter Inhalt.