【问题标题】:Configuring angular production files after build构建后配置角度生产文件
【发布时间】:2023-03-13 19:36:01
【问题描述】:

我有一个 Angular 9 项目,它是应用程序套件安装程序 [Wix 安装程序] 的一部分。 Angular 应用程序使用的设置之一是 API 的地址,它从某个可配置的地址获取数据。我知道我可以拥有许多角度环境文件,只需使用以下命令即可:

environment.env1.ts

export const environment = {
  production: true,
  apiAddress: "http://apiAddress1/api/",
};


ng build --prod --configuration=env1    

environment.env2.ts

    export const environment = {
      production: true,
      apiAddress: "http://apiAddress2/api/",
    };

    ng build --prod --configuration=env2

这意味着对于每个潜在的 API 地址,我都需要进行新的构建并运行以上命令。如何克服上述情况并在构建后配置输出二进制文件?

假设没有明确的方法来实现构建后的配置,我可以对生成的 main*.js 文件中的 API 地址进行“简单字符串替换”吗?会有副作用吗?

【问题讨论】:

标签: angular angular-cli angular-aot angular-compiler angular-cli-v9


【解决方案1】:

可能在构建完成后对生成的文件执行查找和替换,但这感觉不对。

而是创建一个 configuration.json 文件并将其放在您的资产文件夹中。然后在您的应用程序中,使用导入直接引用该文件。您可能必须通过在 tsconfig.json 中将 resolveJsonModule 设置为 true 来启用此功能。

现在,在构建应用程序后,可以使用简单的技术替换 configuration.json 中的值,而不必担心意外的副作用,例如在 NodeJs 中使用 fs.readFileSync(path)fs.writeFileSync(path, JSON.stringify(data))

示例 xyz.module.ts 部分

import dynamicConfig from '../assets/configuration.json';
@NgModule({
  providers: [
    {
      provide: API_BASE_URL,
      useValue: dynamicConfig.apiAddress
    }
  ]
})
export class XyzModule { }

【讨论】:

    【解决方案2】:

    您可以在配置文件中外包您的 api 端点。并提供AppInitializer 以使用您的配置文件。 这是一个例子:

    loader函数,通过http从/config/config.json加载配置并设置api配置:

    export function loadConfig(http: HttpClient, config: ApiConfiguration): (() => Promise<boolean>) {
      return (): Promise<boolean> => {
        return new Promise<boolean>((resolve: (a: boolean) => void): void => {
          http.get('./config/config.json')
            .pipe(
              map((x: any) => {
                config.rootUrl = x.rootUrl + '/v2';
                resolve(true);
              }),
              catchError((x: { status: number }, caught: Observable<void>): ObservableInput<{}> => {
                // 404 local development, other errors are strange
                resolve(x.status === 404);
                return of({});
              })
            ).subscribe();
        });
      };
    }
    

    json 只包含一个名为rootUrl 的字符串。

    要使用此功能,请在应用初始化之前,在您的app.module.ts 中提供AppInitializer

    providers: [
        {
          provide: APP_INITIALIZER,
          useFactory: loadConfig,
          deps: [
            HttpClient,
            ApiConfiguration
          ],
          multi: true
        }
    

    ApiConfiguration 存储 api 端点,它只是一个具有默认值的类(用于开发):

    @Injectable({
      providedIn: 'root',
    })
    export class ApiConfiguration {
      rootUrl: string = 'localhost:8080';
    }
    

    只需将配置文件放在您的 /dist 文件夹中,它应该可以工作 :)

    【讨论】:

    • 这是一个非常好的解决方案。我以前没有听说过APP_INITIALIZER。您可以直接使用toPromise(),而不是将可观察对象包装在 Promise 中吗?
    • 我不确定,但这也应该有效@DanielGimenez
    猜你喜欢
    • 2020-11-19
    • 1970-01-01
    • 2019-05-01
    • 1970-01-01
    • 2019-04-04
    • 1970-01-01
    • 2020-04-11
    • 1970-01-01
    • 2019-08-22
    相关资源
    最近更新 更多