Efim Rozovsky
Efim Rozovsky

Reputation: 383

Angular, how to switch between production and development environments?

I have a big Angular application which is still needed in development, but already ready for use in production, I want to be switch between the states with simple change of

isProduction: boolean = false

to true, I did it by making apiHelperService which is just usual service, it works fine for most application:

import {Injectable} from "@angular/core";
import {Response, Http, Headers, RequestOptions} from "@angular/http";
import {Observable} from "rxjs/Observable";

@Injectable()
export class ApiHelperService {
  productionURL: string = 'http://35.203.121.40';
  developmentURL: string = 'http://10.25.37.523';
  serverUrl: string;
  apiPort: string = ':3000/';
  socketPort: string = ':2000/';
  isProductionMode: boolean = false;


  constructor() {
    this.serverUrl = this.isProductionMode ? this.productionURL : this.developmentURL;
  }

  getApiURL(): string {
    return this.serverUrl + this.apiPort;
  }

  getSocketUrl(): string {
    return this.serverUrl + this.socketPort;
  }
  getApiIp(): string {
    const serverIp = this.isProductionMode ? this.productionURL.split(':')[0] : this.developmentURL.split(':')[0];
    console.log('string url is:', serverIp);
    return serverIp;

  }
  serialize(obj) {
    var str = [];
    for (var p in obj) {
      if (obj.hasOwnProperty(p) && ((obj[p] != null && obj[p] != '') || (typeof obj[p] == "boolean"))) {
        if (obj[p].length == 0) {
          continue;
        }
        else if (obj[p].length > 1 && typeof obj[p] == 'object') { // reformats arrays
          for (let i = 0; i < obj[p].length; i++) {
            str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p][i]));
          }
        }
        else {
          str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
        }
      }
    }

    return '?' + str.join("&");
  }

  extractData(res: Response) {
    let body = res.json();
    // console.log("body", body)
    return body || {};
  }

  handleError(error: Response | any) {
    let errMsg: string;
    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
    } else {
      errMsg = error.message ? error.message : error.toString();
    }
    console.error(errMsg);
    return Observable.throw(errMsg);
  }

}

BUT i have socket library that configures the socket URL in the

app.module.ts

so when I try to use dynamic URL(in the app.module.ts) like this:

const apiHelper = new ApiHelperService(); //fails here
const url: string = apiHelper.getSocketUrl();
const config: SocketIoConfig = { url: url, options: {
  "force new connection" : true,
  "reconnectionAttempts": "Infinity",
  "timeout" : 10000,
  "transports" : ["websocket"]} };

it fails with this error:

ERROR in Error: Error encountered resolving symbol values statically. Calling 
function 'ApiHelperService', function calls are not supported. Consider replacing the function or lambda with a
reference to an exported function, resolving symbol AppModule

so my question is, is my approach wrong? what is the right approach to handle this problem?

Upvotes: 4

Views: 8899

Answers (1)

Pasha K
Pasha K

Reputation: 407

it works in different way: alligator.io/angular/environment-variables

you must specify variables in environment.ts and environment.prod.ts

then import {environment} from '../../environments/environment'; environment object will contain proper variables

Upvotes: 6

Related Questions