2016-08-04 35 views
12

Ich habe eine SPA (in Aurelia/TypeScript, aber das sollte nicht wichtig sein), die SystemJS verwendet. Nehmen wir an, es läuft unter http://spa:5000/app.JavaScript Intercept Modul Import

Es lädt manchmal JavaScript-Module wie waterservice/external.js auf Anfrage von einer externen URL wie http://otherhost:5002/fetchmodule?moduleId=waterservice.external.js. Ich benutze SystemJS.import(url), um dies zu tun, und es funktioniert gut.

Aber wenn dieses externe Modul ein anderes Modul mit einem einfachen import { OtherClass } from './other-class'; importieren will, funktioniert dies (verständlich) nicht. Wenn es vom SPA geladen wird, sieht es http://spa:5000/app/other-class.js. In diesem Fall muss ich den Pfad/Standort abfangen, um ihn an http://otherhost:5002/fetchmodule?moduleId=other-class.js umzuleiten.

Hinweis: Die Typoskript-Kompilierung für waterservice/external.ts funktioniert, weil der Typskript-Compiler problemlos ./other-class.ts finden kann. Natürlich kann ich keine absolute URL für den Import verwenden.

Wie kann ich das Laden des Moduls innerhalb eines Moduls abfangen, das ich mit SystemJS importiere?

Ein Ansatz, den ich bereits getestet habe, ist das Hinzufügen einer Zuordnung in der SystemJS-Konfiguration. Wenn ich es wie import { OtherClass } from 'other-class'; importieren und eine Zuordnung wie "other-class": "http://otherhost:5002/fetchmodule?moduleId=other-class" hinzufügen, funktioniert es. Aber wenn dieser Ansatz gut ist, wie kann ich Mapping dynamisch zur Laufzeit hinzufügen?

Andere Ansätze wie eine generische Lade-URL-Interception sind ebenfalls willkommen.


aktualisieren

Ich versuchte SystemJS abfangen als vorschlagen, durch artem wie diese

var systemLoader = SystemJS; 
var defaultNormalize = systemLoader.normalize; 
systemLoader.normalize = function(name, parentName) { 
    console.error("Intercepting", name, parentName); 
    return defaultNormalize(name, parentName); 
} 

Dies würde normalerweise nichts ändern, aber einige Konsolenausgabe produzieren, um zu sehen, was los ist auf. Leider scheint dies etwas zu ändern, da ich einen Fehler bekomme. Uncaught (in Versprechung) TypeError: this.has ist keine Funktion innerhalb system.js.

Dann habe ich versucht, Zuordnungen mit SystemJS.config({map: ...}); hinzuzufügen. Überraschenderweise arbeitet diese Funktion inkrementell, wenn ich sie anrufe, verliert sie nicht die bereits bereitgestellten Mappings. So kann ich tun:

System.config({map: { 
    "other-class": `http://otherhost:5002/fetchModule?moduleId=other-class.js` 
}}); 

Dies funktioniert nicht mit relativen Pfaden (jene, die mit . oder .. beginnen), aber wenn ich die gemeinsam denjenigen in der Wurzel setzen das funktioniert.

Ich würde immer noch lieber das Laden abfangen, um mit mehr Szenarien umgehen zu können, aber im Moment habe ich keine Ahnung, welche has Funktion in dem obigen Ansatz fehlt.

Antwort

2

how can I add mapping dynamically at runtime?

AFAIK SystemJS kann nur

SystemJS.config({ map: { additional-mappings-here ... }}); 

telefonisch jederzeit konfiguriert werden, wenn es bei Ihnen nicht funktioniert, können Sie Loader außer Kraft setzen.Normalisieren und fügen Sie dort ein eigenes Mapping von Modul-IDs zu URLs hinzu. Etwas in diesen Zeilen:

// assuming you have one global SystemJS instance 
var loader = SystemJS; 

var defaultNormalize = loader.normalize; 
loader.normalize = function(name, parentName) { 
    if (parentName == 'your-external-module' && name == 'your-external-submodule') { 
     return Promise.resolve('your-submodule-url'); 
    } else { 
     return defaultNormalize.call(loader, name, parentName); 
    } 
} 

Ich habe keine Ahnung, ob dies mit Typoskript funktioniert oder nicht. Außerdem müssen Sie herausfinden, welche Namen in Ihrem Fall an loader.normalize übergeben werden.

Wenn Sie systemjs builder verwenden, um Ihren Code zu bündeln, müssen Sie diese Überschreibung außerdem dem vom Builder verwendeten Loader hinzufügen (und das ist eine ganz andere Geschichte).

+0

Aufgrund eines Feiertages hatte ich keine Zeit, um diesen Vorschlag jetzt zu sehen, aber werde es tun. Verleihung des Kopfgelds, weil es andernfalls ablaufen würde. Ich könnte jedoch mit Fragen zurückkommen;) – ZoolWay

+0

Danke für Ihre Einsicht. Ich habe die Frage mit beiden Versuchen aktualisiert. Haben Sie eine Idee, warum das Abfangen von "normalisieren" in meinem Fall einen Fehler erzeugt? – ZoolWay

+0

Oh mein Fehler tut mir leid - defaultNormalize braucht 'dieses' Argument: defaultNoramlize.call (loader, name, parentName); – artem