2016-07-13 14 views
2

Ich möchte etwas HTML von einer anderen Domain mit require.js holen. Ich weiß, dass CORS-Richtlinien das nicht einfach erlauben. Hinweis: Ich habe den Webserver (mit Access-Control-Allow-Origin "*" und anderen Direktiven) und require.js so weit konfiguriert, dass alle JS- und CSS-Dateien (css mit require-css-Plugin) wie erwartet von der anderen Domäne geladen werden - nur das Holen von HTML macht Probleme. Aber im Browser-Netzwerk-Protokoll kann ich sehen, dass der HTML-Inhalt sogar geladen wird. Dieser Inhalt wird jedoch nicht an die Funktion require übergeben! Der Browser erhält den Inhalt, aber require.js liefert sie nicht als Parameter ...RequireJS text plugin: HTML kann nicht von einer anderen Domain geladen werden

Meine Konfiguration:

requirejs.config({ 
    baseUrl: "http://some.other.domain/", 
    paths: { 
     jquery:  'ext/jquery/jquery.min', 
     htmlTemplate: 'test.html?', 
     siteCss:  '../css/site' 
    }, 
    shim: { 
     htmlTemplate: [ 
      'css!siteCss' 
     ] 
    }, 

    config: { 
     text: {     
      useXhr: function (url, protocol, hostname, port) { 
       return true; 
      } 
     } 
    }, 
    map: { 
     '*': { 
      text: 'ext/require/text', 
      css: 'ext/require/css.min' 
     } 
    } 
}); 


require(['text!htmlTemplate'], function (htmlTemplate) { 
    console.log(htmlTemplate); // prints 'undefined' into the console 
}); 

Zwei Anmerkungen: Die useXhr Konfiguration von require.js text plugin adds “.js” to the file name genommen wird, aber es macht keinen Unterschied, ob es da ist oder nicht. Ich habe einen ? an htmlTemplate Pfad angehängt. Damit wird der .js nicht an die URL angehängt und der Browser lädt den HTML-Inhalt - wie gesagt, leider ohne dass require.js ihn an den Parameter htmlTemplate übergibt.

Was kann ich tun? Ich habe gelesen, dass wenn ich das require.js optimizer benutze, würde die generierte Datei dieses Problem nicht mehr haben (aber das funktioniert ...). Aber ich muss mein JS ohne Optimierung bei jeder Bearbeitung entwickeln.

Update: Eine Lösung gefunden, aber ich würde mich freuen, wenn jemand die "richtige" Lösung bieten kann.

+0

@Louis Ich habe die Frage zu aktualisieren. Es ist jetzt "text! HtmlTemplate" im Request-Aufruf. Wenn ich es in meiner Antwort richtig verstanden habe, könnte ich das Text-Plugin komplett ignorieren, da ich keinen Text mehr herunterlade, sondern ein JS-Modul. Ich frage mich also, warum das Dokument nicht sagt, dass "Text!" Entfernt werden könnte ... Confusing .... – robsch

+0

Es ist mir unklar, warum die Dokumentation auf diese Weise geschrieben ist. Die einzige Hypothese, die ich habe, ist, dass es für maximale Flexibilität geschrieben wurde. Wenn Sie 'text! Foo' haben und mit mehreren Konfigurationen arbeiten, wobei' foo.html' lokal oder 'foo.html' auf einem anderen Server sein kann, müssen Sie keinen Aufruf wie' require ([' Text! foo.html ']) '. Die einzige Sache, die sich ändert, ist die Konfiguration, die Sie RequireJS geben und wie Sie auf die Anfrage 'GET' reagieren (entweder mit dem HTML direkt oder HTML in einem Modul). – Louis

+0

@Louis Ich glaube, ich habe mein Problem gefunden. Eine weitere [Antwort] hinzugefügt (http://stackoverflow.com/a/38369034/57091). – robsch

Antwort

4

Ich habe das eigentliche Problem gefunden! Dieser Teil:

sollte es wirklich tun. Ich fand jedoch heraus, dass es überhaupt nicht angerufen wurde. Stattdessen wurde die Standardimplementierung aufgerufen. Und das kehrte falsch zurück.

Damit es funktioniert, ist es notwendig, die richtigen Schlüssel in der Config-Sektion zu haben, da das Mapping nicht dafür ausgewertet zu werden scheint.

So ist dies die richtige Konfiguration, die HTML-Code aus der anderen Domäne abruft:

requirejs.config({ 
    baseUrl: "http://some.other.domain/", 
    paths: { 
     jquery:  'ext/jquery/jquery.min', 
     htmlTemplate: 'test.html', //      // ---> removed the '?' 
     siteCss:  '../css/site' 
    }, 
    shim: { 
     htmlTemplate: [ 
      'css!siteCss' 
     ] 
    }, 

    config: { 
     'ext/require/text': {        // ---> full path is required!!!    
      useXhr: function (url, protocol, hostname, port) { 
       return true; 
      } 
     } 
    }, 
    map: { 
     '*': { 
      text: 'ext/require/text', 
      css: 'ext/require/css.min' 
     } 
    } 
}); 


require(['text!htmlTemplate'], function (htmlTemplate) { 
    console.log(htmlTemplate); // now prints HTML into the console!!! 
}); 

Halleluja!

Den richtigen Hinweis gefunden here. Eine andere Option könnte sein, den Pfad für Text festzulegen. Zumindest die Konfiguration muss irgendwie eingestellt werden, damit die Funktion aufgerufen wird ...

+1

Ah, ja tatsächlich. Die Namen des 'config'-Teils müssen mit den Modulnamen übereinstimmen, die geladen werden. Ihre Karte sagt "in allen Modulen, wenn das Modul' text' angefordert wird, laden Sie stattdessen das Modul 'ext/require/text'". Meine Empfehlung ist es, 'map' zu löschen und stattdessen' paths' zu verwenden, um 'text' und' css' auf die Pfade der beiden Module abzubilden und 'config' zurück zu' text' zu ändern. Karte wird wirklich verwendet, um Probleme zu umgehen, die von Drittanbietern verursacht werden, was hier nicht notwendig erscheint. Aber ja, was Sie hier haben, ist eine Lösung. – Louis

+0

@Louis Vielen Dank für diesen Hinweis! – robsch

+0

Es gibt auch eine Frage zu [map vs. paths] (http://stackoverflow.com/q/19216580/57091). – robsch

0

Ich denke, ich habe eine Lösung gefunden. Doc of requirejs/text:

Also, wenn die Text-Plugin feststellt, dass die Anforderung für die Ressource auf einer anderen Domäne ist, wird es versuchen, eine „Js“ zuzugreifen Version der Ressource durch einen Script-Tag. GET-Anforderungen für Skript-Tags sind über Domänengrenzen hinweg zulässig. Die .js-Version der Ressource sollte nur ein Skript mit einem Aufruf von define() sein, der eine Zeichenfolge für den Modulwert zurückgibt.

Durch das änderte ich die Konfiguration dazu, so verwendet, um Text wird nicht mehr:

requirejs.config({ 
    baseUrl: "http://some.other.domain/", 
    paths: { 
     jquery:  'ext/jquery/jquery.min', 
     htmlTemplate: 'test.html', // removed the '?' 
     siteCss:  '../css/site' 
    }, 
    shim: { 
     htmlTemplate: [ 
      'css!siteCss' 
     ] 
    }, 
    map:  { 
     '*': { 
      // removed the text plugin 
      css: 'ext/require/css.min' 
     } 
    } 
    // removed the useXhr configuration for the text plugin 
}); 


require(['htmlTemplate'], function (htmlTemplate) { 
    console.log(htmlTemplate); // prints '<div>Here I am!</div>' into the console 
}); 

Jetzt http://some.other.domain/test.html.js geladen wird. Der Gehalt an test.html ist:

define(function() { 
    return '<div>Here I am!</div>'; 
}); 

Also ich die HTML mit einem wenig von JS umgeben - kein Problem für mich. Und jetzt wird htmlTemplate auf die erwartete Zeichenfolge festgelegt. Es ist nicht mehr reines HTML, aber da es eine feste Vorlage ist (d. H. Nicht generiert), kann es akzeptabel sein.

0

Ich bekomme keine 'Access-Control-Allow-Origin'-Header ist auf der angeforderten Ressource vorhanden. Nach dem Hinzufügen des Codes

config: { 
     'ext/re`enter code here`quire/text': {        required!!!    
      useXhr: function (url, protocol, hostname, port) { 
       return true; 
      } 
     } 
    },