【问题标题】:FileReplacements vs Environment variables文件替换与环境变量
【发布时间】:2020-02-18 12:03:07
【问题描述】:

我有一个案例,我必须能够为两个不同的服务器部署我的 Angular 6 项目,每个服务器都有稍微不同的 API、用户处理等。 出于这个原因,我以服务的形式添加了不同的抽象层,以保持与其余代码的接口相同。

因为文件将具有完全不同的内容,我想在单独的文件中编写单独的服务,并仅将一组服务设置为“活动”,例如获取数据、处理用户等。

app/
├── core/
│   ├── Server1.user.service.ts
│   ├── Server2.user.service.ts
│   ├── Server1.data.service.ts
│   ├── Server2.data.service.ts
│   └── ...
├── components/
│   ├── ...
│   └── ...
└── ...

我想要避免的是在我的代码中有很多if (deployedForServer1) {...},因为这很难维护并且很难保持概述。

现在我不确定,实现这一点的最佳方法是什么。

我的第一种方法是用 angular.json 中的“fileReplacements”替换服务。这样做的好处是只部署我需要的代码,但会导致相当复杂的 angular.json 配置。

另一种方法是通过环境变量处理它,但在这里我不确定是否可以避免在我的代码中出现多个类似if (deployedForServer1) {...} 的查询。

我的意思不是要以意见来回答这个问题,而是要提供这些方法中的一种方法是否存在根本错误或我现在没有看到的任何严重缺点的信息。

【问题讨论】:

    标签: angular environment-variables


    【解决方案1】:

    第二个实现if(deployedForServer1) { ... } 是错误的,将成为维护的绝对噩梦。如果发生变化,例如新的 api 地址或新端口,您将需要更改代码并部署新的生产版本。此外,它的扩展性非常差。如果您想在其他 5 台服务器上部署应用程序,则需要在代码中添加。

    如果只有主机地址是动态的,那么你要遵循的原则:一次构建,到处部署。

    您可以创建服务:

    import { Injectable } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    import { environment } from 'src/environments/environment';
    
    @Injectable({
        providedIn: 'root'
    })
    export class AppConfigService {
        constructor(
            private http: HttpClient
        ) { }
    
        private appSettings: any = {};
    
        setAppConfig() {
    
            if(environment.production) {
                return this.http.get('config.json')
                    .toPromise()
                    .then(apiKeys => {
                        this.appSettings = apiKeys;
                    })
                    .catch(error => {
                        console.error(error)
                        return Promise.reject();
                    })
            } else {
                this.appSettings = environment.configToApi;
                return Promise.resolve();
            }
    
        }
    
        getAppSettings() {
            return this.appSettings;
        }
    }
    
    

    然后你将在你的app.module 中使用APP_INITIALIZER 调用setAppConfig() 函数:

    {
              provide: APP_INITIALIZER,
              useFactory: (appConfig: AppConfigService) => {
                  return () => {
                      return appConfig.setAppConfig();
                  }
              },
              multi: true,
              deps: [AppConfigService]
    }
    

    您看,该服务读取一个本地文件config.json,该文件将保存服务器特定的配置:

    {
        "apiAddress": "...",
        "apiAddress2": "..."
    }
    
    

    配置存储在服务的appSettings对象中,您可以随时调用getAppSettings()访问配置。

    这种方法的优点是:

    1. 您只需构建一次,即可在任何地方部署
    2. 配置是在运行时设置的,而不是在构建时设置的。这意味着无需构建/部署新版本即可更改任何服务器配置。

    【讨论】:

    • 这是一个非常好的方法,我肯定也需要。不幸的是,它的区别远不止一些常量,它是一个完全不同的 API,需要严格的抽象,所以仅仅一个配置文件是行不通的。
    • 啊,我明白了。然后我会在 angular.json 中使用不同的配置,因为您需要替换完全不同的 API 和抽象等。
    猜你喜欢
    • 2011-07-13
    • 2021-08-01
    • 2016-02-02
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    • 2011-08-18
    • 2019-12-26
    • 1970-01-01
    相关资源
    最近更新 更多