0

Next.js (V15, App router, SSR) does not render HTML as initially structured.

It renders <template> tags inside the structure, and further in the source, the content in a hidden <div>.

Thus, there is no structure in the source HTML, all attempts to be semantically correct are quite vain: all you see before JS is an empty structure and then a bunch of unstructured data.

Isn't that a problem for accessibility and/or SEO?

Is it taken for granted that JS will be ran by search engines and a11y tools? Then why even bother doing SSR?

Here are two examples of what Next.js (V15, App router) renders as the initial HTML for server components.

Main content:

JSX

<body>
    <main id="main">
        {children}
    </main>
</body>

Renders:

<body>

<main id="main">
        <template id="P:1"></template><!--$--><!--/$--><!--$--><!--/$-->
</main>

<!-- ... -->
<!-- This is supposed to be #main content -->
<div hidden id="S:1">
    <div>
        <div class="cards-scroller-titles"></div>
        <div class="cards-scroller">
            <div class="card"><h1 class="card-title">À propos</h1>
                <div class="about-grid">
                    <section class="presentation">
                        <div class="">
                            <div><span><p>Je suis développeur freelance, basé sur Nantes et spécialisé en <strong>Symfony</strong>, <strong>architecture back-end</strong>, <strong>React/Next.js</strong> et <strong>intégration soignée</strong>.</p>

<!-- ... -->
</body>

Some components:

JSX:

<ul className="section-content">
    {data.parcours.map((job: string) =>
        <TimedItem item={job}/>
     )}
</ul>

Renders:

<ul class="section-content">
                    <li class="timed-item">
                        <time class="date">
                            <template id="P:14"></template>
                        </time>
                        <h4 class="title">
                            <template id="P:15"></template>
                        </h4>
                    </li>
                    <li class="timed-item">
                        <time class="date">
                            <template id="P:16"></template>
                        </time>
                        <h4 class="title">
                            <template id="P:17"></template>
                        </h4>
                    </li>
</ul>
<!-- ... -->
<div hidden id="S:14">2010+</div>
<script>$RS("S:14", "P:14")</script>
<div hidden id="S:15">Développeur / architecte web freelance</div>
<script>$RS("S:15", "P:15")</script>
<div hidden id="S:16">2010+</div>
<script>$RS("S:16", "P:16")</script>
<div hidden id="S:17">Contributions à des projets open-source (modules Symfony, plugins PhpStorm, Mastodon...)</div>
<script>$RS("S:17", "P:17")</script>
<div hidden id="S:18">2006 — 2012</div>

2 Answers 2

1

Google Search Engine will render javascript. Understand the JavaScript SEO basics

How Google processes JavaScript
Google processes JavaScript web apps in three main phases:

  1. Crawling
  2. Rendering
  3. Indexing

Googlebot queues pages for both crawling and rendering. It is not immediately obvious when a page is waiting for crawling and when it is waiting for rendering. When Googlebot fetches a URL from the crawling queue by making an HTTP request, it first checks if you allow crawling. Googlebot reads the robots.txt file. If it marks the URL as disallowed, then Googlebot skips making an HTTP request to this URL and skips the URL. Google Search won't render JavaScript from blocked files or on blocked pages.

Googlebot then parses the response for other URLs in the href attribute of HTML links and adds the URLs to the crawl queue. To prevent link discovery, use the nofollow mechanism. ...

If you think that you are having issues, then this page describes how to fix them.


I don't use Next.js, but I don't have any issues with my JavaScript generated content. Even my webapps (basically a JavaScript application) gets indexed fine.

The only things you have to be careful about are

  • Very heavy use of JavaScript
  • JavaScript based content that takes too long to render
    • Google will ware you of this.
  • Links generated by JavaScript.
    • To be sure, ensure that the links to all pages are presented either via a sitemap or a sitemap page that has them all listed as links. I do both.
  • Pages generated by JavaScript (such as in Webapps)
    • Again, you can use a robot sitemap and/or a visual sitemap to compensate.
1
  • I don’t care that much about Google, it’s more about general semantics. But considering Google: if it runs JS, why bother doing SSR? Commented Apr 26 at 8:12
0

Yeah, this is a common thing with Next.js. By default, it uses JavaScript to render stuff in the browser (client-side), so when you "view source," you’ll mostly just see a blank . That’s normal.

But the good news is: Next.js can render full HTML on the server too—using either getServerSideProps (for server-side rendering) or getStaticProps (for static site generation). Both of those give you clean, SEO-friendly HTML right out of the box.

Just make sure you’re not fetching all your data only in useEffect on the client, especially for pages that matter for SEO.

You can also check how Google sees your page using their Mobile-Friendly Test or Rich Results Test. If it looks good there, you're fine.

So yeah, it’s not really a problem with Next.js - it’s just about how you set things up.

3
  • 1
    It sounds like you are affiliated with it - if so , you are obligated to declare it. Commented Apr 26 at 7:37
  • 1/ It’s not really clear how you can have clean HTML, could you provide an example? 2/ you say « By default, it uses JavaScript to render stuff in the browser (client-side) » hmmmm are you really speaking about Next.js and SSR ? That sounds « plain React » Commented Apr 26 at 8:06
  • 3/ getServerSideProps etc doesn’t exist anymore in the app router. Commented Apr 26 at 8:19

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.