The lack of HTML pre-rendering in a Next.js app with SSR means that the content is not accessible to web-scrapers

I'm encountering an issue with my next.js app that utilizes server side rendering. Upon running the application locally and in production (on vercel edge), the initial page response seems to be a javascript bundle rather than the fully rendered HTML page. As a result, all the SEO efforts I've put in, such as defining <meta/> tags, are essentially useless, since the first response lacks these tags. While the page loads correctly in the browser, it appears that web scrapers only consider the initial server response.

When inspecting the network tab, the first response with the "document" initiator reveals the following:

<!DOCTYPE html>
<html>

<head>
  <style data-next-hide-fouc="true">
    body {
      display: none
    }
  </style><noscript data-next-hide-fouc="true">
    <style>
      body {
        display: block
      }
    </style>
  </noscript>
  <meta charSet="utf-8" />
  <meta name="viewport" content="width=device-width" />
  <meta name="next-head-count" content="2" /><noscript data-n-css=""></noscript>
  <script defer="" nomodule="" src="/_next/static/chunks/polyfills.js?ts=1665897162450"></script>
  ... (truncated for brevity)
</html>

I initially believed that next.js would generate full HTML pages on the server before sending them to the browser. I'm uncertain whether configuring a "production" build option within the next.config.js file could resolve this, or if it's a bug within next.js itself.

Below is an excerpt from my _app.js file:

import React from 'react';
... (code continues, truncated for brevity)

I would greatly appreciate any assistance or insights on this matter!

Answer №1

I managed to resolve this issue by making a crucial discovery. Despite trying various solutions, the breakthrough came when I decided to comment out the <AuthContextProvider/>, and surprisingly, everything started working smoothly!

It turns out that the problem originated from the auth context file, where I was implementing conditional rendering based on a loading state. This was hindering SSR from functioning correctly:

Here is the code snippet before and after the modification:

const AuthContext = createContext({});

export const useAuth = () => useContext(AuthContext);

export const AuthContextProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  const provider = new GoogleAuthProvider();

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      setUser(user ? user : null);
      setLoading(false);
    });
    return () => unsubscribe();
  }, []);

  const login = () => {
    return signInWithRedirect(auth, provider);
  };

  const logout = async () => {
    setUser(null);
    await signOut(auth);
  };

  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {!loading && children}
    </AuthContext.Provider>
  );
};

After the modification:

const AuthContext = createContext({});

export const useAuth = () => useContext(AuthContext);

export const AuthContextProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const provider = new GoogleAuthProvider();

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      setUser(user ? user : null);
    });
    return () => unsubscribe();
  }, []);

  const login = () => {
    return signInWithRedirect(auth, provider);
  };

  const logout = async () => {
    setUser(null);
    await signOut(auth);
  };

  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
};

Answer №2

There are multiple reasons why HTML rendering may not be happening, with one common issue being that something is blocking the process. For example, using Redux-Persist can completely block rendering. When you try to view the page source after right-clicking on the page, you may notice that no HTML is being rendered. It is important to identify which packages are causing this obstruction, as not all NPM packages are compatible with NextJS and may exhibit these behaviors.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Steps for organizing a list based on the number of clicks

I've created an HTML list with images of political party logos. Each logo is a grid item that can be clicked on. I want to sort the list based on the number of clicks each logo receives, essentially ranking them by popularity. However, I'm not su ...

What is the best way to customize column width in AG-Grid?

I am looking for a way to dynamically set column width in my table. I have provided a stackblitz example which demonstrates that when changing the screen size, only the table border adjusts, but not the column widths. Is there a way to also change the col ...

Tips for triggering a function when the range slider is adjusted

I'm looking to trigger a function whenever a user changes a range slider in my Vue.js project, and I also need to pass the new value to that function. The code snippet below shows what I have so far. <div cla ...

JavaScript Build Failure: Linting Error Detected - no-constant-condition

I am encountering an error labeled as Unexpected constant condition no-constant-condition when attempting to compile this code. (The error is on a line indicated with >>>) This code operates based on user input. The variables commandVariable0 and ...

Troubleshooting handlebars path problem in Express.JS

https://i.sstatic.net/qEB42.jpg I have my node's logic stored in the "app" folder, where the views folder resides with templates for handlebars (express-handlebars). Inside the "config" folder, there's an express.js file where I require the exp ...

Technique for updating URL when submitting a form on a webpage

I'm a newcomer to the world of coding and I have a simple issue that needs fixing. I want to create a form field where users can input the last segment of a URL provided to them. After entering this segment, I want the page to refresh automatically a ...

Displaying values dynamically as they transition between states in Reactjs

There are four components that I'm working with - UserHome, SearchFlight, Events, and Alerts. The UserHome component is where I import all the other components: <SearchFlight/> <Events /> <Alerts /> Within the SearchFlight compone ...

Is it possible to delete a route if the .remove function is not available?

Hey there, I'm having an issue with a route I created to delete a product. Every time I try to run it, I'm getting an error message that says .remove is not a function. I've been searching for a solution but haven't been able to fix it. ...

Guide to accessing a server file directly from the client's web browser

Hey Team, I have a requirement for the browser to read a property file from the server. To achieve this, I am using JQuery/AJAX as shown below. <script> var properties = null; $(document).ready(function(){ $.ajax({url:"demo_test.txt",success:fun ...

Button click not functioning to switch the displayed image in Javascript

As a beginner in Javascript, I'm attempting to create a basic button in html that switches the originally shown image when clicked. Unfortunately, my current code isn't functioning properly. Could someone please assist me in identifying the mista ...

Why is my IEDriverServer typing so slow? Seeking JavaScript solutions

While working with Selenium and IEDriverServer, I have encountered an issue where the keys are being sent to the input at a very slow pace. After conducting some research, many websites recommend ensuring that the Browser and IEDriverServer are of the sam ...

When navigating back, the Bootstrap Multistep Form breaks down

Tools I'm currently utilizing: HTML, CSS, Javascript, Bootstrap 3 Library / Package in use: https://codepen.io/designify-me/pen/qrJWpG Hello there! I am attempting to customize a Codepen-based Bootstrap Multistep Form from the provided link abov ...

What is the best way to retrieve data from the server for individual div elements?

Utilizing Laravel and JQuery to render the HTML is my current approach. <div id="div1">0</div> <div id="div2">0</div> <div id="div3">0</div> Each instance of 0 within the divs needs to be s ...

In a set of strings, locate the two shortest ones, remove them, and then add them back to the end repeatedly until there is only one string

I've been struggling with a coding challenge for a couple of hours now and could really use some help. Here are the detailed instructions: Take an array of strings and create a single string by following these steps: Repeat the following steps as lo ...

What is the best way to implement or disable a function when toggling a switch in pure JavaScript?

I'm currently facing an issue with my transliteration function that is supposed to be executed only when the checkbox is checked. The problem is, even after unchecking the checkbox, the function still continues to run. const checkBox = document.que ...

Having trouble with executing functions on an express js Route?

I'm currently exploring Node and Express, and I'm encountering an issue when trying to pass a function instead of plain text on my route. It seems that the documentation only mentions using res.send() method with text. Even when attempting to use ...

Embracing the power of dynamic imports in Next.js 10 with SDK integration for

I attempted to dynamically import the TRTC SDK using Next.js 10: const TRTC = dynamic(() => import('trtc-js-sdk').then((module) => module.NamedExport), { ssr: false }); However, I encountered an error stating "TRTC.createClient is not a co ...

What is the method used by three.js to render video with spherical UV mapping?

I have a streaming video displayed in a 3*3 format. I am able to splice the entire video into individual sections using THREE, // Creating a 3x3 PlaneGeometry var geometry = new THREE.PlaneGeometry(400, 200, 3, 3); const video1 = document.getElem ...

Generate a dynamic key object in Angular/TypeScript

I am working with an object called "config" and an id named "id". My goal is to create an array of objects structured like this: [ "id" : { "config1: ... "config2: ... "config3: ... } "id2" : { "config ...

How to load MTL files from local storage using Three.js in Chrome

I'm encountering an issue when attempting to load MTL files using Three.js on Chrome. While everything runs smoothly on Safari, I keep running into a cross-origin request error in Chrome when working with local files. I'm at a loss on how to reso ...