Configure base URL depending on environment

19,991

Solution 1

If you are using the Angular CLI you can do:

ng build --prod --base-href /myUrl/

OR

ng build --prod --bh /myUrl/

Solution 2

UPDATED:
Carefully follow these steps and you are good to go :)
----------------------------------------------------------
1. Create 4 files in environment folder: (2 might there by default)
example: 
environment.ts, environment.prod.ts,environment.test1.ts,environment.test2.ts

2. Use this common code for every file with slight change:

    export const environment = {
      production: true, //production is true for environment.prod.ts file
                        //for other test production is false
      apiUrl: ''        //base_url of each environment
    };

3. Maintain a constant file where you will write all base urls.
code sample of constant.ts:

    import { environment } from '../environments/environment';
    let url = environment.apiUrl;
    export const AppConstant = Object.freeze({
        BASE_API_URL: url,
    }

4. import this constant in your service or component class wherever your calling back-end. 

5. In angular-cli.json: 


    "environmentSource": "environments/environment.ts",
          "environments": {
            "dev": "environments/environment.ts",
            "prod": "environments/environment.prod.ts",
            "test1": "environments/environment.test1.ts",
            "test2": "environments/environment.test2.ts"
          }

6.

    ng build --env=prod
    ng build --env=dev / ng build
     ng build --env=test1
     ng build --env=test2

7. if aot is creating problem. you can use :  ng build --env=prod --no-aot

8. TO make things simple: 

you can additonally add new build commands: 
 "scripts": {
    "ng": "ng",
    "start": "ng serve --env=local --no-aot",
    "start:qa": "ng serve --env=dev --no-aot",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "build:prod": "ng build --prod --env=prod --no-aot --output-hashing=all",
    "build:dev": "ng build --prod --env=dev --no-aot --output-hashing=all",
    "build:local": "ng build --env=local"
  }
When you run,command is  ==> npm run start OR npm run start:qa 
OR==> npm run build:local or npm run build:dev, etc.

9. Hashing will solve caching isuue.

Hope it solves your problem. It works for me.

Solution 3

An alternative to the option described in @DeborahK answer could be to add build configurations to package.json and setup your IDE to specify the desired build configuration depending on environment it's building for.

Here is a snippet from package.json:

{
  ...
  "scripts": {
    ...
    "build": "ng build",
    "build:Debug": "ng build --dev --base-href /",
    "build:Release": "ng build --prod --base-href /angular-app/",
    ...
  },
  ...
}

And here is a snippet of .csproj file to give you an idea of how it could be integrated with Visual Studio (credits to @Andrey_Fomin in this discussion):

  <Target Name="NgBuildAndAddToPublishOutput" AfterTargets="ComputeFilesToPublish">
    <Exec Command="npm run | findstr &quot;build:$(Configuration)&quot;" ConsoleToMSBuild="true" IgnoreExitCode="true" EchoOff="true" WorkingDirectory="$(MSBuildProjectDirectory)">
      <Output TaskParameter="ConsoleOutput" PropertyName="NpmScriptName" />
    </Exec>
    <Exec Condition=" '$(NpmScriptName)'=='build:$(Configuration)' " Command="npm run $(NpmScriptName)" />
    <Exec Condition=" '$(NpmScriptName)'!='build:$(Configuration)' " Command="npm run build" />
  </Target>

Solution 4

In angular 6 we can do it in better way, by using environment.x.ts (x means it might be production/development/configuration etc files).

suppose if its dev mode file name(environment.dev.ts)

export const environment = {
    production: false,
    appRoot: "/" or appRoot: "http://somerestapi"
};

suppose if its in production mode file name(environment.prod.ts)

   export const environment = {
        production: true,
        appRoot: "/" or appRoot: "http://somerestapi"
    };

and same appRoot can be used in all services as in below service.ts file.

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

 appRoot = environment.appRoot;

    emplLoginCheckUrl = this.appRoot + "/checkValidUser";

      validateUserDetails(employeeDetails): Observable<any> {
            console.log(this.appRoot );
            return this._httpClinet.post(this.emplLoginCheckUrl, employeeDetails);
        }

after this we have one more job to do, its open your angular.json file

apply below changes to "dev": mode

"dev": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.dev.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": true,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true
            }

and apply below changes to "production": mode

 "production": {
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ]
            },

but you have to choose which one is needed to run the application, like if you want to run in dev mode use below command it will automatically apply appRoot(URL) for all aservices where you called.

ng build --configuration=dev (for development mode). ng build --configuration=production (for production mode).

Share:
19,991
Alexander Abakumov
Author by

Alexander Abakumov

Hello, My name is Alex Abakumov and I've been a professional Software Engineer since 2005. At the beginning of my career, I used primarily C\C++, and a little bit of PHP and Java. In 2008 I started using .NET and since then it became my passion :) In 2010 - 2015 I've been working with a German company doing projects for US and German clients and since 2015 I work exclusively with US companies onsite. I have extended experience in developing software solutions in Transportation, Insurance, Finance fields. I'm experienced with full .NET Web and Windows desktop stacks, WCF, SQL Server, HTML5 web apps based on JavaScript\TypeScript and Angular, KnockoutJS, jQuery frameworks, as well as developing mobile apps for iOS and Android (both Java and NDK) available on AppStore\Google Play. I'm proficient with C#, Java, C\C++, JavaScript, TypeScript, SQL, Objective-C languages. Except coding, I like science, reading, psychology, jogging and swimming. Thanks for your time and hope you have a great day! :)

Updated on June 13, 2022

Comments

  • Alexander Abakumov
    Alexander Abakumov almost 2 years

    Suppose we have Angular 4+ app that needs to be located in different relative root URLs on different environments, i.e.:

    • http://localhost:4200/index.html for development
    • http://prod.server.com/angular-app/index.html for production

    Most likely, we'd want to have that option in our environment.x.ts files:

    export const environment = {
        production: false,
        appRoot: "/"
    };
    
    export const environment = {
        production: true,
        appRoot: "/angular-app/"
    };
    

    How can we configure Angular build/runtime infrastructure to automatically adjust the app depending on this option in environment.x.ts files?

    UPDATE: Since I'm using the Angular CLI toolchain indirectly via Visual Studio build/publish system (template), it'd be nice to have a solution based completely on Angular CLI + *.json/*.ts/*.js files. This way it would be suitable for any build system where Angular CLI could be used.