【问题标题】:Angular: Weird if statement behaviour in app.module.tsAngular:app.module.ts 中的奇怪 if 语句行为
【发布时间】:2020-09-09 07:30:47
【问题描述】:


我们最近在 app.module.ts 中遇到了奇怪的行为。我们使用 environment.ts 和 environemnt.prod.ts 文件在模块的导入数组中包含/排除特定库(库应该被排除在生产构建中)。它看起来像这样:

import { environment } from '../environments/environment'
//
@NgModule({
//
  imports: [
    CommonModule,
    BrowserModule,
    environment.production ? [] : libraryXXX,
    HttpClientModule,
    FormsModule
  ],

经过几天的调查后,我们发现 libraryXXX 每次都包含在构建中,即使带有 --prod 标志也是如此。我们测试了问题所在 - environment.ts/prod.ts 文件中的值被正确读取,但无论出于何种原因,比较总是返回 false。我的意思总是:将上面的片段替换为:

environment.production == true ? [] : libraryXXX

environment.production == false ? [] : libraryXXX

没有改变任何事情 - 图书馆总是包括在内。就像 if 语句被破坏了(?)。将其提取到变量并没有改变任何事情。我们最终做了半hacky的解决方案,比如:

环境.ts

import { libraryXXX } from 'whatever'

export const environment = {
  production: false,
  libraryXXX: libraryXXX
}

环境.prod.ts

export const environment = {
  production: true,
  libraryXXX: []
}

并简单地引用 app.module.ts 中的 environment.libraryXXX。但出于好奇 - 谁能向我解释为什么简单的 if 语句失败了?由于它是 app.module.ts 我无法调试它,甚至无法查看控制台输出,以了解发生了什么。有人有想法吗?

【问题讨论】:

  • 条件语句和表达式肯定没有损坏。此外,您遇到的行为是可以预料的。编译器无法删除该库,因为它不知道生产标志的值在运行时将是什么。这不是条件捆绑的完成方式,您不能这样做
  • 这应该可以。问题是,您是如何确定该库“始终包含”的?
  • @MikeOne 我们尝试简单地运行类似:“true ? [] : libraryXXX”和“false ? [] : libraryXXX”。不同之处在于输出文件。这个特定的库搞砸了捆绑文件。我们可以很容易地看到没有库的捆绑包工作正常,而带库的捆绑包被破坏了。因此,当离开上述任何类型的“if”语句时,构建总是一团糟。
  • 好吧,尽管有这种情况,lib 仍然有一个导入。该语句只是阻止它在模块范围内导入。不过应该是树状的..除非那个模块有点狡猾..

标签: javascript angular typescript build environment


【解决方案1】:

这会起作用。

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

const targetModules = [
    CommonModule,
    BrowserModule,
    HttpClientModule,
    FormsModule
];

if (environment.production) {
   targetModules.push(libraryXXX);
}

//
@NgModule({
//
  imports: targetModules,
//

【讨论】:

  • 看起来很有希望,我一定会试一试:)
【解决方案2】:

你可以做什么:

您可以导入 prod 和 mock 版本这两个库。

然后你可以决定(environment.production)你将提供哪一个:

providers: [
   {
      provide: DbTrassenanfrageStatusService,
      useClass: environment.production ? XyzMockService : XyzService
   }
]

如果您在谈论模块: 试试这个:

const exports = [];
if (environment.production === true) {
  exports.push(ModuleXyyyz);
  console.info('FactoryModule: ModuleXyyyz;');
} else {
  console.info('FactoryModule: nothing;');
}

@NgModule({
  imports: [
    ModuleXyyyz
  ],
  exports
})
export class FactoryModule {
}

然后在您的应用模块中导入 FactoryModule。

要“选择” environment.prod.ts 配置,只需通过 --prod 标志构建或启动它:

ng serve --prod
ng build --prod

请参阅angular cli doc 了解更多信息(--prod、--configuration,...)

如果你有这样的环境。*.ts:

export const environment = {
    production: true,
    env: 'prod',
    version: '{BUILD_VERSION}',
    commitHash: '{COMMIT_HASH}',
    showVersionIndicator: false,
    routerTracing: false,

...然后您可以在启动时(在您的应用组件中)打印出版本之类的字段:

console.info('Version: ', environment.version);

【讨论】:

  • 这不是他想要做的。他试图在构建时消除对开发版本的依赖,但基于运行时条件
  • environment.production 是构建时条件,而不是运行时条件。
  • 您确定没有将 CLI 标志 --configuration production 与环境对象混淆吗?你能告诉我这在 Angular 的 CLI 中记录在哪里吗?
  • 您可以使用以下命令设置配置:“ng build --configuration=XXX”。然后使用 environment.XXX.ts(它将被复制到 environment.ts 文件中)。在这个 ts 文件中,你可以有 production:true/false 或其他。
  • 当然可以。我的意思是编译器不会忽略问题中的导入
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多