How to Read External Data Files in Angular Production Builds

A quick solution to read data from config files dynamically.3 min


read-data-from-external-file-before-angular-application-starts

TL;DR – Learn how to read data from external files in Angular production builds. A step-by-step guide for developers.

This article will show you how you can read data from your external files from the production build.

Cover Image credits: Image by Author prepared with PowerPoint

Issue 1: Update multiple client projects by replacing variables in the main.**.js file

On your production build of Angular project, If You want to read data from the external configuration file (let’s say JSON format), to avoid the building process for all the time while upgrading the same code everywhere, on each server. You can easily create the JSON file and update the values only when needed, it will dynamically read your latest changes. Isn’t cool?

Issue 2: If You have to update labels everywhere in your entire application, but you hardcoded it and so making multiple changes everywhere, is much time-consuming.

What if you put everything in your JSON file or constant file? If you want to update those labels to English, Spanish, German, French, or any language, you need to update everything in your entire application.

Issue 3: Managing Local, Dev, Test, Beta, and Prod environments

In your large-scale applications, it might be hard to manage all the environments you can use, Angular + java, Angular+ node, Angular + PHP, Angular + Ruby, etc combinations for frontend backend.

Maintaining IP addresses is sometimes a headache if you have several projects and deployments!

Don't Miss: Clear Cache Programmatically in Angular Index.html: A Programmatically Simple Solution

All in One Solution

Keep a configuration file in your assets dir of your Angular project and read that configuration file before the application starts up. This solution will work for all the angular 2+ versions, it will work like a charm.

You can use it to read configuration files as you do in other languages like Java, Php, Ruby, Python, etc.

How it will load the data? — Check the procedure

a) It will read an environment file named ‘environment.json’. This file indicates what is the current working environment. Options are: ‘development’ and ‘production’;

b) It will read a config JSON file based on what is found in the environment file. If the environment is “production”, the file is ‘config.production.json’. If the environment is “development”, the file is ‘config.development.json’.

All these read things will be done before Angular starts up the application.

It assumes you already have a working application, with a module and everything set up. Follow the below steps: —

Update your Existing Module

Open your existing module (let’s say app.module.ts) and add the following couple of lines to your list of providers.

import { APP_INITIALIZER } from '@angular/core';
import { AppConfig }       from './app.config';
import { HttpModule }      from '@angular/http';

...
//Add this function as initiating load method first
function initConfig(config: AppConfig){
    return () => config.load()
}
@NgModule({
    imports: [
        ...
        HttpModule
    ],
    ...
    providers: [
        ...
        AppConfig,
        { provide: APP_INITIALIZER, useFactory: initConfig, deps: [AppConfig], multi: true }
    ],
    ...
});
export class AppModule { 
...
}
  • The first line makes AppConfig class available to Angular.
  • The second line uses APP_INITIALIZER to execute Config.load() the method before application startup. The ‘multi: true’ is being used because an application can have more than one line of APP_INITIALIZER.
  • Make sure you set “HttpModule” in “imports” section if you want to make HTTP calls using Angular built-in Http library.

Setup app.config.ts

Create a class AppConfig and name the file ‘app.config.ts’ (It doesn’t matter what file name you keep for the same).

This is the place, we will do the reading of the environment and config files. The data of both files will be stored in the class so we can retrieve them later.

Note that, native Angular Http the library is used to read the JSON files.

import { Inject, Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Rx';

@Injectable()
export class AppConfig {

    private config: Object = null;
    private environment:    Object = null;

    constructor(private http: Http) {

    }

    /**
     * Use to get the data found in the second file (config file)
     */
    public getConfig(key: any) {
        return this.config[key];
    }

    /**
     * Use to get the data found in the first file (environment file)
     */
    public getEnv(key: any) {
        return this.environment[key];
    }

    /**
     * This method:
     *   a) Loads "environment.json" to get the current working environment (e.g.: 'production', 'development')
     *   b) Loads "config.[environment].json" to get all environment's variables (e.g.: 'config.development.json')
     */
    public load() {
        return new Promise((resolve, reject) => {
            this.http.get('environment.json').map( res => res.json() ).catch((error: any):any => {
                console.log('Configuration file "environment.json" could not be read');
                resolve(true);
                return Observable.throw(error.json().error || 'Server error');
            }).subscribe( (envResponse) => {
                this.environment= envResponse;
                let request:any = null;

                switch (envResponse.environment) {
                    case 'production': {
                        request = this.http.get('config.' + envResponse.environment+ '.json');
                    } break;

                    case 'development': {
                        request = this.http.get('config.' + envResponse.environment+ '.json');
                    } break;

                    case 'default': {
                        console.error('Environment file is not set or invalid');
                        resolve(true);
                    } break;
                }

                if (request) {
                    request
                        .map( res => res.json() )
                        .catch((error: any) => {
                            console.error('Error reading ' + envResponse.environment+ ' configuration file');
                            resolve(error);
                            return Observable.throw(error.json().error || 'Server error');
                        })
                        .subscribe((responseData) => {
                            this.config = responseData;
                            resolve(true);
                        });
                } else {
                    console.error('environmentconfig file "environment.json" is not valid');
                    resolve(true);
                }
            });

        });
    }
}

Why use Promises? — See that, resolve() is used in all scenarios because we don’t want the application to crash if any problem is found in the configuration files. If you prefer, you can set error scenarios to reject().

If you want you can use Observable from Rxjs too. (Recommended for Angular 5+ versions)

Create environment.json

This is the place, you will configure the current development environment. Allowed values are ‘development’ and ‘production’.

{
    "env": "development"
}

or

{
    "env": "production"
}

You may add this file to .gitignore your convenience.

Setup your config.development.json

This is the place you will configure development config variables. You can add as many variables as you want to this JSON file.

{
    "host": "localhost"
}

You may add this file to .gitignore to your convenience.

Set up config.production.json

This is the place you will write production config variables. You can add as many variables as you want to this JSON file.

{
    "host": "192.168.10.142"
}

You may add this file to .gitignore to your convenience.

Access values in Any Angular Component

Example of how you can read the values previously loaded from both files. In this case, we are reading the ‘host’ variable from the config file and ‘environment’ from the environment.json file.

import { AppConfig } from './app.config';

export class AnyClass {
    constructor(private config: AppConfig) {
        // note that AppConfig is injected into a private property of AnyClass
    }
    
    myMethodToGetHost() {
        // will print 'localhost'
        let host:string = config.get('host');
    }
    
    myMethodToGetCurrentEnv() {
        // will print 'development'
        let env: string = config.getEnv('environment');
    }
}

Bingo, You did it! If you make the prod build using ng build --prod command, then it works fantastically with charm.

If you find this article helpful, Show some love with upvotes, and share it with your friends.

adsense


Discover more from 9Mood

Subscribe to get the latest posts sent to your email.


Like it? Share with your friends!

What's Your Reaction?

Lol Lol
0
Lol
WTF WTF
0
WTF
Cute Cute
0
Cute
Love Love
0
Love
Vomit Vomit
0
Vomit
Cry Cry
0
Cry
Wow Wow
0
Wow
Fail Fail
0
Fail
Angry Angry
0
Angry
Rakshit Shah

Legend

Hey Moodies, Kem chho ? - Majama? (Yeah, You guessed Right! I am from Gujarat, India) 25, Computer Engineer, Foodie, Gamer, Coder and may be a Traveller . > If I can’t, who else will? < You can reach out me by “Rakshitshah94” on 9MOodQuoraMediumGithubInstagramsnapchattwitter, Even you can also google it to see me. I am everywhere, But I am not God. Feel free to text me.

0 Comments

Leave a Reply

Choose A Format
Story
Formatted Text with Embeds and Visuals
List
The Classic Internet Listicles
Ranked List
Upvote or downvote to decide the best list item
Open List
Submit your own item and vote up for the best submission
Countdown
The Classic Internet Countdowns
Meme
Upload your own images to make custom memes
Poll
Voting to make decisions or determine opinions
Trivia quiz
Series of questions with right and wrong answers that intends to check knowledge
Personality quiz
Series of questions that intends to reveal something about the personality
is avocado good for breakfast? Sustainability Tips for Living Green Daily Photos Taken At Right Moment