Как установить базовый URL AngularjJS динамически в зависимости от выбранной переменной среды?

У меня есть среда разработки и производства, в которой мой URLотличаются:

производство:

www.exmaple.com/page

развитие:

dev.environmenthttps://stackoverflow.com/project/page

Я знаю, что могу установить базовый URL в AngularJS с помощью

но это нене помогите мне здесь. Перед загрузкой приложения 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;
      });
    });

Есть ли способ динамически установить базовый URL, основанный на извлеченном файле конфигурации в AngularJS (может быть, с .htaccess)?

Попытка 1: Попробуй получить конфиг через.run и установите базовый URL через 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; // 'https://stackoverflow.com/project/'
  configDeferred.resolve();
});

и в моем index.html:


Похоже, это не работает: когда я изменяю атрибут href тега на ng-href, он корректно загружает контент, но изменяет мой URL-адрес наdev.environment/page вместоdev.environmenthttps://stackoverflow.com/project/page

ОБНОВИТЬ: Конфигурационный файл:

{
  "mode": "development",
  "baseUrl": "https://stackoverflow.com/project/"
}
 Daan06 мар. 2014 г., 10:36
Я только добавил это <
 Craig06 мар. 2014 г., 04:23
Можете ли вы показать нам свой config.json?
 charlietfl07 янв. 2014 г., 22:31
Можно'у вас есть серверный код, просто установите переменную в тег скрипта? Или разобрать?location.href
 Daan07 янв. 2014 г., 23:41
1: да 2: забыл скопировать, обновил 3: это обновленный HTML
 Daan07 янв. 2014 г., 23:18
Получение и настройка с помощью тега скрипта - это не тот способ, которым я хочу это делать (я хочу использовать фреймворк). Парсинг location.href - вариант, но опять же, как именно вы это сделаете, используя фреймворк?
 charlietfl07 янв. 2014 г., 13:54
на самом деле не уверен, что подразумевается или что вам нужно помочь с
 Daan07 янв. 2014 г., 22:29
Согласно документации AngularJS, мне нужно установить базовый URL в моем файле index.html (в <база> тег), который загружается сначала, а затем загружается app.js. В app.js у меня есть запрос $ http к файлу конфигурации, который имеет правильную среду и, следовательно, правильный базовый URL, который необходимо установить. Итак, после получения файла конфигурации, мне нужно каким-то образом установить базовый URL
 Daan07 янв. 2014 г., 16:47
Сформулировал вопрос по другому
 charlietfl07 янв. 2014 г., 22:26
до сих пор не ясно, в чем проблема с URL ... может разобратьlocation.href определить существующий URL, если это помогает
 Ilan Frumer07 янв. 2014 г., 23:25
проверяет: (1) является ли ваш атрибут ng-app тегом html? (2) Я не вижу ни одного configDeferred.reslove в вашем коде (3) При использовании ng-href используйте inspect element, чтобы увидеть, действительно ли angular вставил интерполированный {{baseUrl}}
 atjoshi31 дек. 2017 г., 15:53
base href = "/" нг-HREF =»{{BaseUrl}}» > это сработало для меня и в блоке выполнения $ rootScope.baseUrl = BASE_URL; // BASE_URL восстанавливается из конфигурации, которая вводится через gulp во время процесса сборки

Ответы на вопрос(4)

Решение Вопроса

grunt

Когда я запускаю свое приложение angular, у меня есть несколько задач:

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

Затем хрюкать сделать замену строк с помощьюgrunt-preprocess модуль:

мойconstants.tpl.js файл анализируется:

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

и 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

создаст новый файл с URL

 Daan12 мар. 2014 г., 14:07
Кажется, нет ответа, интегрированного с AngularJS, которыйпочему это самое чистое решение
 Daan10 мар. 2014 г., 16:49
Очень интересно, можете ли вы дать мне небольшой пример того, какой дополнительный код мне понадобится, чтобы эта работа? Я предпочитаю не работать с базовым тегом, как объяснил @Rishul Matta
 Cétia10 мар. 2014 г., 17:07
Ты знаешь ворчание? Если нет, то область действия этого ответа будет слишком большой, и я предлагаю вам прочитать grunt docs;) Я обновил свой ответ, чтобы дать вам лучший пример (не проверено, очень упрощенный код)
как бы вы создали сервис, который получает объект конфигурации с сервера
app.run(function($rootScope, yourService){   
    yourService.fetchConfig(function(config){
        $rootScope.baseUrl = config.baseUrl;
   })
});
наценка


   
   ......
нотаЕсли ваш сервис использует $ http или $ resource, у вас все будет хорошоЕсли вместо этого вы используете jQuery ajax-вызовы, вы должны запустить $ rootScope. $ Apply () после установки переменных в область видимости.
 Ilan Frumer07 янв. 2014 г., 23:00
Покажите мне переменные окружения, которые вы пытаетесь получить в базе href.
 Daan07 янв. 2014 г., 22:02
Похоже, это не работает: когда я изменяю атрибут href для <база> тег к ng-href, он корректно загружает контент, но меняет мой URL наdev.environment/page вместо .dev.environment/project/page
 Daan07 янв. 2014 г., 22:04
Я также пытался изменить <база> тег к, но это дает мне следующую ошибку:Error: A history state object with URL 'http://0.0.1.148/' cannot be created in a document with origin 'http://dev.environment'., Может быть, приятно сказать, что я также использую angular-ui-router
 Daan12 мар. 2014 г., 14:09
Этот ответ не будет работать + с помощью <base href = "" /> может использоваться для угловой структуры, но не будет соблюдаться обычными тегами привязки
 Daan07 янв. 2014 г., 23:17
Я обновил свой вопрос

и я действительно неЯ не хочу указывать мой базовый путь в каком-либо конфигурационном файле. Мы работаем со многими разработчиками над нашим приложением, и у каждого из них разная рабочая среда. Наконец я нашел решение, которым я не очень горжусь, но оно работает как шарм. Требуется только одно: PHP.

Поэтому вместо написания base href с вашим JS попробуйте следующее:

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

Если у вас уже есть PHP на вашем сервере, то это только вопрос переименования вашегоindex.html вindex.php (также не забывайте о.htaccess если у тебя есть).

Я знаю, что это решение неэто хорошо для всех, это не должно, этоЭто просто мое решение проблемы для тех, у кого PHP уже есть на сервере. Я надеюсь, что это поможет, по крайней мере, некоторым из вас :)

поскольку оно также может испортить функционирование якорных тегов и может привести к нежелательной навигации. Подход, который вы должны прочитать конфигурацию из файла 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. Теперь ввести константу в вашем приложении для этого я руководствовалсяEddiec а такжеCD

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);

надеюсь, это помогает ура!

 Rishul Matta10 мар. 2014 г., 18:05
хм, что бы вы ни делали ... чтобы прочитать конфигурацию, вам нужно будет запустить файл перед запуском приложения, и более того, json - это улучшение по сравнению с xml, которое я написал для xml, вы также можете получить код для json :)
 Daan10 мар. 2014 г., 16:47
Я согласен, использование базового тега плохо и портит мои якоря. Но я предпочитаю (потому что я работаю в среде JS) файл JSON в вашем примере, и я неМне нравится тот факт, что мне нужно запустить файл перед инициализацией моего приложения Angular (но, возможно, это единственный способ).

Ваш ответ на вопрос