2017-01-03 2 views
0

Ich versuche derzeit, die Leistung einer ziemlich großen Angular JS-Anwendung zu erhöhen, indem Sie von einem großen Stück Javascript-Datei, um 3 - 4 kleinere, die potenziell haben könnte sei sogar faul geladen.Modul Injektion Probleme bei der Kombination von Requirejs Bundles und requirejs Optimierer

Ich verwende die folgenden npm Pakete und Versionen:

grunt-contrib-requirejs: 1.0.0 
grunt: 0.4.5 
requirejs: 2.3.0 

Anfangs gab es ein Grunzen Aufgabe, die alle erforderlichen JavaScript-Dateien haben, enthalten sie alle in einer Datei mit dem requirejs Optimierer verwendet wird, für das Es gab eine Hauptkonfigurationsdatei main.js, wo alle Pfade und Shims für alle spezifischen Pakete definiert wurden (ich kann Beispielkonfigurationen usw. bei Bedarf einfügen).

Jetzt ist die Idee, von dieser großen Datei zu gehen, die Anwendung in 3 - 4 kleinere Javascript-Dateien zu modularisieren, um die Ladezeit zu verkürzen (weil das Laden von 4 kleinen Dateien parallel schneller ist als das Laden von 1 großen Dateien).

Dafür verwenden wir die Option modules in grunt-requirejs und die Option bundles, um alle Module und deren Inhalte zu definieren.

Die Projektstruktur ist wie folgt:

/src/ 
    ./Gruntfile.js 
    ./scripts/ 
    ./app.js 
    ./vendor.js 
    ./app_mini.js 
    ./features/ 
     ./test.service.js 
/dist/ 

Die Grunzen Aufgabe wie folgt definiert ist:

requirejs: { 
    bundle: { 
     options: { 
     baseUrl: '/src', 
     mainConfigFile: '/src/scripts/app.js', 
     bundlesConfigOutFile: 'scripts/app.js', 
     findNestedDependencies: true, 
     dir: '/dist', 
     modules: [ 
      { 
      name: 'scripts/vendor', 
      exclude: [], 
      override: { 
       { 
       paths: { 
        'angular': 'bower/angular/angular', 
        'jquery': 'bower/jquery/dist/jquery' 
       }, 
       bundles: { 
       } 
       }, 
      } 
      }, 

      { 
      name: 'scripts/app', 
      exclude: ['scripts/vendor'], 
      override: { 
       { 
       paths: { 
        'vendor': 'scripts/vendor', 
        'app_mini': 'scripts/app_mini', 
        'testservice': 'scripts/features/test.service' 
       }, 
       bundles: { 
        'vendor': ['angular', 'jquery'] 
       } 
       } 
      } 
     ] 
     } 
    } 
    } 

Der dist-Ordner nach der Ausführung von requirejs: bundle sieht wie folgt aus:

/dist/ 
    ./scripts/ 
    ./app.js 
    ./vendor.js 

So, app_mini und testservice sind in 012 enthaltenund angular und jquery sind in vendor.js enthalten.

Mein app.js im src Ordner sieht wie folgt aus mehr oder weniger:

define('app', 
    [ 
    'angular', 
    'app_mini', 
    'testservice' 
    ], 
    function(
    angular, 
    app_mini, 
    testservice) {} 
); 

require([ 
    'angular', 
    'app_mini', 
    'testservice' 
], function (
    angular, 
    app_mini, 
    testservice 
) { 
    // entry to app 


}, function(err) { 
    console.log('error loading module: ' + err.requireModules); 
}; 

Ich bin für den langen Dateiinhalt sorry, aber es ist unmöglich, das Problem zu beschreiben, ohne es So :), das Problem ist, möchte ich einen zentralen Platz haben, um die gesamte Requirejs Konfiguration für den Optimierer und für die App selbst zu setzen. Offensichtlich sind die Pfade für den Optimierer relativ zum gruntfile-Pfad, und die Pfade für die laufende App sind relativ zur entsprechenden Datei.

Da die Bundle-Konfiguration automatisch von requirejs generiert wird (wegen bundlesConfigOutFile), kann ich nicht wirklich viel über die Namen machen, die dort verwendet werden, da sie aus der Modul-Option gezogen werden.

Die Bündel Config, die in app.js wird generiert und enthalten sieht wie folgt aus:

require.config({ 
    bundles: { 
    'scripts/vendor': [ 
     'angular', 
     'jquery' 
    ], 
    'scripts/app': [ 
     'testservice', 
     'app_mini', 
     'app' 
    ] 
    } 
}); 

nun zuerst, ich hatte das Problem, dass RequireJs wollte Anbieter laden.js durch Pfad scripts/scripts/vendor.js

Um das zu beheben, enthalten ich ein baseUrl = '/' in die require.config von app

Aber jetzt habe ich ein Problem, dass testservice nicht in der Lage ist app_mini und angular zu injizieren, so dass es einen Fehler zu werfen , weil beide Module nicht definiert sind.

Die optimierten app.js im dist-Ordner wie folgt aussieht, vielleicht können Sie das Problem vor Ort:

(function(){ 


define(
    'testservice',[ 
        'angular', 
        'app_mini' 
    ], function(
        angular, 
        app_mini 
   ) { 
        'use strict'; 
  
        app_mini.factory('testservice', TestService); 
  
        function TestService() { 
            var service = { 
                test: test 
            }; 
            return service; 
        }; 
  
        var test = function() { 
            console.log("testservice::test()"); 
        }; 
}); 
  
define('app_mini', 
    [ 
        'angular', 
        'testservice' 
    ], 
  
    function (
        angular, 
        testservice 
   ) { 
        'use strict'; 
  
  
        var module = angular.module(‘some.project’, []); 
  
        module.run(AppRun); 
  
        AppRun.$inject = [ 
            '$rootScope', 
            'testservice' 
        ]; 
        function AppRun($rootScope, testservice) { 
            console.log(“yay, it works”); 
  
            testservice.test(); 
        } 
  
        return module; 
    } 
); 
  
require.config({ 
    bundles: { 
        'scripts/vendor.bundle': [ 
            'angular', 
            'jquery' 
        ], 
        'scripts/app.bundle': [ 
            'testservice', 
            'app_mini', 
            'app' 
        ] 
    } 
}); 
  
require.config({ 
    baseUrl: '/' 
}); 
  
 define(‘app’, 
    [ 
        'angular', 
        'app_mini', 
        'testservice' 
    ], function(
        angular, 
     app_mini, 
     testservice 
){}); 
  
require([ 
        'angular', 
        'app_mini', 
        'testservice' 
    ], function (
        angular, 
        app_mini, 
        testservice 
   ) { 
  
    angular.element().ready(function() { 
        var $html = angular.element(document.getElementsByTagName('html')[0]); 
        angular.bootstrap($html, [app_mini['name']]); 
    }); 
  
}, function (err) { 
    'use strict'; 
  
    console.log('Error loading requirejs-module: ' + err.requireModules); 
}); 
  
define("scripts/app.bundle", function(){}); 
  
})(); 

Antwort

0

Okay, dachte ich, dass wahrscheinlich niemand durch das alles lesen, und ich habe gerade bemerkt, dass ich hätte das wirkliche Problem viel besser aufgezeigt. (Es war, dass app_mini und Winkel durch die Zeit nicht definiert wurden wurden sie injiziert in Testservice)

So das Problem war nur, dass ich vollständig in der Shim Config passieren verpasst, die js erlaubt erfordern Winkel- und jquery einzuwickeln in AMD-Module. Da das fehlte, konnte eckig nie gefunden werden, was app_mini sowie Testservice und damit auch die gesamte App kaputt machte.

So bearbeitete ich den Hersteller Modul Config dementsprechend durch die Shim-Zugabe:

modules: [ 
     { 
     name: 'scripts/vendor', 
     exclude: [], 
     override: { 
      { 
      paths: { 
       'angular': 'bower/angular/angular', 
       'jquery': 'bower/jquery/dist/jquery' 
      }, 
      shim: { 
       angular: { 
       exports: 'angular', 
       deps: ['jquery'] 
       } 
      }, 
      bundles: { 
      } 
      }, 
     } 
     },