angular 初始化_应用程序初始化程序的工作原理,因此您需要了解有关angular中动态配置的知识...

angular 初始化

When we develop an application designed to run on multiple environments, we have to decide how to provide a configuration of appropriate variables depending on those environments

当我们开发旨在在多种环境下运行的应用程序时,我们必须决定如何根据这些环境提供适当的变量配置

TLDR; 📕 (TLDR; 📕)

  • environment.ts is not the best way to provide an environment configuration

    environment.ts不是提供一个环境配置的最佳途径

  • do not introduce environmental configuration in build-time

    不要在构建时引入环境配置
  • Special injection token called APP_INITIALIZER is used for convenient and effective external configuration providing

    称为APP_INITIALIZER的特殊注入令牌可用于方便有效的外部配置,以提供

  • I’ve prepared for you the minimal example which solves this problem by using APP_INITIALIZER. You can find it on StackBlitz

    我已经为您准备了使用APP_INITIALIZER解决此问题的最小示例。 您可以在StackBlitz上找到它

第一轮❓(First round ❓)

The simplest example of an environmental variable is API configuration. Commonly, we use a different URL depending on target environment. For instance:

环境变量的最简单示例是API配置。 通常,我们根据目标环境使用不同的URL。 例如:

  • dev: https://yourdomain.dev.org/api/resources

    开发人员:https://yourdomain.dev.org/api/resources
  • test: https://yourdomain.test.org/api/resources

    测试:https://yourdomain.test.org/api/resources
  • prod: https://yourdomain.prod.org/api/resources

    产品:https://yourdomain.prod.org/api/resources

In many Angular projects that I have seen, this problem has been solved by using analogous files provided by the Angular framework: environment.dev.ts, environment.test.ts and environment.prod.ts.

在我见过的许多Angular项目中,已通过使用Angular框架提供的类似文件解决了此问题: environment.dev.tsenvironment.test.tsenvironment.prod.ts

These files for our example would look like this

这些示例文件看起来像这样

// environment.dev.ts
export const environment = {
  production: true,
  apiUrl: "https://yourdomain.dev.org/api/resources"
};


// environment.test.ts
export const environment = {
  production: true,
  apiUrl: "https://yourdomain.test.org/api/resources"
};


// environment.prod.ts
export const environment = {
  production: true,
  apiUrl: "https://yourdomain.prod.org/api/resources"
};

It cannot be said that this approach is very bad or does nor meet the assumptions made. However, look what happens if you choose this way to keep your variables and want to complete the full cycle of application delivery to production.

不能说这种方法是非常糟糕的,或者不能满足所做出的假设。 但是,看看如果您选择这种方式来保留变量并希望完成应用程序交付生产的整个周期会发生什么。

  1. If everything works fine locally, the application is built on the development environment using the environment.dev.ts file

    如果在本地一切正常,则使用environment.dev.ts文件在开发环境上构建应用程序
  2. If everything works fine in the development environment, we can promote it to the test environment. In order for the application to run in the test environment, the application must be rebuilt using the environment.test.ts file this time

    如果在开发环境中一切正常,我们可以将其升级到测试环境。 为了使应用程序在测试环境中运行,这次必须使用environment.test.ts文件重建应用程序。
  3. If the application has been tested in the test environment and is ready for production, we have to take the same steps. So we need to rebuild the application again using environment.prod.ts

    如果应用程序已经在测试环境中进行了测试并且可以投入生产,那么我们必须采取相同的步骤。 因此,我们需要使用environment.prod.ts再次重建应用程序

Please note one fact. The application must be built three times (!!!) before it goes from the developer’s hand to the production environment.

请注意一个事实。 该应用程序必须先构建三遍( !!! ),然后才能从开发人员的手转到生产环境。

得出的第一个结论是: (The first conclusions that arise are: 👈)

  • If you want to deliver a small change to production, you have to repeat the same building process several times, which will significantly extend the delivery time.

    如果要对生产进行少量更改,则必须重复几次相同的构建过程,这将大大延长交付时间。
  • You can never be sure that a tested artifact from the dev environment or test will build correctly on the prod environment

    您永远无法确保开发环境或测试中经过测试的工件会在生产环境中正确构建

Based on these conclusions and my own experience, I can safely and honestly tell you that environment.ts files are not a good place to hold most types of configuration. More precisely:

根据这些结论和我自己的经验,我可以安全而诚实地告诉您,环境.ts文件不是保存大多数类型配置的好地方。 更确切地说:

Certain configuration types should not be shipped when building an artifact. Storing environment-dependent variables in Angular’s environment.ts is the anti-pattern. Unfortunately, common anti-pattern.

构建构件时,某些配置类型不应该交付。 在Angular的environment.ts中存储与环境有关的变量是反模式。 不幸的是,常见的反模式。

So if you choose not to hold your configuration in environment.ts, what can you do?

因此,如果您选择不将配置保存在environment.ts中,该怎么办?

第二回合-APP_INITIALIZER方法💪 (Round 2 — APP_INITIALIZER approach 💪)

Angular’s Injection Token APP_INITIALIZER comes with great help, thanks to which you can introduce additional initialization functions to your application. This functionality of the Angular framework ensures that the provided functions are executed when an application is started, while an application is still being initialized. These functions return a Promise object and an Angular’s app will not be initialized until it is being executed.

Angular的注入令牌APP_INITIALIZER带来了很大的帮助,您可以借助它为应用程序引入其他初始化函数。 Angular框架的此功能可确保在启动应用程序时仍在初始化应用程序时执行提供的功能。 这些函数返回一个Promise对象,并且在执行之前不会初始化Angular的应用程序。

Is is a proper way to pass the configuration?

是通过配置的正确方法吗?

当然! 即使在正式的Angular框架文档中,您也可以阅读:📕 (Of course! Even in the official Angular framework documentation, you can read: 📕)

You can, for example, create a factory function that loads language data or an external configuration, and provide that function to the APP_INITIALIZER token. That way, the function is executed during the application bootstrap process, and the needed data is available on startup.

例如,您可以创建一个工厂函数来加载语言数据或外部配置,并将该函数提供给APP_INITIALIZER令牌。 这样,该功能将在应用程序引导过程中执行,并且所需的数据在启动时可用。

Follow me on Twitter if you want to be updated about new great Angular and frontend stuff! 😄

如果您想了解有关Angular和前端新功能的最新信息,请在Twitter上关注我😄

实践中的运行时配置 (Runtime configuration in practice)

Firstly, we need a file to hold configuration details in, and it will not be part of JavaScript artifacts which are built when ng build is executed. This configuration file should be downloaded on demand when the application is initialized.

首先,我们需要一个文件来保存配置详细信息,它不会成为执行ng build构建JavaScript工件的一部分。 初始化应用程序时,应按需下载此配置文件。

// ./src/assets/config/configuration.json
{
  "apiUrl": "https://yourdomain.dev.org/api/resources"
}

for the following assumed configuration model.

对于以下假定的配置模型。

export type Configuration = {
  apiUrl: string;
}

We also need a service that has the responsibility to download the configuration and make it available while the application is running.

我们还需要一个服务,该服务负责下载配置并在应用程序运行时使其可用。

public loadConfiguration() {
    return this._http
      .get("src/assets/config/configuration.json")
      .toPromise()
      .then((configuration: Configuration) => {
        this._configuration = configuration;
        return configuration;
      })
      .catch((error: any) => {
        console.error(error);
      });
  }
}

The last step is to use the above method with the APP_INITIALIZER token. It is used in the providers section for a specific NgModule.

最后一步是将上述方法与APP_INITIALIZER令牌一起使用。 它在提供程序部分用于特定的NgModule

It’s worth to consider creating a separate module dedicated to fetching configuration instead of adding the following code to the main app.module.ts

值得考虑创建一个单独的模块专门用于获取配置,而不是将以下代码添加到主app.module.ts中

providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: loadConfiguration,
      deps: [ConfigurationLoader],
      multi: true
    }
  ]

The loadConfiguration function is provided with the useFactory parameter. The function itself looks like this

loadConfiguration功能设置有useFactory参数。 函数本身看起来像这样

export function loadConfiguration(configService: ConfigurationLoader) {
  return () => configService.loadConfiguration();
}

By following the steps above, we ensure the following behavior for our application

通过执行上述步骤,我们确保应用程序具有以下行为

  • when the application is started, the loadConfiguration from the ConfigurationLoader instance is run and it starts downloading the configuration from /assets/config/configuration.json

    启动应用程序时,将运行ConfigurationLoader实例中的loadConfiguration ,并开始从/assets/config/configuration.json下载配置

  • the application waits until the configuration is loaded from /assets/config/configuration.json

    应用程序等待,直到从/assets/config/configuration.json加载配置

  • Finally, the application is initialized and the configuration is available through getConfiguration method of ConfigurationLoader instance

    最后,初始化应用程序,并通过ConfigurationLoader实例的getConfiguration方法获得配置

The magic is that the configuration placed in the assets directory is not taken into account at the time of building. You can modify the contents of the assets directory at any time without rebuilding the app. So the scheme for delivering the application to production now looks like this

魔术是在构建时不考虑放置在资产目录中的配置。 您可以随时修改资产目录的内容,而无需重建应用程序。 因此,将应用程序交付生产的方案现在看起来像这样

  1. If everything works fine locally, the application is built on the development environment and the /assets/config/configuration.json file is delivered externally

    如果在本地一切正常,则该应用程序将在开发环境上构建,并且/assets/config/configuration.json文件将在外部交付

  2. If everything works fine in the development environment, the application is promoted to the test environment. In order to run the application in the test environment, we take the artifact already built and replace the /assets/config/configuration.json file, which this time contains the configuration specific to the test environment

    如果在开发环境中一切正常,则将应用程序升级到测试环境。 为了在测试环境中运行该应用程序,我们采用已经构建的工件,并替换/assets/config/configuration.json文件,这次文件包含特定于测试环境的配置。

  3. If the application is passed the tests in the test environment and is ready to go to the production, we take the same artifact again, push it to the prod environment and replace the analogous configuration file /assets/config/configuration.json for the prod environment.

    如果应用程序通过了测试环境中的测试并准备投入生产,我们将再次使用相同的工件,将其推送到生产环境中,并为该生产替换类似的配置文件/assets/config/configuration.json 。环境。

Wow! By using APP_INITIALIZER and runtime configuration approach, you are able to limit the process of building the application in the entire delivery cycle to only one time! Frankly speaking, this one time is the maximum number of times according to the best practices. You also ensured that your built artifact on the initial environment is equal to a single byte with what is placed in the final environment.

哇! 通过使用APP_INITIALIZER和运行时配置方法,您可以将在整个交付周期中构建应用程序的过程限制为一次! 坦白说,根据最佳实践,这一次是最大次数。 您还确保了在初始环境中构建的工件等于放置在最终环境中的单个字节。

If you want to see how this solution works, I have prepared a live example on StackBlitz for you.

如果您想了解该解决方案的工作原理,我已经为您准备了一个StackBlitz的实时示例。

Image for post

摘要📕 (Summary 📕)

  • environment.ts is not the best way to provide an environment configuration in Angular ecosystem. We can safely name it as anti-pattern.

    environment.ts提供在角生态系统的环境配置的最佳途径。 我们可以安全地将其命名为反模式。

  • do not introduce an environment configuration which is runtime-dependant

    不要引入依赖于运行时的环境配置

  • Injection Token — APP_INITIALIZER is used for convenient and effective external configuration delivery in Angular ecosystem.

    注入令牌— APP_INITIALIZER用于在Angular生态系统中方便有效地交付外部配置。

  • I have prepared for you a minimal example of solving the problem by using APP_INITIALIZER. You will find him on StackBlitz

    我已经为您准备了一个使用APP_INITIALIZER解决问题的最小示例。 您会在StackBlitz上找到他

Follow me on Twitter if you want to be updated about new great Angular and frontend stuff! 😄

如果您想了解有关Angular和前端新功能的最新信息,请在Twitter上关注我😄

翻译自: https://itnext.io/how-does-app-initializer-work-so-what-do-you-need-to-know-about-dynamic-configuration-in-angular-718e7c345971

angular 初始化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值