Merhaba,


Daha önceki "Angular'da SEO - Server-side Rendering (SSR): Angular Universal'a giriş" başlıklı yazımızda Angular Universal nedir? nasıl kullanılır? canlı bir örnek ile uyguladık ve öğrendik.


Bu yazımızda ise Angular Universal kullandığımızda karşımıza çıkan bir sorunun çözümü ile ilgili.


Nedir bu sorun?

setTimeout, setInterval, localStorage, sessionStorage gibi komutlar tarayıcı tarafında çalışan komutlardır, ssr işleminde ise uygulamamız sunucu tarafında işleniyor ve bu komutlarda sunucu tarafında çalışmadığı için hataya düşüyor. Sorun tam olarak bu. Hataya düşüncede uygulamamız localhost:4000 portuna girdiğimizde projemiz açılmayabilir (sekme yükleniyor olarak kalabilir vb.) ve "xxx" is not defined şeklinde hata verir. Yani localStorage is not defined gibi.


Çözüm ise çok basit.

Sunucu tarafında çalışmayan komutları sadece tarayıcıda çalışmasını sağlayacak bir if bloğu içerisine alacağız ve sorun ortadan kalkacak.


import { isPlatformBrowser, isPlatformServer } from '@angular/common';

constructor(
  @Inject(PLATFORM_ID) private _platformId: Object
) { }

if (isPlatformBrowser(this._platformId)) {
 // Sadece tarayıcıda çalışmasını istediğimiz kodlar burada yer alacak.
 // Örn: setTimeout, setInterval, localStorage, sessionStorage vb. komutlar bu if içerisinde olacak.
}

if (isPlatformServer(this._platformId)) {
 // Sadece sunucuda çalışmasını istediğimiz kodlar burada yer alacak.
}


Şimdi önceki "Angular'da SEO - Server-side Rendering (SSR): Angular Universal'a giriş" yazımızdaki örneğimize geri dönelim ve şunu yapalım;

Projemiz açıldığında localStorage'e bir kayıt ekleyelim.


app.component.ts dosyasını açalım;

Projeyi oluşturduğumuzda app.component içerisinde varsayılan olarak constructor ve ngOnInit methodu gelmiyor ilk iş olarak hemen bunları ekleyelim ve projemizi hazırlayalım. Yani şu hale getirelim;

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

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

  constructor(
  ) { }

  ngOnInit() {
    
  }

}


Projemiz açıldığında localStorage'e bir kayıt ekleyecektik hemen bunu yapalım.

ngOnInit() {
  localStorage.setItem('token', 'xxxxxxxxxxxxxx');
}


ng serve komutuyla projemizi başlattığımızda hiçbir problem olmayacak. Universal ile projemizi başlattığımızda (npm run build:ssr && npm run serve:ssr) ise aşağıdaki gibi hata verecektir.


Evet işte bu yazıyı yazma amacımız bu hata. Şimdi bu hatayı ortadan kaldıralım.

constructor içerisinde aşağıdaki gibi tanımlamamızı yapıyoruz;

@Inject(PLATFORM_ID) private _platformId: Object

Bu işlemi yaptığımızda @angular/core içerisinden "Inject" ve "PLATFORM_ID" yi import etmemiz gerekiyor.


Şimdi gelelim sunucu tarafında çalışmasını istemediğimiz bölümü belirlemeye. Yani localStorage'e değer atadığımız kısımı şu şekilde bir if bloğu içerisine alıyoruz;

if (isPlatformBrowser(this._platformId)) {
  localStorage.setItem('token', 'xxxxxxxxxxxxxx');
}


Son olarak app.component.ts dosyamız şu şekilde oluyor;

import {Component, Inject, OnInit, PLATFORM_ID} from '@angular/core';
import {isPlatformBrowser} from '@angular/common';

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

  constructor(
    @Inject(PLATFORM_ID) private _platformId: Object
  ) { }

  ngOnInit() {
    if (isPlatformBrowser(this._platformId)) {
      localStorage.setItem('token', 'xxxxxxxxxxxxxx');
    }
  }

}



Evet şimdi tekrar build ediyoruz ve sorun ortadan kalkmış oluyor.