SEO för React- och Next.js-sajter: det som räknas
”React är dåligt för SEO” är en av de mest seglivade myterna inom webbutveckling. Det finns ett korn av sanning i den, men den gäller ett visst sätt att använda React — inte React i sig.
Har du en React- eller Next.js-sajt, eller funderar på en, handlar det egentligen om två frågor. Ser sökmotorn sidans innehåll utan att köra JavaScript? Och är sajten tekniskt i ordning, som vilken annan välbyggd webbplats som helst? Den första är en arkitekturfråga, den andra en checklistefråga.
Var myten kommer ifrån
En klassisk React-app (SPA, single-page application) skickar nästan tom HTML från servern: en enda <div> och en hänvisning till en skriptfil. Allt innehåll — rubriker, texter, länkar — dyker upp först när webbläsaren har laddat ner och kört JavaScript-koden.
För en besökare spelar det ingen roll — sidan ser färdig ut. För en sökrobot gör det det.
Google renderar JavaScript, men i ett separat steg. Först läses HTML-koden, och renderingen sker senare, när det finns resurser för det. Oftast går det bra. Men om ett skript kraschar, en dataförfrågan får timeout eller en fil är blockerad i robots.txt, indexerar Google det som fanns i HTML-koden — alltså ingenting.
Många andra renderar inte alls. De flesta andra sökrobotar, AI-tjänsternas botar och länkförhandsvisningar (Facebook, LinkedIn, Slack, WhatsApp) läser bara rå HTML. För dem är en klientrenderad sida tom: en delad länk saknar rubrik och bild, och en AI-sökning har inget att citera.
Problemet är alltså inte React, utan var HTML-koden byggs.
Lösningen: HTML byggs på servern eller vid byggtid
Två sätt som båda ger sökroboten färdigt innehåll direkt:
- Serverrendering (SSR) — servern sätter ihop HTML-koden för varje förfrågan.
- Statisk generering (SSG) — HTML-koden sätts ihop i förväg, vid byggtid (build), och servern skickar bara en färdig fil.
Next.js gör så som standard. I App Router är komponenterna serverkomponenter, och en sida genereras statiskt om den inte behöver förfrågningsspecifik data. Varje URL returnerar riktig HTML med innehållet på plats; JavaScript lägger bara till interaktivitet ovanpå (det kallas hydrering).
Snabbtest: finns texten i HTML-koden?
Öppna sidan, tryck Ctrl+U (Cmd+Option+U på Mac) och sök efter en mening från sidan. Inte via utvecklarverktygen — de visar sidan först efter att JavaScript har körts. Samma sak från kommandoraden:
curl -s https://din-sajt.se/tjanster/ | grep -c "en mening som syns på sidan"
Blir resultatet 0 skapas innehållet först i webbläsaren. URL-granskningen i Search Console visar dessutom vilken HTML Google fick efter renderingen.
Checklista för en React- eller Next.js-sajt
Serverrenderad HTML är en förutsättning, inte hela jobbet. Det här ska finnas på plats på varje sida.
Egen title och metabeskrivning på varje sida. Det vanligaste SPA-felet: samma rubrik på varje URL. I Next.js sätts den med metadata-exporten, eller med generateMetadata på dynamiska sidor, och den hamnar i HTML-kodens <head> redan på servern, inte senare.
Canonical. Varje sida anger vilken URL som är dess officiella adress — annars kan varianter med frågeparametrar eller avslutande snedstreck konkurrera som dubbletter av samma sida.
hreflang på en flerspråkig sajt. Varje språkversion pekar på alla andra och på x-default, och hänvisningarna måste vara ömsesidiga. Vår egen sajt har fem språk med översatta URL:er, och varje sida får sin canonical och sina hreflang-taggar från ett och samma ställe — för hand skulle det inte hålla sig korrekt på fem språk.
Genererad sitemap.xml och robots.txt. I Next.js är det filerna app/sitemap.ts och app/robots.ts. Webbplatskartan byggs av samma data som sidorna, så en ny sida kan inte glömmas bort. Vår sajt genererar sin sitemap vid byggtid.
Strukturerad data (JSON-LD). Företag, tjänster, artiklar, vanliga frågor och brödsmulor i ett <script type="application/ld+json">-block. Det måste finnas i den ursprungliga HTML-koden, inte läggas till av klienten i efterhand.
Riktiga länkar. Google följer <a href>-länkar men klickar inte på knappar. Next.js-komponenten Link renderar ett korrekt <a>-element. Navigering som bara sker via onClick och router.push() är osynlig för en sökrobot.
En riktig 404. En sida som saknas ska returnera HTTP-status 404, inte 200 med texten ”sidan hittades inte” — det senare kallar Google en mjuk 404 (soft 404). I Next.js sköter notFound() det. Vid statisk export måste webbhotellet servera 404-sidan med rätt statuskod.
En regel för avslutande snedstreck. /tjanster och /tjanster/ är två olika URL:er. Välj en (trailingSlash i Next.js), 301-omdirigera den andra och se till att interna länkar använder samma form. Ersätter en ny sajt en gammal, läs också hur du byter webbplats utan att tappa SEO.
Bilder med mått och alt-text. width och height reserverar utrymmet i förväg så att innehållet inte hoppar (CLS). next/image kräver dem ändå. Vid statisk export är Next.js automatiska bildoptimering avstängd — bilderna måste komprimeras till en rimlig storlek i förväg.
Klientkomponenter bara där det finns interaktion. 'use client' skickar en komponent till webbläsaren tillsammans med allt den importerar. En meny, ett formulär och ett filter behöver det; ett textblock och sidfoten gör det inte.
Hastighet: fällor som är typiska för React
Helhetsbilden av Core Web Vitals finns i artikeln webbplatsens hastighet: så mäter och förbättrar du den. En React-sajt har dessutom tre egna fällor.
JavaScript-mängd och hydrering
Även en serverrenderad sida laddar ner JavaScript och hydrerar sig. Tills det är klart reagerar inte knapparna — det försämrar INP, särskilt på billigare telefoner. Varje klientkomponent och varje bibliotek (karusell, animationsbibliotek, datumbibliotek) gör paketet större. En tung widget längst ner på sidan är värd att ladda först när den behövs (next/dynamic).
Göm inte rubriken bakom JavaScript
Ett vanligt mönster: innehållet ”tonar in”, och därför börjar det på opacity: 0 tills ett skript ger klartecken. Görs det med sidans huvudrubrik väntar LCP — Googles viktigaste mått på laddningshastighet — på att JavaScript-koden laddas ner och hydreras. Laddas skriptet inte alls förblir rubriken osynlig.
Det lärde vi oss på vår egen sajt. Startsidans rubrik är LCP-elementet och använder nu en ren CSS-animation som startar från första målningen, i stället för en JavaScript-styrd intoning. Scrolleffekter längre ner på sidan är en annan sak — rubriken är inte beroende av dem.
Skicka inte alla språk till webbläsaren
På en flerspråkig sajt är det lätt att av misstag importera hela översättningsordlistan i en klientkomponent. Då laddar varje besökare ner texterna på alla språk. Bättre mönster: en serverkomponent läser texten och skickar bara de strängar klientkomponenten behöver, som props.
Statisk export: varje sida är en färdig fil
Next.js kan exportera hela sajten som ren HTML (output: 'export'). Resultatet är en mapp med filer som vilken webbserver eller CDN som helst kan servera.
- Snabbt — servern räknar inte ut något vid besöket.
- Säkert — det finns ingen databas, ingen adminpanel och ingen serverkod att angripa.
- Billigt att drifta — ett vanligt statiskt webbhotell räcker.
Vår egen sajt är en helt statisk export: Next.js (App Router), React och TypeScript, fem språk.
Priset för det: varje innehållsändring innebär ett nytt bygge och en ny uppladdning. För en företagssajt och en blogg som ändras en gång i veckan passar det bra. Ändras innehållet varje minut, har användarna konton eller behövs sökning mot en databas, behöver du serverrendering eller en separat tjänst. Även ett kontaktformulär behöver en liten serverdel som tar emot det.
Sitter du på WordPress i dag och funderar på att byta, läs byta från WordPress utan att förlora din SEO och den bredare jämförelsen WordPress eller en kodbaserad webbplats.
När du ska ta hjälp
Har du redan en React-sajt, gör tre kontroller: titta på källkoden för tre sidor, jämför antalet indexerade sidor i Search Console med det faktiska antalet sidor och se om rubrikerna skiljer sig mellan sidorna. Saknas texten i HTML-koden hjälper det inte att justera metataggar — renderingen måste göras om, ofta genom att gå från SPA till Next.js.
Vi bygger webbplatser med Next.js så att allt ovan finns med från början. Finns sajten redan men rör sig inte i Google, börja med sökmotoroptimering.
