将环境变量传递给angular2库

时间:2017-04-20 21:07:13

标签: angular angular-cli

我使用angualr2-library yeoman generator创建了公司内部库。

一些角度服务在我们当前的应用程序中使用环境变量(api端点在每个env上都有变化)。我想知道将当前环境对象传递给angular2库服务的最佳方法是什么?

6 个答案:

答案 0 :(得分:25)

如果你仍然在寻找解决方案,这就是我如何完成与你所要求的相似的东西(使用Angular 4.2.4)。

AppModule(或您要导入图书馆的地方)中,拨打forRoot()上的LibraryModule方法。借助此功能,您可以将任何配置值传递给您的库,例如你应用的环境。

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

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        ...
        LibraryModule.forRoot(environment)
    ],
    bootstrap: [AppComponent]
})
export class AppModule {
}

LibraryModule当然需要提供forRoot()方法。 然后,在providers数组中,您可以提供值and more的服务。在这种情况下,为了简单起见,'env'充当保存给定环境对象的令牌。您也可以使用InjectionToken代替。

@NgModule({
    ...
})
export class LibraryModule {

    public static forRoot(environment: any): ModuleWithProviders {

        return {
            ngModule: LibraryModule,
            providers: [
                ImageService,
                {
                    provide: 'env', // you can also use InjectionToken
                    useValue: environment
                }
            ]
        };
    }
}

由于您的env现在提供了令牌LibraryModule,因此您可以将其注入其所有子服务或组件中。

@Injectable()
export class ImageService {

    constructor(private http: Http, @Inject('env') private env) {
    }

    load(): Observable<any> {
        // assume apiUrl exists in you app's environment:
        return this.http.get(`${this.env.apiUrl}/images`)
            .map(res => res.json());
    }

}

我希望有所帮助!

答案 1 :(得分:6)

我在a GitHub issue中找到了解决此问题的替代解决方案。 GitHub线程中的解决方案有一个错误(错字),因此我在此处包括了固定的解决方案:

首先,将一个提供程序添加到包含您的环境文件的顶级AppModule中。

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

@NgModule({
  providers: [
    {provide: 'environment', useValue: environment}
  ]
  // object properties omitted for brevity...
})
class AppModule {}

最后,利用Inject装饰器将环境文件包含在您希望的应用程序的任何其他部分中(库或其他):

@Component({
  // object properties omitted for brevity
})
class MyComponent {

  private environment

  constructor(
    @Inject('environment')
    environment
  ) {
    this.environment = environment
  }

}

答案 2 :(得分:4)

使用 Angular 11 的完整工作解决方案。假设您使用命令 library1 生成了一个名为 ng generate library library1 的库。

<块引用>

应用模块文件

// Your other imports ...
import { Library1Module } from 'library1';
import { environment } from 'src/environments/environment';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,

    // Pass the data you want to share with your library. Here we will pass 'apiUrl'. 
    Library1Module.forRoot({ apiUrl: environment.apiUrl }),

    AppRoutingModule
  ]
})
export class AppModule { }
<块引用>

library1.module.ts('Library1'模块主文件):

import { ModuleWithProviders, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Configurations } from './configurations';
import { Library1Component } from './library1.component';

@NgModule({
  declarations: [Library1Component],
  imports: [CommonModule],
  exports: [Library1Component]
})
export class Library1Module {

  // Create this static method in the library module.
  public static forRoot(config: Configurations): ModuleWithProviders<Library1Module> {

    return {
      ngModule: Library1Module,
      providers: [
        { provide: Configurations, useValue: config }
      ]
    };
  }

}
<块引用>

configurations.ts(在“projects\library1\src\lib”文件夹中声明这个类)。声明您需要从“环境”文件中获取的所有配置。

export class Configurations {
  public apiUrl: string;

  constructor() {
    this.apiUrl = '';
  }

}
<块引用>

library1.service.ts('Library1Service' 将接收配置对象)。

import { Injectable, Optional } from '@angular/core';
import { Configurations } from './configurations';

@Injectable({
  providedIn: 'root'
})
export class Library1Service {

  private _apiUrl = 'No value';

  constructor(@Optional() config?: Configurations) {
    if (config) {
      this._apiUrl = config.apiUrl;
    }
  }

  get apiUrl() {
    return this._apiUrl;
  }

}
<块引用>

library1.component.ts(使用配置数据的Library1组件)。

import { Component } from '@angular/core';
import { Library1Service } from '../public-api';

@Component({
  selector: 'lib-library1',
  template: `
    <p>
      This component inside "library1" library and reads the values from "environment.ts" file.
    </p>

    <h1>API URL : {{apiUrl}}</h1>`
})
export class Library1Component {
  apiUrl = '';

  constructor(library1Service: Library1Service) {
    this.apiUrl = library1Service.apiUrl;
  }
}
<块引用>

app.component.ts(使用 library1 组件确认 URL 已传递到您的库)。

.......
<lib-library1></lib-library1>
.......

答案 3 :(得分:0)

如果您仍在寻找答案。 在当前版本中,即Angular> 6,您无需执行任何操作。

angular-cli命令“ ng build --prod(用于生产)和ng build(用于开发)”将为您解决这个问题。

示例:如果要在开发环境中运行项目,则将从src / environments / environment.ts中捕获所有变量。 在您的组件库项目中,只需导入“从'environments / environment'导入{环境};“。 (请确保路径正确无误),这将取决于angle-cli build命令。

答案 4 :(得分:0)

我认为here的一种更好的方法

我认为你们会发现这很有用:将抽象类用作可交换行为的依赖注入标记

我在Nx项目中有3个Angular应用程序,它们共享一些常见的环境变量。公共站点,私有门户和管理应用程序。在我的库中,我使用的是抽象的Environment类,该类定义了常见的环境变量。

 function clear_styles_and_scripts() {
     global $wp_scripts;
     global $wp_styles;

foreach( $wp_scripts->queue as $handle ) :

    wp_dequeue_script( $handle );
    wp_deregister_script( $handle );

     endforeach;

foreach( $wp_styles ->queue as $handle ) :

    wp_dequeue_style( $handle );
    wp_deregister_style( $handle );

    endforeach;

 }
  add_action( 'wp_enqueue_scripts', 'clear_styles_and_scripts', 100 );

然后我将3个environment.ts文件更改如下。

export abstract class Environment {
  abstract readonly production: boolean;
  abstract readonly appUrls: {
    readonly public: string;
    readonly portal: string;
    readonly admin: string;
  };
}

export const environment = new EnvironmentImpl(); 当然,environment.prod.ts与dev environment.ts是对称的。然后,在根目录app.module.ts中为每个Angular应用程序提供各自的环境依赖性。

import { Environment } from '@my-lib-prefix/common';

class EnvironmentImpl implements Environment {
  production = false;
  appUrls = {
    public: 'http://localhost:4200',
    portal: 'http://localhost:4201',
    admin: 'http://localhost:4202'
  };
}

现在,任何组件都可以以干净,通用的方式注入环境依赖项。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { Environment } from '@my-lib-prefix/common';
import { environment } from '../environments/environment';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [{ provide: Environment, useValue: environment }],
  bootstrap: [AppComponent]
})
export class AppModule {}

它强制执行每个environment.ts以实现抽象类中定义的“公共”环境变量。此外,每个相应的EnvironmentImpl都可以使用针对应用的特定环境变量进行扩展。这种方法看起来非常灵活和干净。干杯! ^ _ ^

答案 5 :(得分:0)

如果您要为firebase传递环境变量,只需在您的库中使用它即可:

@NgModule({
  declarations: [MyAngularComponent],
  exports: [MyAngularComponent],
  imports: [
    AngularFireModule,
    AngularFirestoreModule,
    CommonModule
  ]
})
export class MyAngularModule {

  public static forRoot(firebaseConfig: FirebaseOptions): ModuleWithProviders<MyAngularModule> {

    return {
      ngModule: MyAngularModule,
      providers: [
        { provide: FIREBASE_OPTIONS, useValue: firebaseConfig }
      ]
    }
  }
}

然后将其导入,就像AngularFire ...

MyAngularModule.forRoot(environment.firebase)

来自此帖子:pass angularFire config imported in library using forRoot