Sehr spät zum Thread, aber eine Technik, die ich vor Angular verwendet habe, besteht darin, JSON und die Flexibilität von JS zu nutzen, um Sammlungsschlüssel dynamisch zu referenzieren und unveräußerliche Fakten der Umgebung (Hostservername, aktuelle Browsersprache) zu verwenden usw.) als Eingaben zur selektiven Unterscheidung / Bevorzugung von Schlüsselnamen mit Suffix innerhalb einer JSON-Datenstruktur.
Dies bietet nicht nur einen Bereitstellungsumgebungskontext (pro OP), sondern einen beliebigen Kontext (z. B. Sprache), um i18n oder eine andere Varianz bereitzustellen, die gleichzeitig und (idealerweise) innerhalb eines einzelnen Konfigurationsmanifests ohne Duplizierung und lesbar offensichtlich ist.
IN ÜBER 10 LINIEN VANILLA JS
Übermäßig vereinfachtes, aber klassisches Beispiel: Eine API-Endpunkt-Basis-URL in einer JSON-formatierten Eigenschaftendatei, die je nach Umgebung variiert, wobei (Host) der Host-Server ebenfalls variiert:
...
'svcs': {
'VER': '2.3',
'API@localhost': 'http://localhost:9090/',
'API@www.uat.productionwebsite.com': 'https://www.uat.productionwebsite.com:9090/res/',
'API@www.productionwebsite.com': 'https://www.productionwebsite.com:9090/api/res/'
},
...
Ein Schlüssel zur Unterscheidungsfunktion ist einfach der Server-Hostname in der Anforderung.
Dies kann natürlich mit einem zusätzlichen Schlüssel kombiniert werden, der auf den Spracheinstellungen des Benutzers basiert:
...
'app': {
'NAME': 'Ferry Reservations',
'NAME@fr': 'Réservations de ferry',
'NAME@de': 'Fähren Reservierungen'
},
...
Der Umfang der Unterscheidung / Präferenz kann auf einzelne Schlüssel (wie oben) beschränkt werden, wobei der "Basis" -Schlüssel nur überschrieben wird, wenn ein passender Schlüssel + Suffix für die Eingaben in die Funktion vorhanden ist - oder eine gesamte Struktur und diese Struktur selbst rekursiv analysiert für übereinstimmende Diskriminierungs- / Präferenzsuffixe:
'help': {
'BLURB': 'This pre-production environment is not supported. Contact Development Team with questions.',
'PHONE': '808-867-5309',
'EMAIL': 'coder.jen@lostnumber.com'
},
'help@www.productionwebsite.com': {
'BLURB': 'Please contact Customer Service Center',
'BLURB@fr': 'S\'il vous plaît communiquer avec notre Centre de service à la clientèle',
'BLURB@de': 'Bitte kontaktieren Sie unseren Kundendienst!!1!',
'PHONE': '1-800-CUS-TOMR',
'EMAIL': 'customer.service@productionwebsite.com'
},
Wenn also ein besuchender Benutzer der Produktionswebsite die Einstellung für die deutsche ( De- ) Sprache hat, wird die obige Konfiguration wie folgt zusammengefasst:
'help': {
'BLURB': 'Bitte kontaktieren Sie unseren Kundendienst!!1!',
'PHONE': '1-800-CUS-TOMR',
'EMAIL': 'customer.service@productionwebsite.com'
},
Wie sieht eine solche magische Präferenz- / Diskriminierungs-JSON-Umschreibungsfunktion aus? Nicht viel:
// prefer(object,suffix|[suffixes]) by/par/durch storsoc
// prefer({ a: 'apple', a@env: 'banana', b: 'carrot' },'env') -> { a: 'banana', b: 'carrot' }
function prefer(o,sufs) {
for (var key in o) {
if (!o.hasOwnProperty(key)) continue; // skip non-instance props
if(key.split('@')[1]) { // suffixed!
// replace root prop with the suffixed prop if among prefs
if(o[key] && sufs.indexOf(key.split('@')[1]) > -1) o[key.split('@')[0]] = JSON.parse(JSON.stringify(o[key]));
// and nuke the suffixed prop to tidy up
delete o[key];
// continue with root key ...
key = key.split('@')[0];
}
// ... in case it's a collection itself, recurse it!
if(o[key] && typeof o[key] === 'object') prefer(o[key],sufs);
};
};
In unseren Implementierungen, die Angular- und Pre-Angular-Websites enthalten, booten wir die Konfiguration einfach weit vor anderen Ressourcenaufrufen, indem wir den JSON in einen selbstausführenden JS-Abschluss einfügen, einschließlich der Funktion prepare (), und grundlegende Eigenschaften von Hostname und einspeisen Sprachcode (und akzeptiert alle zusätzlichen beliebigen Suffixe, die Sie möglicherweise benötigen):
(function(prefs){ var props = {
'svcs': {
'VER': '2.3',
'API@localhost': 'http://localhost:9090/',
'API@www.uat.productionwebsite.com': 'https://www.uat.productionwebsite.com:9090/res/',
'API@www.productionwebsite.com': 'https://www.productionwebsite.com:9090/api/res/'
},
...
/* yadda yadda moar JSON und bisque */
function prefer(o,sufs) {
// body of prefer function, broken for e.g.
};
// convert string and comma-separated-string to array .. and process it
prefs = [].concat( ( prefs.split ? prefs.split(',') : prefs ) || []);
prefer(props,prefs);
window.app_props = JSON.parse(JSON.stringify(props));
})([location.hostname, ((window.navigator.userLanguage || window.navigator.language).split('-')[0]) ] );
Eine Pre-Angular-Site hätte jetzt ein reduziertes Fenster (keine @ Suffix-Schlüssel) window.app_props , auf das verwiesen werden kann .
Eine Angular-Site kopiert als Bootstrap / Init-Schritt einfach das Dead-Drop-Requisitenobjekt in $ rootScope und zerstört es (optional) aus dem globalen Bereich / Fensterbereich
app.constant('props',angular.copy(window.app_props || {})).run( function ($rootScope,props) { $rootScope.props = props; delete window.app_props;} );
anschließend in Steuerungen einzuspritzen:
app.controller('CtrlApp',function($log,props){ ... } );
oder von Bindungen in Ansichten verwiesen:
<span>{{ props.help.blurb }} {{ props.help.email }}</span>
Vorsichtsmaßnahmen? Das @ -Zeichen ist keine gültige JS / JSON-Variablen- / Schlüsselbenennung, wird jedoch bisher akzeptiert. Wenn dies ein Deal-Breaker ist, ersetzen Sie jede Konvention, die Sie mögen, wie "__" (doppelter Unterstrich), solange Sie sich daran halten.
Die Technik kann serverseitig angewendet, auf Java oder C # portiert werden, aber Ihre Effizienz / Kompaktheit kann variieren.
Alternativ könnte die Funktion / Konvention Teil Ihres Front-End-Kompilierungsskripts sein, sodass der vollständige JSON für alle Umgebungen und alle Sprachen niemals über das Netzwerk übertragen wird.
AKTUALISIEREN
Wir haben die Verwendung dieser Technik weiterentwickelt, um mehrere Suffixe für einen Schlüssel zuzulassen, um nicht gezwungen zu werden, Sammlungen zu verwenden (Sie können dies immer noch tun, so tief Sie möchten) und um die Reihenfolge der bevorzugten Suffixe einzuhalten.
Beispiel (siehe auch jsFiddle ):
var o = { 'a':'apple', 'a@dev':'apple-dev', 'a@fr':'pomme',
'b':'banana', 'b@fr':'banane', 'b@dev&fr':'banane-dev',
'c':{ 'o':'c-dot-oh', 'o@fr':'c-point-oh' }, 'c@dev': { 'o':'c-dot-oh-dev', 'o@fr':'c-point-oh-dev' } };
/*1*/ prefer(o,'dev'); // { a:'apple-dev', b:'banana', c:{o:'c-dot-oh-dev'} }
/*2*/ prefer(o,'fr'); // { a:'pomme', b:'banane', c:{o:'c-point-oh'} }
/*3*/ prefer(o,'dev,fr'); // { a:'apple-dev', b:'banane-dev', c:{o:'c-point-oh-dev'} }
/*4*/ prefer(o,['fr','dev']); // { a:'pomme', b:'banane-dev', c:{o:'c-point-oh-dev'} }
/*5*/ prefer(o); // { a:'apple', b:'banana', c:{o:'c-dot-oh'} }
1/2 (Grundverwendung) bevorzugt '@dev'-Schlüssel, verwirft alle anderen Suffix-Schlüssel
3 bevorzugt '@dev' gegenüber '@fr', bevorzugt '@ dev & fr' gegenüber allen anderen
4 (wie 3, bevorzugt jedoch '@fr' gegenüber '@dev')
5 keine bevorzugten Suffixe, löscht ALLE Suffixeigenschaften
Dies wird erreicht, indem jede Eigenschaft mit Suffix bewertet wird und der Wert einer Eigenschaft mit Suffix auf die Eigenschaft ohne Suffix angehoben wird, wenn über die Eigenschaften iteriert wird und ein höher bewertetes Suffix gefunden wird.
Einige Effizienzvorteile in dieser Version, einschließlich der Beseitigung der Abhängigkeit von JSON für das Deep-Copy und der rekursiven Wiederkehr in Objekte, die die Bewertungsrunde in ihrer Tiefe überstehen:
function prefer(obj,suf) {
function pr(o,s) {
for (var p in o) {
if (!o.hasOwnProperty(p) || !p.split('@')[1] || p.split('@@')[1] ) continue; // ignore: proto-prop OR not-suffixed OR temp prop score
var b = p.split('@')[0]; // base prop name
if(!!!o['@@'+b]) o['@@'+b] = 0; // +score placeholder
var ps = p.split('@')[1].split('&'); // array of property suffixes
var sc = 0; var v = 0; // reset (running)score and value
while(ps.length) {
// suffix value: index(of found suffix in prefs)^10
v = Math.floor(Math.pow(10,s.indexOf(ps.pop())));
if(!v) { sc = 0; break; } // found suf NOT in prefs, zero score (delete later)
sc += v;
}
if(sc > o['@@'+b]) { o['@@'+b] = sc; o[b] = o[p]; } // hi-score! promote to base prop
delete o[p];
}
for (var p in o) if(p.split('@@')[1]) delete o[p]; // remove scores
for (var p in o) if(typeof o[p] === 'object') pr(o[p],s); // recurse surviving objs
}
if( typeof obj !== 'object' ) return; // validate
suf = ( (suf || suf === 0 ) && ( suf.length || suf === parseFloat(suf) ) ? suf.toString().split(',') : []); // array|string|number|comma-separated-string -> array-of-strings
pr(obj,suf.reverse());
}
'ngconstant:development'
in'serve'
- wenn Sie es in config Uhr setzen unter'gruntfile'
sotasks: ['ngconstant:development']
- Sie Neustart nicht benötigt ,grunt serve
wenn Sie die Entwicklung Variablen im gruntfile aktualisieren.