AngularUniversalを利用している際に、クライアントのみもしくはサーバのみ実行する方法についてです。
どういう状況で利用するか
例えば、Windowオブジェクトを利用した処理などでよく利用します。
以下のようにalertをする処理を入れたとします。
export class PlatformComponent implements OnInit {
msg: String;
constructor() {}
ngOnInit() {
this.msg = 'platform';
alert('Hello!!')
}
}
すると、サーバサイドレンダリングをする際にwindow関数がないというエラーが発生してしまいます。
ERROR ReferenceError: alert is not defined
at PlatformComponent.ngOnInit (/app/angular-universal/dist/server/main.js:526:9)
以下省略
このような時に、今回ご紹介するような方法でクライアント側でだけ処理をするように指定します。
修正方法
component.tsファイルでの指定
まずはcomponent.tsファイルでの分岐方法です。
@angular/core
のPLATFORM_IDを利用することで、実行されている環境がクライアントかサーバかを判定することが可能です。
以下のように利用します。
import { Component, OnInit, PLATFORM_ID, Inject } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
@Component({
selector: 'app-platform',
templateUrl: './platform.component.html',
styleUrls: ['./platform.component.css']
})
export class PlatformComponent implements OnInit {
msg: String;
isBrowser: boolean;
constructor(@Inject(PLATFORM_ID) private platformId) {
this.isBrowser = isPlatformBrowser(platformId);
}
ngOnInit() {
console.log('this is ' + ((this.isBrowser)? 'Browser': 'Server'))
this.msg = 'platform';
if (this.isBrowser) {
alert('Hello!!')
}
}
}
あとは、isBrowserメンバーを用意しておいて、ブラウザ・サーバで処理をわけることが可能です。
this is Server
this is Browser
component.htmlファイルでの指定
component.htmlファイルでも出し分けをさせることが可能です。
以下のように利用します。
<ng-container *ngIf="isBrowser">
<p>{{msg}}</p>
</ng-container>
実行結果です。
ブラウザの実行結果
サーバ側の実行結果
view-source:http://localhost:4200/platform
で確認します。
(省略)
<app-root _nghost-sc0="" ng-version="8.2.13"><span _ngcontent-sc0="">This action returns all cats app is running!</span><p _ngcontent-sc0="">This is Body</p><router-outlet _ngcontent-sc0=""></router-outlet><app-platform _nghost-sc1=""><!----></app-platform></app-root>
(省略)
このように<p>platform</p>
が出力されていないことが確認できます。
以上です。