如何根据获取环境变量动态设置AngularjS基本URL?

时间:2014-01-07 10:30:55

标签: .htaccess angularjs config environment base-url

我有一个开发和生产环境,我的网址不同:

生产:

www.exmaple.com/page

发展:

dev.environment/project/page

我知道我可以使用

在AngularJS中设置基本URL

<base href='/project/' />

但这对我没有帮助。在我加载AngularJS应用程序之前,我获取了一个配置文件(在app.js中,带有.run语句,该语句读取具有环境的变量:

]).run([
  '$rootScope',
  '$http',
  function (
    $rootScope,
    $http
  ) {
    var configDeferred = $q.defer();

    // fetch config and set the API    
    $http.get('config.json').then(function(response) {
      $rootScope.config = response.data;
      configDeferred.resolve();
    });

    // Wait for the config to be loaded, then go to state
    $rootScope.$on('$stateChangeStart', function (event, next, current) {
      event.preventDefault();
      $q.all([configDeferred.promise]).then(function() {
        $state.transitionTo(next.name);
        return;
      });
    });

有没有办法根据AngularJS中提取的配置文件(可能带有.htaccess)动态设置基本URL?

尝试1: 尝试通过.run获取配置,并通过ng-href:

设置基本网址

在我的app.js中编辑以下代码行:

// fetch config and set the API    
$http.get('config.json').then(function(response) {
  $rootScope.config = response.data;
  $rootScope.baseUrl = response.data.baseUrl; // '/project/'
  configDeferred.resolve();
});

并在我的index.html中:

<base ng-href="{{baseUrl}}" />

看起来这不起作用:当我将tag的href属性更改为ng-href时,它会正确加载内容,但会将我的网址更改为dev.environment/page而不是dev.environment/project/page

更新 配置文件:

{
  "mode": "development",
  "baseUrl": "/project/"
}

4 个答案:

答案 0 :(得分:6)

我个人用grunt来做这种事情。

当我运行我的angular-app时,我有多个任务:

> grunt run --target=dev
> grunt run --target=prod
> grunt build --target=dev
> grunt build --target=prod
> etc...

然后grunt在grunt-preprocess模块的帮助下进行字符串替换:

我的constants.tpl.js文件被解析:

[...]
baseUrl:           '/* @echo ENV_WS_URL */',
[...]

并填充了网址。

有无穷无尽的可能性(字符串替换,文件复制等)。

使用grunt执行此操作可确保dev配置文件不会生产,例如..

如果您对此感兴趣,我可以提供更多详细信息,但我只是想向您展示一种不同的方法。

编辑gruntFile示例:

'use strict';

module.exports = function(grunt) {

    /**
     * Retrieving current target
     */
    var target = grunt.option('target') || 'dev';
    var availableTargets = [
        'dev',
        'prod'
    ];

    /**
     * Load environment-specific variables
     */
    var envConfig = grunt.file.readJSON('conf.' + target + '.json');

    /**
     * This is the configuration object Grunt uses to give each plugin its
     * instructions.
     */
    grunt.initConfig({
        env: envConfig,       

        /*****************************************/
        /* Build files to a specific env or mode */
        /*****************************************/
        preprocess: {
            options: {
                context: {
                    ENV_WS_URL: '<%= env.wsUrl %>'
                }
            },
            constants: {
                src: 'constants.tpl.js',
                dest: 'constants.js'
            }
        },

        karma: {
            unit: {
                configFile: '<%= src.karma %>',
                autoWatch: false,
                singleRun: true
            },
            watch: {
                configFile: '<%= src.karma %>',
                autoWatch: true,
                singleRun: false
            }
        }

    });


    /****************/
    /* Plugins load */
    /****************/
    grunt.loadNpmTasks('grunt-preprocess');

    /*******************/
    /* Available tasks */
    /*******************/
    grunt.registerTask('run', 'Run task, launch web server for dev part', ['preprocess:constants']);

};

现在,命令:

> grunt run --target=dev

将使用网址

创建一个新文件

答案 1 :(得分:3)

asumming您创建了一个从服务器获取配置对象的服务

app.run(function($rootScope, yourService){   
    yourService.fetchConfig(function(config){
        $rootScope.baseUrl = config.baseUrl;
   })
});

标记

<html ng-app="yourApp">
<head>
   <base ng-href="{{baseUrl}}">
   ......

注释

  • 如果您的服务使用$ http或$ resource,则应该没问题
  • 如果您使用jQuery ajax调用,则应在将变量设置为范围后运行$ rootScope。$ apply()。

答案 2 :(得分:1)

使用基本网址可能不是最好的事情,因为它可能会搞砸锚标签的功能,并可能导致不想要的导航。您必须从XML文件中读取配置的方法是完美的,这就是我所做的:

1.在初始化角度应用程序之前,请从配置文件中读取变量:

if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else {// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open("GET", "config.xml", false);
xmlhttp.send();
xmlDoc = xmlhttp.responseXML;

让你的config.xml有这样一个字段

<?xml version="1.0" encoding="utf-8" ?>
<config>  
<url>http://dev/ur/</url>
</config>

2.现在在你的应用程序中注入一个常量,我被EddiecCd

引导
var myApp= angular.module("App", ["ui.router"]).constant('BASE_URL',    
  xmlDoc.getElementsByTagName("url")[0].childNodes[0].nodeValue);

3.你可以在应用程序的任何地方使用BASE_URL你需要注入它这就是我用它来避免ui.router.js中的硬编码路径

var routeResolver = function ($stateProvider, $urlRouterProvider,BASE_URL){
  $stateProvider
    .state('home', {
        url: "/Home",
        views: {
            "main-view": {
                templateUrl: BASE_URL+"/views/Home.htm",
                controller: "homeCtrl",
                resolve: {

                }
            }
        }
    })
}
myApp.config(routeResolver);

希望它有助于欢呼!

答案 3 :(得分:0)

我试图解决这个问题,我真的不想把我的基本路径放在一些配置文件中。我们正在与应用程序上的许多开发人员合作,他们每个人都有不同的工作环境最后,我发现了一个我并不感到自豪的解决方案,但它的作用就像一个魅力。它只需要一件事:PHP。

所以不要用你的JS编写基础href,试试这个:

<?php
    $path = dirname($_SERVER['SCRIPT_NAME']);
    $uri = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['SERVER_NAME'].$path.'/';
    echo '<base href="' . $uri . '" />';
?>

如果您的服务器上已有PHP,那么只需将index.html重命名为index.php(如果您有.htaccess,也不要忘记{{1}}。

我知道这个解决方案并不适合所有人,不应该,对于那些已经在服务器上使用PHP的人来说,这只是我的问题解决方案。我希望至少对你们有些人有帮助:))