在Angular 2中加载配置JSON文件

时间:2017-02-08 10:38:23

标签: json angular typescript

我想在Angular 2(这是一个普通的TypeScript文件)中加载具有WebAPI EndPoints的常量文件。 在Angular1.x中。我们曾经有过相同的常数。 如何在Angular 2中实现相同的目标?

我创建了.ts文件。我主要关注的是如何在每个其他类文件加载时预先加载文件。

.ts文件:

export class testAPI {
     getAPI = "myUrl";
}

在服务文件中我通过正常导入使用相同的东西:

constructor(private http: Http) { 

      //console.log(this.test);
      console.log(this.testing.getAPI);
      //this.test.load();
    }

我将控制台视为未定义。(必须是因为我的Service类在API类之前加载)。

先谢谢。

6 个答案:

答案 0 :(得分:10)

<强>更新

启发了针对此特定问题的解决方案,创建了ngx-envconfig包,并将其发布在NPM注册表中。它具有与本答案中提供的功能相同的功能,甚至更多。

您可以将JSON文件放在assets文件夹中的某个位置,例如:$agentPhone = types_render_field( "agent-phone" ); $agentEmail = types_render_field( "agent-email" ); $agentFax = types_render_field( "agent-fax" ); 。根据环境是否开发,您可以使用两个assets/config文件,一个用于开发,一个用于生产。因此,您可以拥有.jsondevelopment.json个文件,其中每个文件都会保留相应的API端点。

基本上你需要完成以下步骤:

1。设置环境(如果已经有,请跳过此步骤)

production.json文件夹中创建两个文件:

<强> environment.prod.ts

src/environments

<强> environment.ts

export const environment = {
  production: true
};

2。创建JSON配置文件

<强> 资产/配置/ production.json

export const environment = {
  production: false
};

<强> 资产/配置/ development.json

{
  "debugging": false,

  "API_ENDPOINTS": {
    "USER": "api/v1/user",
    ...
  }
}

3。按如下方式创建服务

注意,根据环境,{ "debugging": true, "API_ENDPOINTS": { "USER": "api/v1/user", ... } } 将加载相应的文件

ConfigService

4。与app.module.ts

集成
import { Injectable, APP_INITIALIZER } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs';

import { environment } from 'environments/environment'; //path to your environment files

@Injectable()
export class ConfigService {

    private _config: Object
    private _env: string;

    constructor(private _http: Http) { }
    load() {
        return new Promise((resolve, reject) => {
            this._env = 'development';
            if (environment.production)
                this._env = 'production';
            console.log(this._env)
            this._http.get('./assets/config/' + this._env + '.json')
                .map(res => res.json())
                .subscribe((data) => {
                    this._config = data;
                    resolve(true);
                },
                (error: any) => {
                    console.error(error);
                    return Observable.throw(error.json().error || 'Server error');
                });
        });
    }
    // Is app in the development mode?
    isDevmode() {
        return this._env === 'development';
    }
    // Gets API route based on the provided key
    getApi(key: string): string {
        return this._config["API_ENDPOINTS"][key];
    }
    // Gets a value of specified property in the configuration file
    get(key: any) {
        return this._config[key];
    }
}

export function ConfigFactory(config: ConfigService) {
    return () => config.load();
}

export function init() {
    return {
        provide: APP_INITIALIZER,
        useFactory: ConfigFactory,
        deps: [ConfigService],
        multi: true
    }
}

const ConfigModule = {
    init: init
}

export { ConfigModule };

现在,您可以在任何地方使用ConfigService,获取config import { NgModule } from '@angular/core'; import { ConfigModule, ConfigService } from './config/config.service'; @NgModule({ imports: [ ... ], providers: [ ... ConfigService, ConfigModule.init(), ... ] }) export class AppModule { } 文件中定义的必要API端点。

答案 1 :(得分:6)

可以在TypeScript中导入JSON。你需要添加打字:

typings.d.ts:

declare module "*.json" {
  const value: any;
  export default value;
}

然后像这样导入:

import config from "../config/config.json";

config.json:

{
  "api_url": "http://localhost/dev"
}

答案 2 :(得分:4)

在使用Angular CLI生成的Angular 4+项目中,您将直接使用environment文件夹。在其中,您可以从Karlen的答案中找到environment.ts文件。需要注意的是,这是一种可行的配置解决方案:在构建时就捕获了环境变量。

为什么重要? 在为Angular应用程序设置CI / CD管道时,通常会使用一个构建工具来构建项目(例如Jenkins)和一个部署工具(例如Octopus)来抓取该程序包(dist文件夹),部署到选定的环境,并在此过程中用正确的值替换您的环境变量。如果使用environment.ts文件,则无法以这种方式替换您的环境变量,因为environment.ts文件未包含在dist文件夹中。您的部署工具无法拾取和编辑文件。

我们该怎么办?我们可以在assets文件夹中添加一个JSON配置文件。这些文件默认包含在我们要部署的dist文件夹中。当我们要使用环境变量时,我们只需导入诸如import config from '[relative/path/to/your/config/file.json]'之类的设置。

这样做时,我们会收到类似以下错误的信息:

Cannot find module '../../config.json'. Consider using '--resolveJsonModule' to import module with '.json' extension

这是因为打字稿编译器尝试导入导出的模块而找不到该模块。我们可以通过在tsconfig.json文件中添加以下JSON属性/值来解决此问题。

"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,

resolveJsonModule允许打字稿编译器导入,从中提取类型并生成.json文件。

allowSyntheticDefaultImports允许从模块进行默认导入,而没有默认导出。

有了这个,我们可以运行我们的项目,发现错误已经消失,我们可以使用配置值而没有任何问题。

现在,由于此配置文件包含在服务器上已部署的dist文件夹中,因此我们可以配置部署工具,以将变量值替换为要部署到的环境的特定值。有了此功能,我们可以构建一次Angular应用并将其部署到任何地方

另一个额外的好处是,大多数部署工具(如Octopus)都附带了本机JSON支持,因此您可以对其进行配置,以非常轻松地替换JSON文件中的环境变量。另一种选择是使用正则表达式解决方案替换.ts文件中的环境变量,该文件相对更复杂且容易出错。

答案 3 :(得分:2)

我有同样的问题,最后我放弃了.ts并将它放入.js:D这样:

root中的configuration.js

var configuration = {
    'apiHost': 'http://localhost:8900',
    'enableInMemoryWebApi': false,
    'authMode': 'standalone',
    'wsUrl': 'ws://localhost:8900/ws'
};

module.exports = configuration;

在.ts文件中为ex。 user.service.ts

let configuration = require('../configuration'); //in import section
@Injectable()
export class UserService {
    ...
    getUser(id: number | string): Promise<User> {
        console.log(configuration.apiHost) //will get propertye from .js file
        return this.http.get(`${configuration.apiHost}/${id}`, this.headers).toPromise().then(this.extractData).catch(this.handleError);
    }
}

希望有所帮助

答案 4 :(得分:0)

您可以使用Opague token将常量值设置为提供商

尝试: 在你的const文件中:

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

export const CONFIG_TOKEN = new OpaqueToken('config');
export const CONFIG = {
  apiUrl: 'myUrl'
};

在AppModule中设置为使其成为应用程序的单一提供者:

providers:[
//other providers,
{provide: CONFIG_TOKEN, useValue: CONFIG}
]

对于构造函数中的注入,

constructor( @Inject(CONFIG_TOKEN) private config)

答案 5 :(得分:0)

是的,我做了@karlen

我的app.module.ts具有与上述类似的模式。

AppConfiguration,
{provide:APP_INITIALIZER,useFactory:initConfig, deps:[AppConfiguration],multi:true}

仍然存在与其他服务尝试从文件加载AppConfiguration之前注入值的问题相同的问题