如何在 Angular.js 中配置不同的环境?

IT技术 javascript angularjs angularjs-service
2021-01-25 19:50:14

您如何管理不同环境的配置变量/常量?

这可能是一个例子:

我的其余 API 可localhost:7080/myapi/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中管理这种东西?

6个回答

我的线程有点晚了,但是如果您使用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");

最后,我声明对任何需要它的module的依赖:

// the 'config' dependency is generated via grunt
var app = angular.module('myApp', [ 'config' ]);

现在我的常量可以在需要的地方进行依赖注入。例如,

app.controller('MyController', ['ENV', function( ENV ) {
  if( ENV === 'production' ) {
    ...
  }
}]);
而不是把'ngconstant:development''serve'-如果你把它放在手表的config下'gruntfile'tasks: ['ngconstant:development']-你不会需要重新启动grunt serve时,您更新的gruntfile发展的变量。
2021-03-22 19:50:14
在 grunt-ng-constant 的 0.5 版本中有更新的 Gruntfile.js 语法:github.com/werk85/grunt-ng-constant/issues/31很好的答案,谢谢!
2021-04-05 19:50:14
我发现还需要将 scripts/config.js 文件包含到 angular 中以找到module,如下所示:<script src="scripts/config.js"></script>
2021-04-05 19:50:14
对于那些使用 gulp 的人,有gulp-ng-constant
2021-04-11 19:50:14
除了在 gruntfile.js 中添加常量之外,您还可以像这样放入单独的文件中: package: grunt.file.readJSON('development.json')
2021-04-12 19:50:14

一个很酷的解决方案可能是将所有特定于环境的值分离到一些单独的 angular module中,所有其他module都依赖于:

angular.module('configuration', [])
       .constant('API_END_POINT','123456')
       .constant('HOST','localhost');

然后你需要这些条目的module可以声明对它的依赖:

angular.module('services',['configuration'])
       .factory('User',['$resource','API_END_POINT'],function($resource,API_END_POINT){
           return $resource(API_END_POINT + 'user');
       });

现在你可以考虑更酷的东西:

包含配置的module可以分离到 configuration.js,它将包含在您的页面中。

只要不将这个单独的文件签入 git,每个人都可以轻松编辑此脚本。但是,如果配置位于单独的文件中,则不签入配置会更容易。此外,您可以在本地分支它。

现在,如果您有一个构建系统,如 ANT 或 Maven,您的进一步步骤可能是为 API_END_POINT 值实现一些占位符,这些占位符将在构建时替换为您的特定值。

或者你有你的configuration_a.jsandconfiguration_b.js并在后端决定要包含哪些。

对于Gulp用户,gulp-ng-constantgulp -concatevent-streamyargs结合使用也很有用

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();
}));
有没有办法用 gulp ng 常量删除依赖数组?我对我的常量没有任何依赖,就像你在这个例如“ngAnimate”中所拥有的那样。如果我不包含它,我会得到一个空的依赖数组作为 angular.module("my.module.config", []) 但我希望输出为 angular.module("my.module.config")。我在 gulp ng 常量中没有看到任何选项,但我看到您可以在 grunt ng 常量包中传递 deps: false 。有什么帮助吗?
2021-04-08 19:50:14

为此,我建议您使用 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');

希望能帮助到你。

@itsHarshad - 那是五年前 - 我不记得那么远了。对不起!
2021-03-14 19:50:14
嗨,胡安·巴勃罗,或者@Mawg,如果你知道的话。在我提出关于 SO 的问题/在 Github 上提出问题之前;如何angular-environment检测环境?即你需要在本地机器/网络服务器上做什么,以便它分别知道它是 dev/prod?
2021-03-21 19:50:14
他如何在开发和生产之间切换?
2021-03-30 19:50:14
再次阅读文档...“ envServiceProvider.check()...将根据给定的域自动设置适当的环境”。所以我认为它会检测当前域并适当地设置环境——是时候测试一下了!
2021-04-01 19:50:14
@StevieP 你有没有发现它是如何自动检测环境的?
2021-04-10 19:50:14

您可以使用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 端点在生产和开发中有所不同)。

所以我想很多时候人们会把事情复杂化。window.location.host对我来说,简单的使用已经绰绰有余了。
2021-04-07 19:50:14