Angular.js에서 다른 환경을 어떻게 구성합니까?
다른 환경에 대한 구성 변수 / 상수를 어떻게 관리합니까?
이것은 예가 될 수 있습니다.
내 나머지 API는 사용할 수 localhost:7080/myapi/
있지만 Git 버전 제어에서 동일한 코드를 사용하는 친구는 Tomcat에 API를 배포했습니다 localhost:8099/hisapi/
.
다음과 같은 것이 있다고 가정합니다.
angular
.module('app', ['ngResource'])
.constant('API_END_POINT','<local_end_point>')
.factory('User', function($resource, API_END_POINT) {
return $resource(API_END_POINT + 'user');
});
환경에 따라 올바른 API 엔드 포인트 값을 어떻게 동적으로 주입합니까?
PHP에서는 보통 이런 종류의 config.username.xml
파일을 파일로 사용하여 기본 구성 파일 (config.xml)을 사용자 이름으로 인식되는 로컬 환경 구성 파일과 병합합니다. 그러나 JavaScript에서 이런 종류의 것을 관리하는 방법을 모르겠습니까?
스레드에 약간 늦었지만 Grunt를 사용하는 경우에 큰 성공을 거두었습니다 grunt-ng-constant
.
ngconstant
내 구성 섹션은 Gruntfile.js
다음과 같습니다.
ngconstant: {
options: {
name: 'config',
wrap: '"use strict";\n\n{%= __ngModule %}',
space: ' '
},
development: {
options: {
dest: '<%= yeoman.app %>/scripts/config.js'
},
constants: {
ENV: 'development'
}
},
production: {
options: {
dest: '<%= yeoman.dist %>/scripts/config.js'
},
constants: {
ENV: 'production'
}
}
}
사용하는 작업은 ngconstant
다음과 같습니다
grunt.registerTask('server', function (target) {
if (target === 'dist') {
return grunt.task.run([
'build',
'open',
'connect:dist:keepalive'
]);
}
grunt.task.run([
'clean:server',
'ngconstant:development',
'concurrent:server',
'connect:livereload',
'open',
'watch'
]);
});
grunt.registerTask('build', [
'clean:dist',
'ngconstant:production',
'useminPrepare',
'concurrent:dist',
'concat',
'copy',
'cdnify',
'ngmin',
'cssmin',
'uglify',
'rev',
'usemin'
]);
실행 grunt server
하면 다음과 같은 config.js
파일 이 생성됩니다.app/scripts/
"use strict";
angular.module("config", []).constant("ENV", "development");
마지막으로 필요한 모듈에 대한 종속성을 선언합니다.
// the 'config' dependency is generated via grunt
var app = angular.module('myApp', [ 'config' ]);
이제 내 상수는 필요할 때 의존성 주입 될 수 있습니다. 예 :
app.controller('MyController', ['ENV', function( ENV ) {
if( ENV === 'production' ) {
...
}
}]);
한 가지 멋진 솔루션은 모든 환경 별 값을 별도의 각도 모듈로 분리하여 다른 모든 모듈이 의존하는 것입니다.
angular.module('configuration', [])
.constant('API_END_POINT','123456')
.constant('HOST','localhost');
그런 다음 해당 항목이 필요한 모듈은 이에 대한 종속성을 선언 할 수 있습니다.
angular.module('services',['configuration'])
.factory('User',['$resource','API_END_POINT'],function($resource,API_END_POINT){
return $resource(API_END_POINT + 'user');
});
이제 더 멋진 것들에 대해 생각할 수 있습니다.
구성을 포함하는 모듈은 configuration.js로 분리 될 수 있으며 페이지에 포함됩니다.
이 스크립트는 별도의 파일을 git으로 검사하지 않는 한 각자가 쉽게 편집 할 수 있습니다. 그러나 별도의 파일에 있으면 구성을 확인하지 않는 것이 더 쉽습니다. 또한 로컬로 분기 할 수 있습니다.
이제 ANT 또는 Maven과 같은 빌드 시스템을 사용하는 경우 추가 단계에서 API_END_POINT 값에 대한 자리 표시자를 구현할 수 있습니다.이 자리 표시자는 빌드 타임 동안 특정 값으로 대체됩니다.
또는 당신은 당신이 configuration_a.js
있고 configuration_b.js
포함 할 백엔드에서 결정합니다.
들면 꿀꺽의 사용자 단숨에-ng에 상수는 결합 유용 단숨에-CONCAT , 이벤트 스트림 과 yargs .
var concat = require('gulp-concat'),
es = require('event-stream'),
gulp = require('gulp'),
ngConstant = require('gulp-ng-constant'),
argv = require('yargs').argv;
var enviroment = argv.env || 'development';
gulp.task('config', function () {
var config = gulp.src('config/' + enviroment + '.json')
.pipe(ngConstant({name: 'app.config'}));
var scripts = gulp.src('js/*');
return es.merge(config, scripts)
.pipe(concat('app.js'))
.pipe(gulp.dest('app/dist'))
.on('error', function() { });
});
내 구성 폴더에는 다음 파일이 있습니다.
ls -l config
total 8
-rw-r--r--+ 1 .. ci.json
-rw-r--r--+ 1 .. development.json
-rw-r--r--+ 1 .. production.json
그런 다음 실행할 수 있으며 다음 gulp config --env development
과 같이 생성됩니다.
angular.module("app.config", [])
.constant("foo", "bar")
.constant("ngConstant", true);
또한이 사양이 있습니다.
beforeEach(module('app'));
it('loads the config', inject(function(config) {
expect(config).toBeTruthy();
}));
이를 달성하기 위해 AngularJS 환경 플러그인을 사용하는 것이 좋습니다. https://www.npmjs.com/package/angular-environment
예를 들면 다음과 같습니다.
angular.module('yourApp', ['environment']).
config(function(envServiceProvider) {
// set the domains and variables for each environment
envServiceProvider.config({
domains: {
development: ['localhost', 'dev.local'],
production: ['acme.com', 'acme.net', 'acme.org']
// anotherStage: ['domain1', 'domain2'],
// anotherStage: ['domain1', 'domain2']
},
vars: {
development: {
apiUrl: '//localhost/api',
staticUrl: '//localhost/static'
// antoherCustomVar: 'lorem',
// antoherCustomVar: 'ipsum'
},
production: {
apiUrl: '//api.acme.com/v2',
staticUrl: '//static.acme.com'
// antoherCustomVar: 'lorem',
// antoherCustomVar: 'ipsum'
}
// anotherStage: {
// customVar: 'lorem',
// customVar: 'ipsum'
// }
}
});
// run the environment check, so the comprobation is made
// before controllers and services are built
envServiceProvider.check();
});
그런 다음 컨트롤러에서 변수를 다음과 같이 호출 할 수 있습니다.
envService.read('apiUrl');
도움이 되길 바랍니다.
당신은 사용할 수 있습니다 lvh.me:9000
(당신의 AngularJS와 응용 프로그램에 액세스하는 lvh.me
경우 127.0.0.1에 단지 점) 다음 다른 엔드 포인트를 지정하는 lvh.me
호스트입니다 :
app.service("Configuration", function() {
if (window.location.host.match(/lvh\.me/)) {
return this.API = 'http://localhost\\:7080/myapi/';
} else {
return this.API = 'http://localhost\\:8099/hisapi/';
}
});
그런 다음 구성 서비스를 삽입 Configuration.API
하고 API에 액세스해야 할 때마다 사용 하십시오.
$resource(Configuration.API + '/endpoint/:id', {
id: '@id'
});
약간 어색한 상황이지만 약간 다른 상황에도 불구하고 나에게 잘 작동합니다 (API 엔드 포인트는 생산 및 개발이 다릅니다).
우리는 또한 이런 식으로 할 수 있습니다.
(function(){
'use strict';
angular.module('app').service('env', function env() {
var _environments = {
local: {
host: 'localhost:3000',
config: {
apiroot: 'http://localhost:3000'
}
},
dev: {
host: 'dev.com',
config: {
apiroot: 'http://localhost:3000'
}
},
test: {
host: 'test.com',
config: {
apiroot: 'http://localhost:3000'
}
},
stage: {
host: 'stage.com',
config: {
apiroot: 'staging'
}
},
prod: {
host: 'production.com',
config: {
apiroot: 'production'
}
}
},
_environment;
return {
getEnvironment: function(){
var host = window.location.host;
if(_environment){
return _environment;
}
for(var environment in _environments){
if(typeof _environments[environment].host && _environments[environment].host == host){
_environment = environment;
return _environment;
}
}
return null;
},
get: function(property){
return _environments[this.getEnvironment()].config[property];
}
}
});
})();
그리고에서 controller/service
의존성을 주입하고 액세스 할 속성으로 get 메소드를 호출 할 수 있습니다.
(function() {
'use strict';
angular.module('app').service('apiService', apiService);
apiService.$inject = ['configurations', '$q', '$http', 'env'];
function apiService(config, $q, $http, env) {
var service = {};
/* **********APIs **************** */
service.get = function() {
return $http.get(env.get('apiroot') + '/api/yourservice');
};
return service;
}
})();
$http.get(env.get('apiroot')
호스트 환경에 따라 URL을 반환합니다.
좋은 질문!
한 가지 해결책은 config.xml 파일을 계속 사용하고 다음과 같이 백엔드에서 생성 된 html에 api 엔드 포인트 정보를 제공하는 것입니다 (php의 예).
<script type="text/javascript">
angular.module('YourApp').constant('API_END_POINT', '<?php echo $apiEndPointFromBackend; ?>');
</script>
아마도 예쁜 해결책은 아니지만 효과가 있습니다.
또 다른 해결책은 API_END_POINT
프로덕션 환경에서와 같이 일정한 값 을 유지하고 해당 URL을 로컬 API를 가리 키도록 호스트 파일 만 수정하는 것입니다.
또는 localStorage
다음과 같이 재정의에 사용하는 솔루션 일 수 있습니다.
.factory('User',['$resource','API_END_POINT'],function($resource,API_END_POINT){
var myApi = localStorage.get('myLocalApiOverride');
return $resource((myApi || API_END_POINT) + 'user');
});
스레드에 매우 늦었지만, 내가 Angular 이전에 사용한 기술은 JSON과 JS의 유연성을 활용하여 컬렉션 키를 동적으로 참조하고 환경에 대한 믿을 수없는 사실 (호스트 서버 이름, 현재 브라우저 언어)을 사용하는 것입니다 JSON 데이터 구조 내에서 접미사 키 이름을 선택적으로 식별 / 선호하기위한 입력으로 사용됩니다.
이는 배포 환경 컨텍스트 (OP 당)뿐만 아니라 임의의 컨텍스트 (예 : 언어)를 제공하여 i18n 또는 동시에 필요한 (그리고 이상적으로) 단일 구성 매니페스트 내에서 중복없이 명확하게 읽을 수있는 다른 분산을 제공합니다.
10 라인에 대해 바닐라 JS
지나치게 단순하지만 전형적인 예 : JSON 형식의 속성 파일에있는 API 엔드 포인트 기본 URL (호스트 서버도 변경되는 환경에 따라 다름) :
...
'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/'
},
...
식별 기능의 핵심은 단순히 요청의 서버 호스트 이름입니다.
이것은 자연스럽게 사용자의 언어 설정에 따라 추가 키와 결합 될 수 있습니다.
...
'app': {
'NAME': 'Ferry Reservations',
'NAME@fr': 'Réservations de ferry',
'NAME@de': 'Fähren Reservierungen'
},
...
식별 / 기본 설정의 범위는 개별 키 (위와 같이)로 제한 될 수 있으며 여기서 "기본"키는 함수 입력 또는 전체 구조에 대한 일치하는 키 + 접미사가 있고 해당 구조 자체가있는 경우에만 덮어 씁니다. 일치하는 차별 / 우선 접미사에 대해 재귀 적으로 구문 분석됩니다.
'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'
},
따라서 프로덕션 웹 사이트를 방문하는 사용자에게 독일어 ( de ) 언어 환경 설정이있는 경우 위 구성은 다음과 같이 축소됩니다.
'help': {
'BLURB': 'Bitte kontaktieren Sie unseren Kundendienst!!1!',
'PHONE': '1-800-CUS-TOMR',
'EMAIL': 'customer.service@productionwebsite.com'
},
그러한 마법 선호도 / 차별 JSON 재 작성 기능은 어떻게 생겼습니까? 별로 :
// 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);
};
};
Angular 및 pre-Angular 웹 사이트를 포함하는 구현에서 prefer () 함수를 포함하여 JSON을 자체 실행 JS 클로저 내에 배치하고 호스트 이름 및 기본 속성을 제공하여 다른 리소스 호출보다 먼저 구성을 부트 스트랩합니다. 언어 코드 (필요한 추가 임의 접미사 허용) :
(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]) ] );
사전 Angular 사이트는 이제 접미사 (@ 접미사 키 없음) window.app_props 를 참조하도록 축소 했습니다.
부트 스트랩 / 초기 단계 인 Angular 사이트는 단순히 삭제 된 props 객체를 $ rootScope에 복사하고 선택적으로 전역 / 창 범위에서 파기합니다.
app.constant('props',angular.copy(window.app_props || {})).run( function ($rootScope,props) { $rootScope.props = props; delete window.app_props;} );
이후 컨트롤러에 주입됩니다.
app.controller('CtrlApp',function($log,props){ ... } );
또는 뷰의 바인딩에서 참조됩니다.
<span>{{ props.help.blurb }} {{ props.help.email }}</span>
주의 사항? @ 문자는 유효한 JS / JSON 변수 / 키 이름이 아니지만 지금까지 허용됩니다. 그것이 거래를 깨뜨리는 경우, "__"(이중 밑줄)과 같이 원하는 규칙을 사용하십시오.
이 기술은 서버 측에 적용 할 수 있으며 Java 또는 C #으로 이식 될 수 있지만 효율성 / 컴팩트 성은 다를 수 있습니다.
또는 함수 / 컨벤션이 프론트 엔드 컴파일 스크립트의 일부가 될 수 있으므로 전체 환경 / 모든 언어 JSON이 유선을 통해 전송되지 않습니다.
최신 정보
우리는이 기술의 사용을 키에 여러 접미사를 허용하고, 컬렉션을 강제로 사용하지 않도록하고 (여전히 원하는만큼 깊게 할 수 있음) 선호하는 접미사의 순서를 따르도록 진화했습니다.
예 (또한 작동하는 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 (기본 사용법)은 '@dev'키를 선호하고 다른 모든 접미사 키는 버립니다.
3 은 '@fr'보다 '@dev'를 선호하고 다른 모든 것보다 '@ dev & fr'을 선호합니다
4 (3과 동일하지만 '@dev'보다 '@fr'을 선호 함)
5 선호하는 접미사 없음, 모든 접미사 속성 삭제
각 접미사 속성의 점수를 매기고 속성을 반복하고 더 높은 점수의 접미사를 찾을 때 접미사 속성의 값을 접미사가없는 속성으로 승격시켜이를 수행합니다.
이 버전에서는 딥 카피에 대한 JSON 의존성을 제거하고 깊이에서 스코어링 라운드에서 살아남는 객체로만 되풀이하는 등 일부 버전의 효율성 :
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());
}
당신이 사용하는 경우 브런치를 , 플러그인 Constangular은 서로 다른 환경 변수를 관리하는 데 도움이됩니다.
이 질문 과 답변을 보셨습니까 ?
다음과 같이 앱에 전역 적으로 유효한 값을 설정할 수 있습니다.
app.value('key', 'value');
그런 다음 서비스에서 사용하십시오. 이 코드를 config.js 파일로 옮기고 페이지로드 나 다른 편리한 순간에 실행할 수 있습니다.
참고 URL : https://stackoverflow.com/questions/16339595/how-do-i-configure-different-environments-in-angular-js
'Programing' 카테고리의 다른 글
별도의 변수 사전을 만드는 간단한 방법? (0) | 2020.04.25 |
---|---|
"const"와 "val"의 차이점은 무엇입니까? (0) | 2020.04.25 |
생성자 내에서 가상 함수 호출 (0) | 2020.04.25 |
hashCode ()를 재정의하는 객체의 고유 ID를 얻는 방법은 무엇입니까? (0) | 2020.04.25 |
BeanFactory와 ApplicationContext (0) | 2020.04.25 |