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

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

продукция:

www.exmaple.com/page

развитие:

dev.environment/project/page

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

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

Есть ли способ динамически установить базовый 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; // '/project/'
  configDeferred.resolve();
});

и в моем index.html:

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

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

UPDATE: Файл конфигурации:

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

Ответ 1

Я лично делаю такие вещи с помощью grunt.

Когда я запускаю свой angular -app, у меня есть несколько задач:

> 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-адресом

Ответ 2

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() после установки переменных в область.

Ответ 3

Использование базовых URL-адресов может быть не лучшим, потому что это может также испортить работу якорных тегов и может привести к нежелательной навигации. Подход, который вы должны прочитать конфигурацию из XML файла, идеален, и это то, что я сделал:

1. Прежде чем инициализировать приложение angular, прочитайте переменную из вашего файла конфигурации:

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>

Теперь вы вводите константу в свое приложение для этого, я руководствовался 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);

надеюсь, что это поможет приветствовать!

Ответ 4

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

Итак, вместо того, чтобы писать базовый 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 уже есть на сервере. Надеюсь, это поможет хотя бы некоторым из вас:)