在 Angular 2 中加载配置 JSON 文件

Posted

技术标签:

【中文标题】在 Angular 2 中加载配置 JSON 文件【英文标题】:Load Config JSON File In Angular 2 【发布时间】:2017-06-25 22:26:15 【问题描述】:

我想在具有 WebAPI 端点的 Angular 2(这是一个普通的 TypeScript 文件)中加载常量文件。 在 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();
    

我将控制台设置为未定义。(一定是因为我的服务类在 API 类之前加载)。

提前致谢。

【问题讨论】:

如果涉及到ts文件,你可以简单地导入它 【参考方案1】:

您可以使用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)

【讨论】:

【参考方案2】:

我有同样的问题,最后我放弃了 .ts 并把它放在 .js 中:D 像这样:

根目录下的configuration.js

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

module.exports = configuration;

在 .ts 文件中,例如。 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);
    

希望对你有帮助

【讨论】:

一些错误?你是怎么放的?你把它放在哪里了? 在应用程序的主文件夹中添加 typing.d.ts 并在那里声明您每次要使用的变量。例如:声明 var System: any;声明 var 要求:任何; 我试过这个并且工作正常。但是移动 build 后 json 更改没有给出正确的结果。请帮助我【参考方案3】:

可以在 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"

【讨论】:

如何在文件中调用它?告诉我无法解析 api_url... angular5 尝试使用import * as configuration from '../config/config.json'; 并使用(&lt;any&gt;configuration)['api_url'];【参考方案4】:

更新

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


您可以将 JSON 文件放在资产文件夹中的某个位置,例如:assets/config。根据环境是否为开发环境,您可以使用两个.json 文件,一个用于开发,一个用于生产。因此,您可以拥有 development.jsonproduction.json 文件,每个文件都将保留适当的 API 端点。

基本上你需要经过以下步骤:

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

src/environments文件夹中创建两个文件:

environment.prod.ts

export const environment = 
  production: true
;

environment.ts

export const environment = 
  production: false
;

2。创建 JSON 配置文件

assets/config/production.json


  "debugging": false,

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

assets/config/development.json


  "debugging": true,

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

3。如下创建服务

注意根据环境,ConfigService会加载相应的文件

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 ;

4。与 app.module.ts 集成

import  NgModule  from '@angular/core';
import  ConfigModule, ConfigService  from './config/config.service';

@NgModule(
    imports: [
        ...
    ],
    providers: [
        ...
        ConfigService,
        ConfigModule.init(),
        ...
    ]
)

export class AppModule  

现在,您可以在任何想要获取配置.json 文件中定义的必要 API 端点的地方使用 ConfigService。

【讨论】:

感谢 Karlen。这更有帮助。你能告诉我,我如何在组件中访问此配置值 @kamalav 您只需要在您的组件中使用 ConfigService 并调用该服务所需的功能 很好的答案!如果您想升级到 Angular 6 和 rxjs 6 API,请查看此内容:metaltoad.com/blog/angular-6-upgrading-api-calls-rxjs-6 在我的例子中,整个应用程序已经使用 AppConfiguration 类从一些变量中加载值。所有其他服务都在构造函数中注入了 AppConfiguration。因此,我遵循上述模式并尝试使用服务设置 AppConfiguration 中的值。但是,这些值不会加载,因为其他服务会在 AppConfiguration 从文件加载之前尝试注入该值。有什么建议吗? @Ayush 你用过APP_INITIALIZER吗?您应该强制您的应用程序等待配置文件,为此您需要使用如上所述的 APP_INITIALIZER。【参考方案5】:

在使用 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

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

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

resolveJsonModule 允许 typescript 编译器导入、提取类型和生成 .json 文件。

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

有了这个,我们可以运行我们的项目,我们会发现我们的错误消失了,我们可以毫无问题地使用我们的配置值。

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

另一个额外的好处是,像 Octopus 这样的大多数部署工具都附带原生 JSON 支持,因此您可以将其配置为非常轻松地替换 JSON 文件中的环境变量。另一种方法是使用正则表达式解决方案来替换.ts 文件中的环境变量,这相对更复杂且容易出错。

【讨论】:

我已经关注了您的 cmets 更改,但在某些情况下它不会起作用,您可以看看这个问题。我遇到的问题被注入身份验证服务会引发错误,并且在工作正常的组件中***.com/questions/62768885/… 注意:以上配置项需要在tsconfig.json的compilerOptions部分,而不是根部分。 我必须包括:“esModuleInterop”:tsconfig.json 上的真实属性才能工作

以上是关于在 Angular 2 中加载配置 JSON 文件的主要内容,如果未能解决你的问题,请参考以下文章

ng build 后,字体真棒字体未在 Angular 中加载

防止浏览器在 Angular 中加载拖放文件

在 Angular-fullstack 中加载 local.env.js

在一个活动中加载单个片段两次,从本地json文件中加载2个问题

angular js:是不是需要在模块文件中加载所有控制器和工厂/服务

在 Angular 2 中加载第一页时设置 [(ngModel)] 的值