Передача переменных окружения в библиотеку angular2

Я создал внутреннюю библиотеку компании, используя генератор annomanr2-library yoman.

Некоторые из служб angular используют переменные среды в наших текущих приложениях (конечные точки api изменяются на каждом env). Мне было интересно, как лучше всего передать текущий объект среды в службы библиотеки angular2?

Ответ 1

В случае, если вы все еще ищете решение, вот как я сделал что-то похожее на то, о чем вы просили (используя 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(). В массиве поставщиков вы можете предоставлять услуги, значения и многое другое. В этом случае '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 environment:
        return this.http.get('${this.env.apiUrl}/images')
            .map(res => res.json());
    }

}

Надеюсь, это поможет!

Ответ 2

Я нашел альтернативное решение этой проблемы в проблеме GitHub. Решение в потоке GitHub содержит ошибку (опечатку), поэтому я включаю фиксированное решение здесь:

Для начала добавьте провайдера в свой AppModule верхнего уровня, который содержит файл вашей среды.

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

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

Наконец, используйте Inject decorator для включения файла среды в любую другую часть вашего приложения (библиотеку или иное):

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

  private environment

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

}

Ответ 3

There is a Better Way я Think from здесь

я думаю, что есть лучший способЯ подумал, что вы, ребята, сочтете это полезным: использование абстрактных классов в качестве маркеров внедрения зависимостей для заменяемого поведения

У меня есть 3 приложения Angular в проекте Nx, которые имеют общие переменные среды. Общедоступный сайт, частный портал и приложение администратора. В моих библиотеках я использую абстрактный класс Environment, который определяет общие переменные среды.

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

Затем я изменил 3 файла environment.ts следующим образом.

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'
  };
}

export const environment = new EnvironmentImpl(); Environment.prod.ts, конечно, будет симметричен dev environment.ts. Затем я предоставляю соответствующую зависимость от среды в корневом каталоге app.module.ts для каждого приложения Angular.

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 {}

Теперь любой компонент может внедрять зависимости среды простым и понятным способом.

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

@Component({
  selector: 'my-login',
  templateUrl: './my-login.component.html'
})
export class MyLoginComponent {
  constructor(private env: Environment) {}
}

Он заставляет каждый environment.ts реализовывать "общие" переменные среды, определенные в абстрактном классе. Кроме того, каждый соответствующий EnvironmentImpl может быть расширен за счет собственных переменных среды, специфичных для приложения. Этот подход кажется очень гибким и чистым. Ура! ^ _ ^

Ответ 4

Если вы все еще ищете ответ. В текущей версии ie Angular> 6 вам не нужно ничего делать.

Команды angular-cli "ng build --prod (для Production) & ng build (для разработки)" позаботятся об этом для вас.

Пример. Если вы запускаете проект в среде разработки, все переменные захватываются из src/environment/environment.ts. В проекте библиотеки компонентов просто импортируйте "import {environment] из" среды/среды "; (пожалуйста, убедитесь в том, что путь) будет отслеживать среду в зависимости от команды сборки углового-cli.