[javascript] 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');
});