Muy tarde al hilo, pero una técnica que he usado, pre-angular, es aprovechar JSON y la flexibilidad de JS para hacer referencia dinámica a las claves de recopilación, y usar datos inalienables del entorno (nombre del servidor host, idioma actual del navegador) , etc.) como entradas para discriminar selectivamente / preferir nombres de clave con sufijo dentro de una estructura de datos JSON.
Esto proporciona no solo el contexto del entorno de despliegue (por OP) sino cualquier contexto arbitrario (como el lenguaje) para proporcionar i18n o cualquier otra variación requerida simultáneamente e (idealmente) dentro de un único manifiesto de configuración, sin duplicación, y legible obvio.
EN ACERCA DE 10 LÍNEAS DE VAINILLA JS
Ejemplo demasiado simplificado pero clásico: una URL base de punto final de API en un archivo de propiedades con formato JSON que varía según el entorno donde (natch) el servidor host también variará:
...
'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/'
},
...
Una clave para la función de discriminación es simplemente el nombre de host del servidor en la solicitud.
Esto, naturalmente, se puede combinar con una clave adicional basada en la configuración de idioma del usuario:
...
'app': {
'NAME': 'Ferry Reservations',
'NAME@fr': 'Réservations de ferry',
'NAME@de': 'Fähren Reservierungen'
},
...
El alcance de la discriminación / preferencia puede limitarse a teclas individuales (como arriba) donde la tecla "base" solo se sobrescribe si hay una tecla coincidente + sufijo para las entradas a la función, o una estructura completa, y esa estructura misma analizado recursivamente para igualar sufijos de discriminación / preferencia:
'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'
},
Por lo tanto, si un usuario visitante del sitio web de producción tiene una configuración de preferencia de idioma ( de ) alemán , la configuración anterior colapsaría para:
'help': {
'BLURB': 'Bitte kontaktieren Sie unseren Kundendienst!!1!',
'PHONE': '1-800-CUS-TOMR',
'EMAIL': 'customer.service@productionwebsite.com'
},
¿Cómo es una función de reescritura JSON de preferencia / discriminación mágica? No mucho:
// 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);
};
};
En nuestras implementaciones, que incluyen sitios web angulares y pre-angulares, simplemente arrancamos la configuración muy por delante de otras llamadas de recursos colocando el JSON dentro de un cierre JS autoejecutable, incluida la función prefer (), y alimentamos las propiedades básicas del nombre de host y código de idioma (y acepta cualquier sufijo arbitrario adicional que pueda necesitar):
(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]) ] );
Un sitio pre-Angular ahora tendría una ventana contraída (sin @ llaves con sufijo) window.app_props para consultar.
Un sitio angular, como un paso de arranque / inicio, simplemente copia el objeto de utilería muerto en $ rootScope y (opcionalmente) lo destruye desde el alcance global / ventana
app.constant('props',angular.copy(window.app_props || {})).run( function ($rootScope,props) { $rootScope.props = props; delete window.app_props;} );
para ser inyectado posteriormente en los controladores:
app.controller('CtrlApp',function($log,props){ ... } );
o referido desde enlaces en vistas:
<span>{{ props.help.blurb }} {{ props.help.email }}</span>
Advertencias? El carácter @ no es válido JS / JSON variable / nombre de clave, pero hasta ahora aceptado. Si eso es un factor decisivo, sustituya cualquier convención que desee, como "__" (subrayado doble) siempre y cuando se adhiera a ella.
La técnica podría aplicarse del lado del servidor, portada a Java o C #, pero su eficiencia / compacidad puede variar.
Alternativamente, la función / convención podría ser parte de su script de compilación front-end, de modo que el JSON completo sangriento de todo entorno / lenguaje nunca se transmite por cable.
ACTUALIZAR
Hemos desarrollado el uso de esta técnica para permitir múltiples sufijos a una clave, para evitar ser forzado a usar colecciones (aún puede, tan profundamente como desee), y también para honrar el orden de los sufijos preferidos.
Ejemplo (también vea trabajar 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 (uso básico) prefiere las teclas '@dev', descarta todas las demás teclas con sufijo
3 prefiere '@dev' sobre '@fr', prefiere '@ dev & fr' sobre todos los demás
4 (igual que 3 pero prefiere '@fr' sobre '@dev')
5 sin sufijos preferidos, elimina TODAS las propiedades con sufijo
Esto se logra al calificar cada propiedad con sufijo y promover el valor de una propiedad con sufijo a la propiedad sin sufijo al iterar sobre las propiedades y encontrar un sufijo con una puntuación más alta.
Algunas eficiencias en esta versión, incluida la eliminación de la dependencia de JSON para copiar en profundidad, y solo recurrir a objetos que sobreviven a la ronda de puntuación en su profundidad:
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'
en'serve'
- si lo pones en la configuración del reloj bajo'gruntfile'
comotasks: ['ngconstant:development']
- usted no tendrá que reiniciargrunt serve
cuando actualice las variables de desarrollo en el gruntfile.