Angular Universal i praksis – Sådan bygger du SEO-venlige singlepage-apps med Angular

Der har været meget snak om Angular i de sidste par måneder, og hvordan man kan bruge den til at bygge klientapps, men en af de vigtigste nyskabelser sker faktisk på serveren.

Dette er en teknologi, der kan være med til at muliggøre en helt ny type webapplikationer: Angular Universal. Lad os finde ud af mere om den! Lad os gennemgå følgende emner:

  • Fordelene ved single page-apps
  • Hvorfor bruger vi så ikke single page-apps overalt?
  • Forstå SEO-implikationerne af en single page-app
  • Hvad er Angular Universal, og hvad muliggør det?
  • Server-side rendering er virkelig ikke bare rendering på serveren
  • En demo af en server-side renderet single page-app i aktion
  • Pre-rendering på byggetidspunktet – upload præ-renderede apps til Amazon S3
  • Den dræbende funktion i Angular Universal: Dependency Injection
  • Konklusioner

Dette indlæg er en introduktion til Angular Universal. For en mere detaljeret guide, der dækker, hvordan man bruger det i praksis, skal du kigge på dette indlæg:

Angular Universal: en komplet praktisk guide

Fordelene ved single page-applikationer

Single page-apps har eksisteret i et stykke tid, og frameworks som Angular, React eller Ember er nok de Javascript-biblioteker, der får mest opmærksomhed i Javascript-verdenen.

Fordelene ved SPA’er er egentlig kun én ting

Fordelene ved single page apps er potentielt mange:

  • når brugeren navigerer på siden, udskiftes kun dele af den, hvilket giver en mere flydende oplevelse
  • Efter den første indlæsning af siden er det kun data, der går over ledningen, når brugeren navigerer i appen: JSON leveres til browseren og anvendes på HTML-skabeloner direkte til browseren
  • Dette fører til bedre ydeevne og åbner mulighed for, at disse backend-tjenester kan bruges til andre ting, da de blot returnerer data

Vi kan koge dette ned til kun én ting:

Single Page Apps kan give en langt bedre brugeroplevelse!

Og brugeroplevelsen er afgørende i den offentlige internetverden. Der er adskillige undersøgelser, der beviser uden tvivl, at sideafbrydelsen og brugernes opgivelse af siden stiger meget hurtigt med sidens forsinkelse.

Hvis en side tager 200 ms mere tid om at indlæse, vil det have en potentiel stor indvirkning på forretning og salg (se denne undersøgelse fra Google). Dette gælder i endnu højere grad på mobile enheder, hvor apps har tendens til at være langsommere.

Hvorfor så ikke bruge SPA’er overalt?

I betragtning af disse statistikker og det faktum, at SPA’er giver en meget forbedret brugeroplevelse, hvorfor bruger alle så ikke single page apps til alt?

De har eksisteret i årevis, og ethvert websted med et navigationssystem kunne drage fordel af at blive bygget på den måde.

Forstå SEO-implikationerne af en single page-app

Der er én hovedårsag til, at single page-apps indtil videre ikke bruges overalt (med to separate årsager):

Single page-apps klarer sig ikke godt i søgemaskinerne

De to årsager til det er:

Søgemaskinen skal “gætte”, hvornår siden er komplet

Når en enkelt side hentes, vil en søgemaskine kun se meget lidt HTML. Først når MVC-rammen træder i kraft, vil siden faktisk blive gengivet fuldt ud ved hjælp af de data, der er hentet fra serveren.

Problemet er, at søgemaskinen skal gætte, hvornår Javascript-rammen er færdig med at gengive siden, så der er en risiko for at indeksere ufuldstændigt indhold.

Den anden grund til, at SPA’er ikke klarer sig godt i søgemaskinerne, er:

SPA deep links er svære at få indekseret

På grund af den manglende understøttelse af HTML5 History i browsere baserede single page apps deres navigations-URL’er i HTML bookmark anchors (URL’er med #, som /home#section1). Disse er ikke let indekseret som separate sider af søgemaskinerne, der er måder at gøre det på, men det er en smerte, og der vil altid være problemer med at få dette indekseret rigtigt i modsætning til at bruge bare almindelig HTML.

Konklusionen kunne være, at der ikke er nogen mening med at have det mest let-navigerbare websted, hvis den måde det er bygget på forhindrer fra at have god SEO.

Nu den gode nyhed

Den gode nyhed er, at ingen af disse to grunde er 100% korrekte længere! Google er begyndt at indeksere bedre single page apps.

Og den nylige deprecation af IE9 betyder, at HTML5 History er tilgængelig næsten overalt, hvilket gør brugen af anker-URL’er ikke længere nødvendig for SPA’er, vi kan bare bruge almindelige URL’er (som /home/section1).

Dette er gode nyheder, men der er andre søgemaskiner, der skaber betydelig trafik. Baidu driver f.eks. mere end halvdelen af trafikken i Kina (aktuelt 1,3 milliarder mennesker).

Der er også stadig spørgsmålet om ydeevne: En single page-app vil være langsommere på grund af de store Javascript-mængder, den har brug for, og den store opstartstid, og vil derfor præstere dårligere end en HTML-baseret løsning.

Og det betyder side drop offs, dette problem vil ikke forsvinde lige foreløbig, især ikke på mobilen. Er der en måde at få det bedste fra alle verdener på, og få både øjeblikkelig navigation, SEO-venlighed og høj ydeevne på mobilen?

Svaret er Ja, med Angular Universal.

Hvad er Angular Universal, hvad muliggør det?

Simpelt sagt gør Angular Universal det muligt for os at bygge apps, der både har de fordele ved ydeevne og brugerengagement, som apps med en enkelt side har, kombineret med SEO-venligheden fra statiske sider.

Server-side rendering er virkelig ikke bare rendering på serveren

Angular Universal har flere andre funktioner end at give en løsning til rendering af HTML på serveren. Baseret på udtrykket “server-side rendering” kunne vi tænke, at det, Angular Universal gør, ligner f.eks. et server-side skabelonsprog som Jade. Men der er meget mere funktionalitet i det.

Med Angular Universal får du den oprindelige HTML-payload renderet på serveren, men du starter også en trimmet version af Angular på klienten, og derfra overtager Angular siden som en single page app og genererer derfra al HTML på klienten i stedet for på serveren.

Så slutresultatet, du får, er det samme, det er en kørende enkeltsideapplikation, men nu, fordi du fik den oprindelige HTML-payload fra serveren, får du en meget bedre opstartstid og også en fuldt SEO-indekserbar app.

Pre-rendering på byggetidspunktet – upload præ-renderede apps til Amazon S3

En anden mulighed, som Angular Universal åbner, er præ-rendering af indhold, der ikke ændres ofte på byggetidspunktet. Dette vil være muligt ved hjælp af enten Grunt-, Gulp- eller Weppack-plugins. Sådan vil en Gulp-konfiguration se ud, der præ-renderer indholdet af vores applikation til en fil:

Og derefter skal vi blot uploade dette til en Amazon S3-spand ved hjælp af Amazon CLI:

Hvis vi linker denne spand til en Cloudfront CDN-distribution, har vi et meget overkommeligt og skalerbart websted.

Hvad sker der, hvis brugeren begynder at interagere med siden med det samme?

Der er en indledende forsinkelse mellem det øjeblik, hvor den almindelige HTML bliver gengivet og præsenteret for brugeren, og det øjeblik, hvor Angular træder ind på klientsiden og tager over som SPA.

I den tidsramme klikker brugeren måske på noget eller begynder endda at skrive i et søgefelt. Det, som Angular Universal giver mulighed for via sin preboot-funktionalitet, er at registrere de begivenheder, som brugeren udløser, og afspille dem, når Angular starter.

På den måde vil Angular kunne reagere på disse begivenheder, som f.eks. ved at vise søgeresultaterne på en Typeahead-liste.

Men hvordan ser det ud på serveren i form af kode?

Sådan renderes HTML med Angular på serveren

Måden, hvorpå indholdet renderes på serveren, er ved hjælp af express Angular Universal rendering engine expressEngine :

Der er også en Hapi-motor tilgængelig, hvis du foretrækker at bruge Hapi i stedet for Express. Der er også serverrenderingsmotorer på vej til alle mulige platforme: C#, Java, PHP, se dette tidligere indlæg for flere detaljer.

Hvordan starter man med Angular Universal?

Det bedste sted at starte er den officielle starter universal-starter, med starteren får vi en kørende applikation, som indeholder en Express-server med server side rendering, der fungerer out of the box.

Det innovative ved Angular Universal er dets enkelhed i brug. En af de vigtigste designfunktioner i Angular Universal er den måde, hvorpå den bruger afhængighedsinjektion.

Server Side Rendering Development is not like coding for the client only

De fleste gange ønsker vi, at vores applikation skal gøre nøjagtig det samme på serveren som på klienten, ved ikke at være direkte afhængig af browserens API’er.

Virkeligheden ved udvikling af server-side rendering er, at det ikke altid er muligt, og der er visse ting, som vi ønsker at gøre forskelligt på klienten og på serveren.

Tag f.eks. renderingen af et diagram: Du ønsker sandsynligvis at kalde et tredjepartsbibliotek, der bruger SVG. Vi kan ikke kalde det på serveren, så hvordan renderer vi det?

Et andet eksempel: Hvordan kan vi rendere autentificerede sider? Fordi indholdet afhænger af, hvem der er logget ind i øjeblikket.

Anvendelse af afhængighedsinjektion til at implementere autentificering

For at håndtere autentificering er dette en måde at gøre det på:

  • På klienten ønsker vi, at brugerens identitet skal tages fra et token, der er tilgængeligt enten på en cookie eller i browserens lokale lager.

  • På serveren ønsker vi, at identitetstokenet skal læses fra en HTTP-anmodningsheader, mens anmodningen gengives.

Hvordan får man samme sideoutput, mens man navigerer til den pågældende side på klienten via en routerovergang vs. på serveren via en browseropdatering?

Først definerer vi en Tjenestegrænseflade

Det første skridt er at definere en grænseflade, som din tjeneste skal levere, og som er uafhængig af køretiden:

Dernæst leverer vi to implementeringer for denne grænseflade, en til klienten og en til serveren. På serveren er der f.eks. ingen anledning til, at login-metoden bliver kaldt, så vi kaster en fejl:

Mens vi på klienten vil udløse Auth0-låseskærmen (et bibliotek, der kun findes i en tredjepartsbrowser) for at give en logon-formular:

Vi injicerer derefter forskellige implementeringer af grænsefladen på serveren og på klienten for det samme injektionstoken:

Og sådan kan vi gøre noget forskelligt på klienten og på serveren i Angular Universal ved at udnytte Angular-dependency injection-containeren.

Faktisk er Angular Universal også bygget op ved hjælp af dette begreb: For eksempel er måden, hvorpå HTML gengives, ved at i stedet for at injicere en DOM-renderer, mens rammen bootstrappes, injiceres en serverrenderer, som genererer HTML ved hjælp af parse5 HTML-serialiseringsbiblioteket.

Konklusioner

Som enhver anden teknologi vil fordelene ved server side rendering udvikle sig over tid. Men lige nu udgør server-side rendering en stor fordel for opbygning af mobilvenlige, søgemaskinevenlige applikationer, der har et højt brugerengagement på grund af sømløs øjeblikkelig navigation.

Det er nemmere end nogensinde før i dag at opbygge disse typer apps ved hjælp af Angular Universal og den universelle starter.

Med Angular Universal gør brugen af dependency injection det meget enkelt at gøre noget lidt anderledes på serveren end på klienten, hvis vi har brug for det.

Gå i gang med Angular

Hvis du vil lære mere om Angular, kan du tage et kig på kurset Angular for begyndere:

Andre indlæg om Angular

Hvis du nød dette indlæg, kan du her se nogle andre populære indlæg på vores blog:

  • Angular Router – Hvordan man opbygger en navigationsmenu med Bootstrap 4 og nested Routes
  • Angular Router – Udvidet guidet tur, Undgå almindelige faldgruber
  • Angular Components – The Fundamentals
  • Sådan kører Angular i produktion i dag
  • Sådan bygger du Angular-apps ved hjælp af Observable Data Services – Faldgruber, der skal undgås
  • Introduktion til Angular Forms – Template Driven, Model Driven eller midt imellem
  • Angular ngFor – Lær alle funktioner, herunder trackBy, hvorfor er det ikke kun for Arrays ?
  • Angular Universal i praksis – Sådan bygger du SEO-venlige Single Page Apps med Angular
  • Hvordan virker Angular Change Detection virkelig?

Leave a Reply