How to config different development environment in Angular 2 app
Asked Answered
J

6

48

I have a constant file

export class constants {
    public static get API_ENDPOINT(): string { return 'https://dvelopment-server/'; }
}

And I imported it to my service

private _registrationUrl = constants.API_ENDPOINT+'api/v1/register';

How can I change the endpont with server change . I have development server staging server and local server. I want app to detect the environment change.

In my angular 1 app I used envserviceprovider for this. Can I use the same in angular 2 app ?

Jotunheim answered 15/3, 2016 at 7:18 Comment(6)
I think you can do this in angular2 also. Not sure there is an equivalent for this library in angular2, but you can easily replicate it by yourself I believe. You have to check your domain your app is running (localhost, devserver.com, etc) and based on that you can set the set variables from the service's config object.Remonstrance
How can I check the domain in which angular 2 app is runningJotunheim
you can use location, it is even working in webworker if self is prefixed https://developer.mozilla.org/en-US/docs/Web/API/Location, https://developer.mozilla.org/en-US/docs/Web/API/WorkerLocationRemonstrance
If you want to build once and deploy the same build artifact multiple times, see https://mcmap.net/q/357270/-most-modern-way-to-externalize-angular-2-environment-configurationRoach
I recommend having a look at https://mcmap.net/q/357271/-configure-angular-2-webpack-app-in-docker-container-environment-specific. The basic idea is to use a script (e.g. in a docker container) that modifies the created minified js based on your environment.Vevay
As the last 2 comments state, I would recommend looking at options that don't involve config at build. you ideally want to build once, and THEN use that build on different environments. Otherwise the QA/test stage is semi invalidated as builds can introduce problems.Chetnik
J
0

I have solved the issue by adding a class method

export class config {

    public static getEnvironmentVariable(value) {
        var environment:string;
        var data = {};
        environment = window.location.hostname;
        switch (environment) {
            case'localhost':
                data = {
                    endPoint: 'https://dev.xxxxx.com/'
                };
                break;
             case 'uat.server.com':
                data = {
                    endPoint: 'https://uat.xxxxx.com/'
                };
                break;

            default:
                data = {
                    endPoint: 'https://dev.xxxx.com/'
                };
        }
        return data[value];
    }
}

In my service

private _loginUrl = config.getEnvironmentVariable('endPoint')+'api/v1/login;
Jotunheim answered 15/3, 2016 at 11:28 Comment(5)
What I don't like about this solution is that it exposes the internals of your development environment publicly. I'm considering using Grunt to copy a target-dependent file into place before concatenation, defining the config class. But, I feel like there has to be a better way.Sandhog
that's just a poor solution. this should not be the accepted answer.Variation
why use another class when you have environments? @zavié gave a good solutionSandhog
if you are doing a build once and deploy everywhere approach, you dont have any other solution besides one that is similar to this.Neediness
adding +1 as its a choosen solutions. Please requesting all to go answering according to the question asked.Russ
A
71

Short answer: use Angular CLI. It is in beta stage but works really well and it's recommended by the Angular Team for starting new projects. With this tool you can configure different environments. At build time, the src/client/app/environment.ts will be replaced by either config/environment.dev.ts or config/environment.prod.ts, depending on the current CLI environment.

Environment defaults to dev, but you can generate a production build via the -prod flag in either ng build -prod or ng serve -prod. Given that this is a new feature, it can be a bit confuse, so look at this great guide for additional info about how to set up Angular Environments using CLI.

Hope this helps.

Andreaandreana answered 29/5, 2016 at 18:44 Comment(8)
Note that the import command from the guide seems no longer working (possibly the path changed). This worked for me: import { environment } from '../../environments/environment';Uganda
This is the approach I used and it's great. We've also got a test environment that uses a different configurations than dev and prod so I added a third environment "test" and mapped it via "environments" in angular-cli.json. So depending on the environment it pulls in the appropriate configurations.Wideman
@zavié Maybe import { environment } from "app/../environments/environment;" is better given that works for every file location.Andreaandreana
Curious...what if you have inherited an Angular 2 app which was built manually and not through Angular CLI? What's the "long answer"?Spirelet
@Spirelet I guess in that case you have at least 2 options. Option one: Create a CLI project from scratch and migrate you app. Option two: Add the functionality for handling environments in your inherited app infrastructure, building tool, npm project, or whatever you have. For the "long answer", take a look at other responses for ideas, or create a new CLI project and take look at the code (that's the magic of Open Source projects btw).Andreaandreana
Having just migrated a SystemJS app to AngularCLI I can tell you it isn't that bad. I had the CLI version running in under an hour, with everything working in less than a day, and that was just to test everything and to fix a few issues(RecordRTC and CKEditor gave me some minor problems, as well as my styles had to be slightly reworked).Borries
Good answer, but my VS Code intellisense was complaining because I replaced the environment.ts file with environment.dev.ts - if you want to keep Intellisense happy, keep an environment.ts file in your environments/ directory, and ensure it has all the same variables as your other environments.Toscano
If you want to do a better organization of you environments, you can se this post: medium.com/@madridserginho/…Eyrie
E
32

I would just like to add put some more light into the answer provided by @Cartucho. He is right about the steps required to setup a personalized environment for your angular 2 apps. I would also like to second the opinion that the article at Guide to Build the app in different environments

But the given article misses out on an important step. Steps to set up a personalized environment are as follows: 1) Create a new file called environment.YourEnvName.ts in the environments folder in the project. 2) Add the Environment description in the "environments" object in the angular-cli.json file.

"environments": {
    "source": "environments/environment.ts",
    "prod": "environments/environment.prod.ts",
    "dev": "environments/environment.dev.ts", 
    "qa": "environments/environment.qa.ts",
    "YourEnvName": "environments/environment.YourEnvName.ts"
  }

3) Once you have made these changes you can build the app for your new environment using the following command.

ng build --environment=YourEnvName or 

ng serve --environment=YourEnvName 

Hope this post is helpful to any new Angular 2 developer.

Earthen answered 31/1, 2017 at 16:49 Comment(0)
J
0

I have solved the issue by adding a class method

export class config {

    public static getEnvironmentVariable(value) {
        var environment:string;
        var data = {};
        environment = window.location.hostname;
        switch (environment) {
            case'localhost':
                data = {
                    endPoint: 'https://dev.xxxxx.com/'
                };
                break;
             case 'uat.server.com':
                data = {
                    endPoint: 'https://uat.xxxxx.com/'
                };
                break;

            default:
                data = {
                    endPoint: 'https://dev.xxxx.com/'
                };
        }
        return data[value];
    }
}

In my service

private _loginUrl = config.getEnvironmentVariable('endPoint')+'api/v1/login;
Jotunheim answered 15/3, 2016 at 11:28 Comment(5)
What I don't like about this solution is that it exposes the internals of your development environment publicly. I'm considering using Grunt to copy a target-dependent file into place before concatenation, defining the config class. But, I feel like there has to be a better way.Sandhog
that's just a poor solution. this should not be the accepted answer.Variation
why use another class when you have environments? @zavié gave a good solutionSandhog
if you are doing a build once and deploy everywhere approach, you dont have any other solution besides one that is similar to this.Neediness
adding +1 as its a choosen solutions. Please requesting all to go answering according to the question asked.Russ
W
0
export class endPointconfig {

    public static getEnvironmentVariable() {
        let origin = location.origin;
        let path = location.href.split('/')[3];
        let value = origin +'/'+ path + '/api/';`enter code here`       
        return value;
    }
}
Wahoo answered 23/2, 2017 at 3:51 Comment(1)
on your service just call the endPointConfig class to return the urlWahoo
I
0

I hope it helps.

First, create development.ts, staging.ts, production.ts configuration files. Second, in your index.pug, import the environment file in the following way:

   SystemJS.import("#{settings.env}").then(function(env) {
       System.import("app").catch(console.error.bind(console));
   } // Promise.all also works!

Remember that in nodeJS/Pug/Jade settings.env contains the NODE_ENV value.

And finally, your system.config.ts map should have the following lines:

    "development": "myUrl/configs/development.js",
    "staging": "myUrl/configs/staging.js",
    "production": "myUrl/configs/production.js",
Ics answered 22/3, 2017 at 3:38 Comment(0)
O
0

@cartucho's answer works great until you try to deploy to multiple environments with services like Heroku or Github actions. These services make it easy to use node environment variables, but do not have a way configure environment specific build commands.

One way to solve this is to set your Angular environment variables up like @cartucho suggested, then set your build script to call a small node application. The node application reads a node environment variable and then decides which build command to run.

In package.json: "build": "node build-app.js",

build-app.js:

const { exec } = require('child_process');

let buildScript = 'ng build --configuration=staging';
if (process.env.ANGULAR_ENVIRONMENT_CONFIGURATION === 'production') {
    buildScript = 'ng build --configuration=production';
}
const child = exec(buildScript, function (err, stdout, stderr) {
    if (err) throw err;
    else console.info(stdout);
});

child.stdout.on('data', function (data) {
    process.stdout.write(data);
});

child.stderr.on('data', function (data) {
    process.stdout.write(data);
});

child.on('exit', function (data) {
    process.stdout.write("I'm done!");
});

I go into more detail and talk about additional steps required for Angular Universal in my blog post: https://dev.to/jfbloom22/a-better-way-to-deploy-angular-universal-to-multiple-environments-206j

Ozzie answered 30/7, 2021 at 17:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.