noxi雑記

.NET、Angularまわりの小ネタブログ

Angular CLIのビルド時にProvideしていた値がnullになった

Angular 6でオブジェクトをProvideしていたら、その中のプロパティの一つがAngular CLIのProdなビルドを通すと null になってしまったので、防備録を兼ねてメモとして残します。

TL;DR

Provideしたオブジェクトをexportすれば影響を避けられる。

検証環境

この記事は以下の環境で動作確認を行っています。

Angular CLI: 6.0.1
Node: 9.11.1
OS: win32 x64
Angular: 6.0.1
... animations, cli, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.6.1
@angular-devkit/build-angular     0.6.1
@angular-devkit/build-optimizer   0.6.1
@angular-devkit/core              0.6.1
@angular-devkit/schematics        0.6.1
@ngtools/webpack                  6.0.1
@schematics/angular               0.6.1
@schematics/update                0.6.1
rxjs                              6.1.0
typescript                        2.7.2
webpack                           4.6.0

再現コード

以下のコードの様にオブジェクトをProvideすると、プロパティの値がnullになります。

// app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Provider } from '@angular/core';

import { AppComponent } from './app.component';

// Provideするオブジェクト
const OBJ: any = {
  hoge: Number.MAX_SAFE_INTEGER
};

// オブジェクトのProvide定義
export function provideValues(): Provider[] {
  return [
    {
      provide: 'HOGE',
      useValue: OBJ,
      multi: false,
    },
  ];
};


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [
    ...provideValues(),
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
// app.component.ts

import { Component, Inject } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'app';

  constructor(@Inject('HOGE') value: any) {
    this.title = '' + (value.hoge == null);
  }
}

このコードは ng serve で実行するとfalseになり、 ng serve --prod で実行するとtrueになります。

回避策

先のコードではexportしていたのは provideValues 関数だけでしたが、Provide対象のオブジェクトもexportすることでこの現象を回避することが出来ます。

// Provideするオブジェクト
export const OBJ: any = {
  hoge: Number.MAX_SAFE_INTEGER
};

// オブジェクトのProvide定義
export function provideValues(): Provider[] {
  return [
    {
      provide: 'HOGE',
      useValue: OBJ,
      multi: false,
    },
  ];
};