Angular Universal i praktiken – hur man bygger SEO-vänliga enkelsidiga appar med Angular

Det har talats mycket om Angular under de senaste månaderna och hur man kan använda den för att bygga klientappar, men en av dess viktigaste innovationer sker faktiskt på servern.

Det här är en teknik som kan bidra till att möjliggöra en helt ny typ av webbprogram: Angular Universal. Låt oss ta reda på mer om den! Vi går igenom följande ämnen:

  • Fördelar med enkelsidiga appar
  • Varför använder vi inte enkelsidiga appar överallt då?
  • Förstå SEO-implikationerna av en enkelsidig app
  • Vad är Angular Universal, vad möjliggör den?
  • Server-side rendering är verkligen inte bara rendering på servern
  • En demo av en server-side renderad enkelsidesapp i praktiken
  • Pre-rendering vid byggtid – ladda upp förrenderade appar till Amazon S3
  • Den dödande funktionen i Angular Universal: Den nya nyckeln i Angular Universal: Dependency Injection
  • Konklusioner

Detta inlägg är en introduktion till Angular Universal. Om du vill ha en mer detaljerad guide om hur du använder den i praktiken kan du ta en titt på det här inlägget:

Angular Universal: a Complete Practical Guide

Advantages of Single Page Applications

Single page apps har funnits ett tag, och ramverk som Angular, React eller Ember är troligen de Javascript-bibliotek som får mest uppmärksamhet i Javascript-världen.

Fördelarna med SPAs är egentligen bara en sak

Fördelarna med single page apps är potentiellt många:

  • När användaren navigerar på sidan byts bara delar av den ut, vilket ger en smidigare upplevelse
  • Efter den första laddningen av sidan är det bara data som går över tråden när användaren navigerar i appen: JSON levereras till webbläsaren och tillämpas på HTML-mallar direkt i webbläsaren
  • Detta leder till bättre prestanda och öppnar möjligheten för dessa backend-tjänster att användas till andra saker, eftersom de bara returnerar data

Vi kan koka ner detta till en enda sak:

Single Page Apps kan ge en mycket bättre användarupplevelse!

Och användarupplevelsen är kritisk i den offentliga Internetvärlden. Det finns ett stort antal studier som bevisar utan tvekan att sidförlust och användaravhopp ökar mycket snabbt med sidfördröjning.

Om en sida tar 200 ms längre tid på sig att ladda kommer detta att ha en potentiellt stor påverkan på affärer och försäljning (se den här forskningen från Google). Detta gäller i ännu högre grad på mobila enheter där appar tenderar att vara långsammare.

Varför inte använda SPA:s överallt då?

Med tanke på denna statistik och det faktum att SPA:s ger en mycket bättre användarupplevelse, varför använder inte alla single page apps för allt?

De har funnits i flera år, och alla webbplatser med ett navigationssystem kan dra nytta av att byggas på det sättet.

Förstå SEO-implikationerna av en enkelsidesapp

Det finns en viktig orsak till att enkelsidesappar hittills inte används överallt (med två separata orsaker):

Enstaka sidor fungerar inte bra i sökmotorer

De två orsakerna till detta är:

Sökmotorn måste ”gissa” när sidan är komplett

När en enskild sida hämtas kommer sökmotorn att se mycket lite HTML. Först när MVC-ramverket träder in kommer sidan faktiskt att renderas fullständigt med hjälp av de data som erhållits från servern.

Problemet är att sökmotorn måste gissa sig fram till när Javascript-ramverket är färdigt med att rendera sidan, vilket innebär att det finns en risk för att ofullständigt innehåll indexeras.

Den andra anledningen till varför SPA:s inte fungerar bra med sökmotorer är:

SPA-djuplänkar är svåra att få indexerade

På grund av bristen på stöd för HTML5-historik i webbläsare baserade appar med en enda sida sina navigerings-URL:er i HTML-bokmärkesankrar (URL:er med #, som /home#section1). Dessa indexeras inte lätt som separata sidor av sökmotorerna, det finns sätt att göra det, men det är besvärligt och det kommer alltid att vara svårt att få detta indexerat på rätt sätt jämfört med att bara använda vanlig HTML.

Slutsatsen skulle kunna vara att det inte är någon mening med att ha den mest lättnavigerade webbplatsen om sättet som den är byggd på hindrar den från att ha bra SEO.

Nu de goda nyheterna

Den goda nyheten är att ingen av dessa två anledningar är 100 % korrekt längre! Google har börjat indexera bättre appar med en enda sida.

Och den senaste avvecklingen av IE9 innebär att HTML5 History är tillgänglig nästan överallt, vilket gör att användningen av ankar-URL:er inte längre behövs för SPA:er, vi kan bara använda vanliga URL:er (som /home/section1).

Det här är goda nyheter, men det finns andra sökmotorer som ger betydande trafik. Baidu driver till exempel mer än hälften av trafiken i Kina (1,3 miljarder människor).

Det finns också fortfarande ett problem med prestanda: en app med en enda sida kommer att vara långsammare på grund av de stora Javascript-mängder den behöver och den stora starttiden, och kommer därför att prestera sämre än en HTML-baserad lösning.

Och detta innebär att sidorna tappas bort, och det här problemet kommer inte att försvinna inom den närmaste tiden, särskilt inte på mobilen. Finns det något sätt att få det bästa av alla världar och få både omedelbar navigering, SEO-vänlighet och hög prestanda på mobilen?

Svaret är Ja, med Angular Universal.

Vad är Angular Universal, vad möjliggör det?

Simpelt uttryckt gör Angular Universal det möjligt för oss att bygga appar som har både prestanda och användarengagemang som fördelar med appar med en enda sida i kombination med SEO-vänligheten hos statiska sidor.

Server-side rendering är egentligen inte bara rendering på servern

Angular Universal har flera andra funktioner än att ge en lösning för rendering av HTML på servern. Baserat på termen ”server-side rendering” skulle vi kunna tänka oss att det som Angular Universal gör liknar till exempel ett server-side template language som Jade. Men det finns mycket mer funktionalitet.

Med Angular Universal får du den initiala HTML-nyttolasten renderad på servern, men du startar också en trimmad version av Angular på klienten och därifrån tar Angular över sidan som en enkelsidesapp och genererar därifrån all HTML på klienten i stället för på servern.

Så slutresultatet är detsamma, det är en körd enkelsidesapplikation, men eftersom du har fått den ursprungliga HTML-nyttolasten från servern får du en mycket bättre starttid och en fullt SEO-indexerbar app.

Förrendering vid byggnadstillfället – ladda upp förrenderade appar till Amazon S3

En annan möjlighet som Angular Universal öppnar är förrendering av innehåll som inte ändras ofta vid byggnadstillfället. Detta kommer att vara möjligt med hjälp av antingen Grunt-, Gulp- eller Weppack-plugins. Så här kommer en Gulp-konfiguration att se ut, som förrenderar innehållet i vår applikation till en fil:

Och sedan helt enkelt ladda upp detta till en Amazon S3-hink med hjälp av Amazon CLI:

Om vi kopplar denna hink till en Cloudfront CDN-distribution har vi en mycket prisvärd och skalbar webbplats.

Hur blir det om användaren börjar interagera med sidan omedelbart?

Det finns en inledande fördröjning mellan det ögonblick då vanlig HTML återges och presenteras för användaren och det ögonblick då Angular kickar in på klientsidan och tar över som SPA.

Under den tidsramen kanske användaren klickar på något eller till och med börjar skriva i en sökruta. Det som Angular Universal tillåter via sin preboot-funktionalitet är att spela in de händelser som användaren utlöser och spela upp dem när Angular väl startar.

På så sätt kommer Angular att kunna reagera på dessa händelser, till exempel genom att visa sökresultaten i en Typeahead-lista.

Men hur ser detta ut på servern när det gäller kod?

Hur man renderar HTML med Angular på servern

Sättet som innehållet renderas på servern är genom att använda Express Angular Universal rendering engine expressEngine :

Det finns också en Hapi-motor tillgänglig om du föredrar att använda Hapi istället för Express. Det finns också serverrenderingsmotorer på gång för alla möjliga plattformar: C#, Java, PHP, se detta tidigare inlägg för mer information.

Hur börjar man med Angular Universal?

Det bästa stället att börja är den officiella startversionen universal-starter, med startversionen får vi en fungerande applikation som innehåller en Express-server med serverrendering på server-sidan som fungerar direkt.

Vad som är nyskapande med Angular Universal är att den är så enkel att använda. En av de viktigaste designfunktionerna i Angular Universal är det sätt på vilket den använder beroendeinjektion.

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

De flesta gånger vill vi att vår applikation ska göra exakt samma sak på servern som på klienten, genom att inte vara direkt beroende av webbläsarens API:er.

Verkligheten när det gäller utveckling av server-side rendering är att det inte alltid är möjligt, och det finns vissa saker som vi vill göra på olika sätt på klienten och på servern.

Ta till exempel rendering av ett diagram: du vill förmodligen anropa ett bibliotek från tredje part som använder SVG. Vi kan inte kalla det på servern, så hur ska vi rendera det?

Ett annat exempel: Hur kan vi rendera autentiserade sidor? Eftersom innehållet beror på vem som är inloggad.

Användning av beroendeinjektion för att implementera autentisering

Att hantera autentisering är ett sätt att göra det på:

  • På klienten vill vi att användarens identitet ska hämtas från en token som finns tillgänglig antingen i en cookie eller i webbläsarens lokala lagring.

  • På servern vill vi att identitets-tokenet ska läsas från en HTTP-förfrågningsrubrik när vi renderar begäran.

Hur får man samma sidutgång när man navigerar till den sidan på klienten via en routerövergång jämfört med på servern via en webbläsaruppdatering?

Först definierar vi ett Tjänstegränssnitt

Det första steget är att definiera ett gränssnitt som din tjänst kommer att tillhandahålla och som är oberoende av körtiden:

Därefter tillhandahåller vi två implementationer för detta gränssnitt, en för klienten och den andra för servern. På servern finns det till exempel inget tillfälle för inloggningsmetoden att anropas, så vi kastar ett fel:

Men på klienten kommer vi att utlösa Auth0-låsskärmen (ett bibliotek som endast finns i webbläsaren från en tredje part) för att tillhandahålla ett inloggningsformulär:

Vi injicerar sedan olika implementationer av gränssnittet på servern och på klienten, för samma injektionstoken:

Och detta är hur vi kan göra något olika på klienten och på servern i Angular Universal, genom att utnyttja Angular dependency injection container.

I själva verket byggs Angular Universal också med hjälp av detta begrepp: till exempel sättet som HTML renderas på är genom att istället för att injicera en DOM-renderare när ramverket startas upp, injiceras en serverrenderare som genererar HTML med hjälp av HTML-serialiseringsbiblioteket parse5.

Slutsatser

Likt all teknik kommer fördelarna med rendering på serversidan att utvecklas med tiden. Men just nu utgör server-side rendering en stor fördel för att bygga mobilvänliga, sökmotorvänliga applikationer som har ett högt användarengagemang på grund av den sömlöst omedelbara navigeringen.

Det är enklare än någonsin idag att bygga dessa typer av applikationer med hjälp av Angular Universal och universalstartaren.

Med Angular Universal gör användandet av injektion av beroenden det mycket enkelt att göra något något lite annorlunda på servern än på klienten om vi behöver det.

För att komma igång med Angular

Om du vill lära dig mer om Angular kan du ta en titt på kursen Angular för nybörjare:

Andra inlägg om Angular

Om du gillade det här inlägget kan du här läsa några andra populära inlägg på vår blogg:

  • Angular Router – Hur man bygger en navigeringsmeny med Bootstrap 4 och nestrade vägar
  • Angular Router – utökad guidad tur, Undvik vanliga fallgropar
  • Angular Components – The Fundamentals
  • Hur man kör Angular i produktion idag
  • Hur man bygger Angular-appar med hjälp av Observable Data Services – Fallgropar att undvika
  • Introduktion till Angular Forms – Template Driven, Modelldriven eller däremellan
  • Angular ngFor – Lär dig alla funktioner inklusive trackBy, varför är det inte bara för matriser?
  • Angular Universal i praktiken – Hur man bygger SEO-vänliga enkelsidiga appar med Angular
  • Hur fungerar Angular Change Detection egentligen?

Leave a Reply