73

I am using angular6, in my project I am using Facebook Account Toolkit for mobile verification purpose.

I need to initialise Account toolkit in index.html file using following code.

  AccountKit.init({
   appId:"XX",
   state:"xx",
   version:"v1.2",
   fbAppEventsEnabled:true,
   debug:true
 });

The problem is, values for appId and state change depending on environment (development/test/production).

How can I use environment variables in index.html file.

Please let me know if anyone has a solution for angular 6.

10 Answers 10

94

You should create copy of index.html and name it index.someenv.html. Then in your angular.json in environment configuration setup file replacement:

"fileReplacements": [
    {
        "replace": "src/index.html",
        "with": "src/index.someenv.html"
    }
]

The angular cli will replace these files when you run your build

UPD: For Angular 8+ use this:

Add the following to your angular.json:

"production": {
  "index": {
    "input": "src/index.someenv.html",
    "output": "index.html"
  },
},
Sign up to request clarification or add additional context in comments.

7 Comments

I am doing this but for some reason it still copies over the original index.html file. I am using the following command to build the angular app: ng build --prod -c production --output-path dist. Do you have any idea why it wouldn't replace the index.html file with index.prod.html ?
@DejanBogatinovski can you show your configuration for production? (in angular.json)
@JosephHorsch only the content of index.html will be replaced, not the filename.
@DejanBogatinovski As of angular 8, you can't replace index files via "fileReplacements". You have to specify your own index file via "index" property. Eg.: "index":"src/index.someenv.html".
See my answer for Angular 8 and above
|
50

This answer supersedes Artyom's answer for Angular 8 and above. Add the following to your angular.json:

"production": {
  "index": {
    "input": "src/index.someenv.html",
    "output": "index.html"
  },
},

1 Comment

This would also be great to do in a CI build. have index.tokens.html contain MY_PLACEHOLDER. index.html contains the default for local development, and in your pipeline just before your prod build do a replacement of MY_PLACEHOLDER with a pipeline variable. This allows values like environment URLs to be stored in the pipeline and a change to them would be to simply re-run the pipeline for a given commit to generate the file with the new URL instead of needing a code change to have to be promoted through various environments.
7

In main.ts file you can use document.write(environment.variable) and it will write what you want in index.html

(I use it to make the Google Analytics script take a dynamic Tracking ID wether it's in development or production mode, and it works well in Angular6)

1 Comment

Hi, would you have a small example to show how you managed to update your Analytics script Tracking ID in your index.html file? Much appreciated
6

An example here for document.write(environment.variable) : https://github.com/angular/angular-cli/issues/4451#issuecomment-285026543

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

if (environment.production) {
  document.write('<script type="text/javascript">// ProductionAnalyticsCodeHere</script>');
} else if (environment.staging) {
  document.write('<script type="text/javascript">// StagingAnalyticsCodeHere</script>');
}

1 Comment

This one is kinda dangerous, because document.write will replace whole HTML document if invoked after page is being loaded.
6

for me above answers did not work on Angular 10, so I created different folder for staging, production etc and placed the index.html which was used by CLI as per the build environment

{
  "projects": {
    "yourApp": {
      "projectType": "application",
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "index": "src/index.html",
          },
          "configurations": {
            "production": {
              "index": "src/production/index.html",
            }
          }
        }
      }
    }
  }
}     

3 Comments

I confirm, This solution worked for me, on angular 13
OK, that's weird. I was set to also confirm that jscroll's solution didn't work in Ang 13/14: (Index html generation failed \r\n ENDENT: no such file or directory, open C:\blah\blah\ClientApp\src\index.test.html), but after I successfully followed this solution and then tried it again (just to test/report whether it was the name of the index file or whether it needed to be in its own folder), jscroll's solution started working. Go figure.
This worked for the default(index.html), but for the dev(index.dev.html), I also had to do mv dist/index.dev.html dist/index.html
2

Avoid direct access to the document object by injecting DOCUMENT to your AppComponent.

import { DOCUMENT } from '@angular/common';
...
  public constructor(
    @Inject(DOCUMENT) private doc: any
  ) {

Add the tag in ngOnInit()

ngOnInit() {
    this.setYourScriptTag();
}

private function to set it

  private setYourScriptTag() {
    const s = this.doc.createElement('script');
    s.type = 'text/javascript';
    s.innerHTML = `AccountKit.init({
   appId: "${environment.appId}",
   state: "${environment.state}",
   version:"v1.2",
   fbAppEventsEnabled:true,
   debug:true
 });`;
    const head = this.doc.getElementsByTagName('head')[0];
    head.appendChild(s);
  }

This answer is from edodusi

https://github.com/angular/angular-cli/issues/4451#issuecomment-384992203

Comments

2

Angular 16: File replacement approach

"production": {
       "index": "src/index.html",
},
"development": {
       "index": "src/index.development.html",
}

Using two different HTML file

Comments

1

I think you can do it all in main.ts

const env = environment;

 AccountKit.init({
   appId:env.appId,  // this lane
   state:env.state,  // this lane
   version:"v1.2",
   fbAppEventsEnabled:true,
   debug:true
});

Thanks.

1 Comment

I had a similar issue with loading google charts js and needing to pass the correct api from the environment variables. Moving the initialize call to main.ts worked for me. Of course timing issues are always a concern when loading/initializing scripts so let us know if it works in your scenario.
0

I added this in main.ts:

var html = document.documentElement.innerHTML
document.documentElement.innerHTML = html.replace("Replace me!", environment.variable)

Note that the old value will still exist in index.html for some time while the page is initially loading. (For example, use this to replace the page title and you'll see the old value displayed before the replace happens.)

1 Comment

FWIW: There is an alternate for setting the title that does not suffer from above @ZX9 mentioned latency, per the Angular docs - angular.io/guide/set-document-title.
-5

import your environment file into .ts file.

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

Create required fields in your class, assign values from environment to these variables in the constructor, use usual binding in the .html file.

.ts

import { Component } from '@angular/core';
import { environment } from '../environments/environment';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  public production = true;
  constructor() {
    this.production = environment.production;
  }
}

.html

<span>{{production}}</span>

1 Comment

thanks, Igor Litvinovich, but I want to use that env variable in index.html , not in .ts file to that particular html file, i am using angular6. and import not working in index.html file.

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.