Erstellen Sie individuelle SPA-Bundles mit Webpack

Wie verwende ich Webpack, um unabhängige SPA-Bundles zu erstellen, die möglicherweise sofort geladen werden, wenn mein Benutzer in meinem SPA navigiert?

Ich habe ein Kontaktmodul und ein Aufgabenmodul. Beide haben zwei Abhängigkeiten. Ich möchte, dass WebPack für jedes Paket Pakete erstellt, die bei Bedarf geladen werden.

Der Code ist unten. Das Problem scheint zu sein, dass jeder dieser Einträge als Anwendungseintrittspunkte angesehen wird und daher Webpack-Bootstrap-Code darin eingefügt wird.

Ich habe verschiedene Beispiele mit @ gesehCommonsChunkPlugin aber ich kann keine API-Referenz / Dokumentation dafür finden, und soweit ich vermuten kann, ist das sowieso nicht das, was ich will.

Edit - Diese Dokumente gefundenHie und fügte einen Versuch mit diesem Plugin unten in meiner Bearbeitung hinzu.

Aktuelle Konfiguration

module.exports = {
    entry: {
        contacts: './contacts',
        tasks: './tasks'
    },
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: '[name]-bundle.js'
    }
};

Contacts.js

define(['./ca', './cb'], function(ca, cb){
    var name = 'Contacts';
    alert(ca + ' ' + cb);
});

Tasks.js

define(['./ta', './tb'], function(ta, tb){
    var name = 'TASKS Main';
    alert(ta + ' ' + tb);
});

tasks-bundle.js

/******/ (function(modules) { // webpackBootstrap
/******/    // The module cache
/******/    var installedModules = {};

/******/    // The require function
/******/    function __webpack_require__(moduleId) {

/******/        // Check if module is in cache
/******/        if(installedModules[moduleId])
/******/            return installedModules[moduleId].exports;

/******/        // Create a new module (and put it into the cache)
/******/        var module = installedModules[moduleId] = {
/******/            exports: {},
/******/            id: moduleId,
/******/            loaded: false
/******/        };

/******/        // Execute the module function
/******/        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/        // Flag the module as loaded
/******/        module.loaded = true;

/******/        // Return the exports of the module
/******/        return module.exports;
/******/    }


/******/    // expose the modules object (__webpack_modules__)
/******/    __webpack_require__.m = modules;

/******/    // expose the module cache
/******/    __webpack_require__.c = installedModules;

/******/    // __webpack_public_path__
/******/    __webpack_require__.p = "";

/******/    // Load entry module and return exports
/******/    return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

    var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(3), __webpack_require__(4)], __WEBPACK_AMD_DEFINE_RESULT__ = function(ta, tb){
        var name = 'TASKS Main';
        alert(ta + ' ' + tb);
    }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));

/***/ },
/* 1 */,
/* 2 */,
/* 3 */
/***/ function(module, exports, __webpack_require__) {

    var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function(){
        var name = 'TASKS - A';
        alert('ta');
    }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));

/***/ },
/* 4 */
/***/ function(module, exports, __webpack_require__) {

    var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function(){
        var name = 'TASKS - B';
        alert('tb');
    }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));

/***/ }
/******/ ]);

BEARBEITE

Hier ist mein Versuch Nummer 2 mit dem CommonsChunkPlugin. Ich habe eine Dummy-App erstell

app.js

var module = window.location.hash.split('/')[0];
alert(module);

Dann habe ich alle meine Kontakte und Aufgabendateien in einen Komponentenordner verschoben, sie aber ansonsten in Ruhe gelassen. Meine neue Konfiguration:

module.exports = {
    entry: {
        app: './app'
    },
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: '[name]-bundle.js'
    },
    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: './components/contacts',
            filename: 'contacts-component-bundle.js'
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: './components/tasks',
            filename: 'tasks-component-bundle.js'
        })
    ]
};

Bizarr, jetzt app-bundle.js scheint keinen Webpack-Bootstrap-Code zu haben

webpackJsonp([0,1,2],[
/* 0 */
/***/ function(module, exports) {

    var module = window.location.hash.split('/')[0];
    alert(module);

/***/ }
]);

contacts-components-bundle.js jetzt hat nur diese

webpackJsonp([1,2],[]);

und tasks-components-bundle.js scheint meinen gesamten Webpack-Bootstrap-Code zu haben

/******/ (function(modules) { // webpackBootstrap
/******/    // install a JSONP callback for chunk loading
/******/    var parentJsonpFunction = window["webpackJsonp"];
/******/    window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) {
/******/        // add "moreModules" to the modules object,
/******/        // then flag all "chunkIds" as loaded and fire callback
/******/        var moduleId, chunkId, i = 0, callbacks = [];
/******/        for(;i < chunkIds.length; i++) {
/******/            chunkId = chunkIds[i];
/******/            if(installedChunks[chunkId])
/******/                callbacks.push.apply(callbacks, installedChunks[chunkId]);
/******/            installedChunks[chunkId] = 0;
/******/        }
/******/        for(moduleId in moreModules) {
/******/            modules[moduleId] = moreModules[moduleId];
/******/        }
/******/        if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);
/******/        while(callbacks.length)
/******/            callbacks.shift().call(null, __webpack_require__);
/******/        if(moreModules[0]) {
/******/            installedModules[0] = 0;
/******/            return __webpack_require__(0);
/******/        }
/******/    };

/******/    // The module cache
/******/    var installedModules = {};

/******/    // object to store loaded and loading chunks
/******/    // "0" means "already loaded"
/******/    // Array means "loading", array contains callbacks
/******/    var installedChunks = {
/******/        2:0,
/******/        1:0
/******/    };

/******/    // The require function
/******/    function __webpack_require__(moduleId) {

/******/        // Check if module is in cache
/******/        if(installedModules[moduleId])
/******/            return installedModules[moduleId].exports;

/******/        // Create a new module (and put it into the cache)
/******/        var module = installedModules[moduleId] = {
/******/            exports: {},
/******/            id: moduleId,
/******/            loaded: false
/******/        };

/******/        // Execute the module function
/******/        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/        // Flag the module as loaded
/******/        module.loaded = true;

/******/        // Return the exports of the module
/******/        return module.exports;
/******/    }

/******/    // This file contains only the entry chunk.
/******/    // The chunk loading function for additional chunks
/******/    __webpack_require__.e = function requireEnsure(chunkId, callback) {
/******/        // "0" is the signal for "already loaded"
/******/        if(installedChunks[chunkId] === 0)
/******/            return callback.call(null, __webpack_require__);

/******/        // an array means "currently loading".
/******/        if(installedChunks[chunkId] !== undefined) {
/******/            installedChunks[chunkId].push(callback);
/******/        } else {
/******/            // start chunk loading
/******/            installedChunks[chunkId] = [callback];
/******/            var head = document.getElementsByTagName('head')[0];
/******/            var script = document.createElement('script');
/******/            script.type = 'text/javascript';
/******/            script.charset = 'utf-8';
/******/            script.async = true;

/******/            script.src = __webpack_require__.p + "" + chunkId + "." + ({"0":"app","1":"./components/contacts"}[chunkId]||chunkId) + "-bundle.js";
/******/            head.appendChild(script);
/******/        }
/******/    };

/******/    // expose the modules object (__webpack_modules__)
/******/    __webpack_require__.m = modules;

/******/    // expose the module cache
/******/    __webpack_require__.c = installedModules;

/******/    // __webpack_public_path__
/******/    __webpack_require__.p = "";
/******/ })
/************************************************************************/
/******/ ([]);

Again, ich versuche nur, Webpack zu verwenden, um einen SPA-Proof of Concept zum Laufen zu bringen, mit einer Art root app.js-Einstiegspunkt und einer beliebigen Anzahl von Modulen / Komponenten, die bei Bedarf geladen werden. Dies ist mit Requiredjs trivial einfach, daher muss ich mir vorstellen, dass ich hier einen Schlüssel vermisse, insbesondere bei all den Artikeln, in denen ich gesehen habe, wie großartig Webpack für SPAs ist.

EDIT 2

Per bebraws Antwort unten Ich habe Folgendes versucht:

app.js

var mod = window.location.hash.split('/')[0];
alert(mod);

require.ensure([], function() {
    require('./components/' + mod).show();
});

webpack.config.js

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

module.exports = {
    entry: {
        app: './app'
    },
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: '[name]-bundle.js'
    }
};

Und dann verbleibe ich in meinem Erstellungsordner mit app-bundle.js mit meinem gesamten Bootstrap-Code und meinem app.js-Code und 1.1-bundle.js mitall meines Aufgaben- und Kontaktcodes.

Ich habeebenfall versuchte dies

module.exports = {
    entry: {
        app: './app'
    },
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: '[name]-bundle.js'
    },
    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: './components/contacts',
            filename: 'contacts-component-bundle.js',
            children: true
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: './components/tasks',
            filename: 'tasks-component-bundle.js',
            children: true
        })
    ]
};

Welche ergibt das gleiche wie oben, aber jetztebenfall hat die Dateien "tasks-component-bundle.js" und "contacts-component-bundle.js", die beide "@" habenu etwas Webpack-Bootstrap-Code; Der Aufgaben- und Kontaktcode ist immer noch im 1.1-Bundle enthalten.

Again, ich möchte einfach nur in der Lage sein, Webpack auf die eine oder andere Weise zu informieren, um einzelne Module und ihre Abhängigkeiten für das nachfolgende verzögerte, asynchrone Laden zu bündeln, wenn dies erforderlich ist.

Die endgültige Antwort wurde von Tobias - Webpack-Ersteller - unten gegeben, die ich hier der Nachwelt zur Verfügung stellen werde.

Wirklich dynamisch ist nicht möglich. webpack (in constract to require.js) kompiliert Ihre App vor der Ausführung und hat keinen Zugriff auf Laufzeitinformationen. Dynamisch erfordert im Webpack Tauchen in jedem möglichen Ordner, solange Ihr dynamischer Ausdruck nicht enthält ... Sie sollten sogar in der Lage sein, ihn so zu konfigurieren, dass er Mod + '/' + Mod mit dem ContextReplacementPlugin und ein wenig RegExp-Magie verwendet die RegExp). Standardmäßig würde es zu viele Module enthalten.

Antworten auf die Frage(6)

Ihre Antwort auf die Frage