lifelong learner — urip iku urup, currently working on accenture.

angular universal – Solusi SEO dari SPA (best practice)

0
Degananda.com -

Haruskah menggunakan angular universal?

ABSOLUTLY!. Angular universal digunakan untuk membuat halaman dari angular atau aplikasi yang dibuat dengan angular dapat dilakukan server side rendering. Tanpa menggunakan angular unversial render akan dilakukan pada client. Lalu apakah perbedaannya? perbedannya adalah pada SEO(search engine akan melakukan index pada plain html) dan social media friendlyness. Aplikasi angular tanpa menggunakan unversial jika dipreview pada facebook tidak akan menampilkan apapun karena render dilakukan pada client.

hal ini berbeda jika mencoba melakukan preview halaman yang dirender pada sisi server. Contohnya adalah google.com.

bayangkan misalkan anda membuat blog dengan menggunakan angular namun tanpa menggunakan universal untuk proses server side rendering. bisa dibayangkan jika pengunjung blog anda menshare tulisan / post anda maka tidak akan muncul isi dari post betapa kecewannya dia(user). Oleh karena itu ulasan ini akan membahas implementasi angular universal.

Selain untuk SEO dan social media friendly angular universal juga dapat meningkatkan performa dari aplikasi, ini dikarenakan client akan mendapatkan langsung plain html dari server yang sebelum jika tanpa menggunakan unversial client harus melakukan render.Otomatis waktu yang dibutuhkan halaman untuk dapat ditampilkan ke user akan semakin singkat.

Implementasi

perlu diketahui bahwa semenjak angular versi 4 dirilis maka angular universal terletak dipackage @angular/platform-server sebagaimana telah disampaikan oleh pengembang angular di halaman github untuk angular.

1. Membuat project angular baru

langsung saja pertama kita harus menyiapkan satu project baru (agar fresh karena digunakan untuk melakukan demo). Buat project baru

ng new universaldemo

tidak perlu menambahkan opsi apapun dibelakang nama project. Selanjutnya pastikan telah masuk ke dalam project tersebut. NB. Kami menggunakan angular versi 4.3.

2. Install package platform-server dan animations

selanjutnya kita install platform-server yang berada pada angular/platform-server. Karena memang secara default platform server tidak masuk bundle (lihat gambar dibawah ini).

oleh karena itu kita perlu menginstallnya melalui npm

npm install @angular/platform-server --save

selanjutnya kita juga perlu menginstall @angular/animations karena memang angular unversal membutuhkan package animations ini. Tanpa package ini angular universal tidak dapat dijalankan atau akan mengalami error.

npm install @angular/animations --save

Done seluruh package yang kita butuhkan telah siap.

3. Implementasi server transition pada app.module.ts

Selanjutnya kita buka app.module.ts pada metada imports tepatnya di browserModule kita akan implementasikan fungsi withServerTransition() fungsinnya adalah sebagai mekanisme transisi pada saat rendering di server.

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule.withServerTransition({appId : 'unversaldemo'}),
    FormsModule,
    HttpModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})

nama dari appid adalah sesuai dengan nama project. Lihat pada package.json jika anda lupa dengan nama project yang digunakan.

4. Membuat server module

Selanjutnya pada folder /src/app buatlah file dengan nama app.server.module.ts kemudian copy dan paste kode berikut ini

import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { AppModule } from './app.module';
import { AppComponent } from './app.component';

@NgModule({
imports: [
    ServerModule,
    AppModule
],
bootstrap: [AppComponent]
})
export class AppServerModule { }

5. Membuat server(nodejs) untuk merender angular

selanjutnya buat file server.ts pada folder src. Server ts ini akan menggunakan express (kita dapat menjalankan nodejs dengan .ts/typescript file) yang akan digunakan untuk melakukan rendering pada server tuliskan copy dan paste kode dibawah ini

import 'reflect-metadata';
import 'zone.js/dist/zone-node';
import { platformServer, renderModuleFactory } from '@angular/platform-server'
import { enableProdMode } from '@angular/core'
import { AppServerModuleNgFactory } from '../dist/ngfactory/src/app/app.server.module.ngfactory'
import * as express from 'express';
import { readFileSync } from 'fs';
import { join } from 'path';

const PORT = 4000;

enableProdMode();

const app = express();

let template = readFileSync(join(__dirname, '..', 'dist', 'index.html')).toString();

app.engine('html', (_, options, callback) => {
const opts = { document: template, url: options.req.url };

renderModuleFactory(AppServerModuleNgFactory, opts)
    .then(html => callback(null, html));
});

app.set('view engine', 'html');
app.set('views', 'src')

app.get('*.*', express.static(join(__dirname, '..', 'dist')));

app.get('*', (req, res) => {
res.render('index', { req });
});

app.listen(PORT, () => {
console.log(`listening on http://localhost:${PORT}!`);
});

6. Konfigurasi angular-cli

Secara garis besar tujuan konfigurasi ini adalah untuk

  1. Melakukan exclude pada server.ts karena server.ts membutuhkan file dari dist yang mana project harus dibuild terlebih dahulu baru server.ts dieksekusi. Sehingga server.ts harus diexclude
  2. Membuat output folder /dist/ngFactory yang nantinnya akan digunakan oleh server.ts
  3. Modifikasi package.json untuk mekanisme build -> menjalankan server.ts dengan bantuan ts-node

6.1 Menambah opsi angular compiler pada ts.config.json

selanjutnya pada file ts.config.json tambahkan angularCompilerOptions

{
  "compileOnSave": false,
  "compilerOptions": {
    "outDir": "./dist/out-tsc",
    "baseUrl": "src",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2016",
      "dom"
    ]
  }, 
  "angularCompilerOptions": {
    "genDir": "./dist/ngfactory",
    "entryModule": "./src/app/app.module#AppModule"
  }  
}

selanjutnya exclude server.ts pada ts.config.app.json karena server.ts yang nantinnya akan dieksekusi dengan menggunakan ts-node(library untuk mengeksekusi ts dengan nodejs) membutuhkan beberapa file yang digenerate dari ng-build –prod. Sehingga server.ts harus diexclude

6.2 Melakukan exclude terhadap server.ts

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "outDir": "../out-tsc/app",
    "module": "es2015",
    "baseUrl": "",
    "types": []
  },
  "exclude": [
    "server.ts",
    "test.ts",
    "**/*.spec.ts"
  ]
}

6.3 modifikasi package.json untuk mekanisme compile

terahir pada package.json kita akan modifikasi script untuk memberikan perintah start dan prestart. Start akan melakukan ng build setelah itu dieksekusi(prestart) maka barulah server.ts akan dijalankan dengan menggunakan ts-node

{
  "name": "unversaldemo",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "ng": "ng",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "prestart": "ng build --prod && ngc",
    "start": "ts-node src/server.ts"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^4.3.2",
    "@angular/cli": "^1.2.6",
    "@angular/common": "^4.0.0",
    "@angular/compiler": "^4.0.0",
    "@angular/core": "^4.0.0",
    "@angular/forms": "^4.0.0",
    "@angular/http": "^4.0.0",
    "@angular/platform-browser": "^4.0.0",
    "@angular/platform-browser-dynamic": "^4.0.0",
    "@angular/platform-server": "^4.3.2",
    "@angular/router": "^4.0.0",
    "core-js": "^2.4.1",
    "rxjs": "^5.1.0",
    "zone.js": "^0.8.4"
  },
  "devDependencies": {
    "@angular/cli": "1.0.0",
    "@angular/compiler-cli": "^4.0.0",
    "@types/jasmine": "2.5.38",
    "@types/node": "~6.0.60",
    "codelyzer": "~2.0.0",
    "jasmine-core": "~2.5.2",
    "jasmine-spec-reporter": "~3.2.0",
    "karma": "~1.4.1",
    "karma-chrome-launcher": "~2.0.0",
    "karma-cli": "~1.0.1",
    "karma-coverage-istanbul-reporter": "^0.2.0",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.1.0",
    "ts-node": "^2.1.2",
    "tslint": "~4.5.0",
    "typescript": "~2.2.0"
  }
}

7. Install ts-node

setelah selesai install ts-node melalui npm dengan perintah

npm install -g ts-node

8. Percobaan

selanjutnya jalankan

npm run start

jika berhasil maka server.ts akan berjalan pada port 4000 setelah itu bukalah localhost:4000 maka akan menghasilkan “apps works” yang menarik disini adalah tidak ada rendering pada client!. biasannya jika membuka aplikasi angular akan terdapat loading diawal, ini tidak menggunakan loading sama sekali sungguh luar biasa.

dibuka pada browser

FAQ :

jika anda mengalami error berupa Module not found: Error: Can’t resolve ‘./$$_gendir/app/app.module.ngfactory’

maka solusinnya adalah update angular cli anda ke versi paling terahir (usahakan melakukan update secara global bukan locally di project tersebut). Terimakasih.

Untuk info mendalam dapat dilihat di sini. Ulasan ini merupakan penambahan penjelasan dari artikel orginal diatas.