How to set AngularjJS base URL dynamically based on fetched environment variable?

.htaccess, angularjs, base-url, config, environment

Solution

I personnaly do this kind of stuff with `grunt`.

When I run my angular-app I have multiple tasks :

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

Then grunt do strings replacement with the help of the `grunt-preprocess` module :

my `constants.tpl.js` file gets parsed :

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

and the url is populated.

There are endless possibilities (string replacements, file copy, etc).

Doing it with grunt ensure that dev config files do not go in production for example..

I can put more details if you're interested but I only wanted to show you a different approach.

edit gruntFile example :

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

};

Now, the command :

> grunt run --target=dev

will create a new file with an url

Problem

I have a development and production environment in which my URL's differ: production: `www.exmaple.com/page` development: `dev.environment/project/page` I know that I can set the base URL in AngularJS with the `<base href='/project/' />` but that doesn't help me out here. Before I load my AngularJS application I fetch a config file (in app.js, with the `.run` statement, which reads a variable that has the environment: ``` ]).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; }); }); ``` Is there a way to dynamically set the base URL, based on a fetched config file in AngularJS (maybe with a .htaccess)? Attempt 1: Try to get the config via `.run` and set the base url via ng-href: Edit the following line of code in my 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(); }); ``` and in my index.html: ``` <base ng-href="{{baseUrl}}" /> ``` It looks like this is not working: when I change the href attribute of tag to ng-href, it loads the content correctly, but changes my URL to `dev.environment/page` instead of `dev.environment/project/page` UPDATE: The config file: ``` { "mode": "development", "baseUrl": "/project/" } ```

Original source