42

I want to remove my local server prefix from my REST API URLs (example, http://localhost:8080) when building for production (ng build --prod).

I get that it's something to do with the environment file environment.prod.ts, but can't find any examples of making use of them to achieve the aforementioned.

Would be great if someone helps me get started!

1

7 Answers 7

76

Dont hard code the URL. Use environment.prod.ts and environment.ts files which are inside src/environments. for localhost, in environment.ts file use some variable to save your url.

export const environment = 
{
    production: false,
    API_URL: 'http://localhost:8080',
};

for production, in environment.prod.ts

export const environment = 
{
    production: true,
    API_URL: 'http://api.productionurl.com',
};

When using in your code import the variable,

import { environment } from '../../environments/environment';
....
....

private API_URL= environment.API_URL;

whenever your are using for production use angular cli command option

ng build --env=prod

The file contents for the current environment will overwrite these during build. The build system defaults to the dev environment which uses environment.ts, but if you do ng build --env=prod then environment.prod.ts will be used instead. The list of which env maps to which file can be found in .angular-cli.json.

For more queries refer, https://angular.io/guide/deployment

Sign up to request clarification or add additional context in comments.

4 Comments

you are hardcoding the URL too. Putting it in another file with a special name like environment is not making you avoid hardcoding :shrug:. API URLs should be set via environment variables. A variable inside a file called environment it's not an environment variable.
@Sebastian interesting, could you suggest how best to set environment variables for API URLS?
@NarayanDheerajKumar the approach I used with docker containers goes like this: before you start your webserver to load your static html and js files, you parse your environment variables and inject them into your index.html file. For this to work seamlessly, you must craft your index.html with, for example, variable placeholders.
@NarayanDheerajKumar I explained in big detail in the answer I just posted: stackoverflow.com/questions/47426721/…
6

DEV/PROD parity approach

One way to this approach using containers is by parsing your environment files before you launch your webserver. This assumes that your are following a good practice, that is, you aren't serving your angular application via ng.

For example, a rudimentary approach would be to craft your index.html with your desired configuration, this is just an example, do it how you see best:

<script>
  window.config = {
     ENV_VAR1: 'ENV_VAR1_PLACEHOLDER',
     ENV_VAR2: 'ENV_VAR2_PLACEHOLDER',
     ....
  }
</script>

Before launching your webserver with your static content, use a script that verifies and matches valid environment variables from your configuration window.config with your actual environment variables.

This is doable with sed for instance, or if you want to go pro, you may also use [jq][1].

After your validation is done, your index.html has the window.config object configured following the dev-prod parity approach from 12factors.

Running your docker container would be just,

docker run -it -e ENV_VAR1="my development value" ...

and for production,

docker run -it -e ENV_VAR1="my production value" ...

2 Comments

This seems like a good answer @Sebastian but it needs a bit about how to make Angular compile when the window.config variable is not in it's rendering scope, causing build failures.
@Routhinator window may be used in the environment.ts file and you export values from there. As javascript is runtime, it won't matter at build time if that object is undefined.
4

Relative URLs

Putting an API_URL in your environment config is a good idea, but if your API and client app is being served from the same server or domain, you can use relative URLs instead. It is much easier to set up and simplifies your build process.

Here is some code that would live in an API service.

  get(path: string, params: HttpParams = new HttpParams()): Observable<any> {
    return this.http.get(`/api${path}`, { params })
      .pipe(catchError(this.formatErrors));
  }

If you are using the environment.API_URL, you can still configure that value to be blank.

This can be helpful if you are serving your app and API from separate localhost servers in a development environment. For example, you might ng serve from localhost:4200 and run your API from a PHP, C#, Java, etc. backend on localhost:43210. You will need the API_URL config for development.

  get(path: string, params: HttpParams = new HttpParams()): Observable<any> {
    return this.http.get(`${environment.api_url}/api${path}`, { params })
      .pipe(catchError(this.formatErrors));
  }

As a bonus, here is an example of ApiService that is an injectable object you can use in your app!

https://github.com/gothinkster/angular-realworld-example-app/blob/63f5cd879b5e1519abfb8307727c37ff7b890d92/src/app/core/services/api.service.ts

Pay attention to the base ref in your main HTML page as well.

Comments

2

You will find the URL configuration in environment.ts and environment.prod.ts file. Don't put hardcoded URL while calling the API. A good practice is to read the API URLs from environment.ts and environment.prod.ts file

For the local environment use environment.ts

export const environment = 
{
    production: false,
    API_URL: 'http://localhost:8080',
};

For the production environment use environment.prod.ts

export const environment = 
{
    production: true,
    API_URL: 'http://api.productionurl.com',
};

2 Comments

Why Prod url has api before produtuonurl.com?
@NithinPaul it might be just an example. Another would be valid as well like http://my.custom.domain.api.prod.com or whatever you want.
1

One possible way to achieve that is, to define different base URLs based on isDevMode() in your code. For example,

import { isDevMode } from '@angular/core';

// ...
let baseUrl: string;
if (isDevMode()) {
    baseUrl = "http://localhost:8080/";
} else {
    baseUrl = "http://api.myprodserver.com/";
}
// ...

Edit: This is meant to be for illustration. You'll likely want to use some type of (env-dependent) "config" in real code.

Comments

1

You don't need to hard code the API_URL as mentioned above just use your environment.prod.ts file. Set-:

  1. production = true.
  2. Change the API_URL to your desired url.
  3. Now run the command ng build --prod=true

It worked for me I guess, will work for you too.

Comments

1

Hardcoding in this or another way an address to the API server is not a good way. The API URL should be stored in a configuration file possible to change without recompiling whole application. I think this is a way you should do it: Editable config file

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.