Webpack mit SnapSVG

Snap verhält sich ein wenig zickig, wenn man es zusammen mit Webpack verwenden möchte. Diese Default-Konfiguration zeigt, wie es doch geht.

var path = require('path');
var webpack = require('webpack');

var js_path = "src/Resources/js";
var ts_path = "src/Resources/ts";

module.exports = {
    module: {
        rules: [{
                /* Regel für normale JavaScript-Dateien, die sich innerhalb
                von src/Resources/js befinden. Die Dateien werden mittels
                babel-loader auf die letzten 2 Browserversionen "kompatibilisiert". */

                loader: "babel-loader",


                include: [ // Regel gilt nur für diesen Pfad
                    path.resolve(__dirname, js_path),
                ],

                // Nur `.js` and `.jsx` Dateien durch Babel schicken
                test: /\.jsx?$/,

                // Babel-Optionen
                query: {
                    //          plugins: ['transform-runtime'],
                    presets: [
                        ['env', {
                            targets: {
                                "browsers": ["last 2 versions", "ie >= 9"]
                            }
                        }]
                    ],
                }
            },
            {
                /* Regel für TypeScript Dateien, die in src/Resources/ts
                oder innerhalb von node_modules sind.*/
                test: /\.tsx?$/,
                use: 'ts-loader',
                include: [
                    path.resolve(__dirname, ts_path),
                    path.resolve(__dirname, "node_modules"),
                ],
            },

            {
                /* Sonderregel für jquery. Dafür sorgen, dass die jQuery-Symbole
                $ sowie jQuery im globalen Namespace landen. Das ist für
                Skripte, die inline in HTML-Dateien sind, notwendig.
                Über das webpack.ProvidePlugin (Beispiel siehe unten) klappt das
                zwar in .js Dateien aber nicht im inline-js. */
                test: /jquery-[0-9\.]*\.js/,
                use: [{
                        loader: 'expose-loader',
                        options: '$'
                    },
                    {
                        loader: 'expose-loader',
                        options: 'jQuery'
                    },
                ]
            },
            {
                /* Snap im Kompatibilitätsmodus importieren. Snap
                erwartet, dass this auf das aktuelle window zeigt. Zudem enthält die
                index.d.ts keine Moduldefinition. Daher müssen die module.exports
                automatisch ergänzt werden.*/
                test: require.resolve('snapsvg/dist/snap.svg.js'),
                use: [
                    'imports-loader?this=>window,fix=>module.exports=0',
                ],
            },
        ],
    },

    /* Ausgabepfad konfigurieren */
    output: {
        path: path.resolve(__dirname, 'public/js'),
        filename: 'main.js'
    },


    /* Verzeichnisse konfigurieren, in denen die Module gesucht werden.*/
    resolve: {
        modules: [
            'node_modules',
            js_path,
            ts_path
        ],
        extensions: [ '.ts', '.js' ],

        /* Bibliotheken auf die konkrete Version verlinken. */
        alias: {
            'jquery': 'jquery-3.2.1.js',
            'snapsvg': 'snapsvg/dist/snap.svg.js',
        }
    },

    /* Entry-Punkte definieren. Diese Dateien werden auch includet,
    selbst wenn sie von nirgendwo referenziert werden.
    Wird für einen Einsprung von inline-JS in HTML-Dateien benötigt.*/
    entry: [
        './src/Resources/js/filtertable.js',
        './src/Resources/js/jstree.js',
        './src/Resources/js/graph.js',
        'jquery',
        'snapsvg',
    ],

    /* Einstellen, welche Form von Source-Maps erzeugt werden sollen. Siehe
    https://webpack.js.org/configuration/devtool/ */
    devtool: 'source-map',

    plugins: [
        /* Symbole in alles .js Dateien zur Verfügung stellen. Dieses plugin
        wirkt sich NICHT auf inline-javascript aus und wird deshalb hier
        nicht verwendet! */
        /*
                new webpack.ProvidePlugin({
                    '$': "jquery",
                    jQuery: "jquery",
                    'window.$': 'jquery'
                })
                */
    ],
    watchOptions: {
        aggregateTimeout: 300,  // 300ms Verzögerung bei Änderungen um nachfolgende Speichervorgänge zusammenzufassen
        poll: 1000,             // Alle 1000ms auf Änderungen prüfen
        ignored: /node_modules/ // Verzeichnis node_modules ignorieren
    },
};