skip to Main Content

I have a next.js app that uses server side rendering. When running the application both locally and in production (on vercel edge), the initial page response is returning what looks like a javascript bundle, and not the fully rendered HTML page. This means that all my SEO is made redundant, as the first response does not contain any of the <meta/> tags that I have defined. The page renders correctly in the browser, but I assume web scrapers only look at the initial response from the server.

Within the network tab, the first response with the "document" initiator contains 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>
  <script src="/_next/static/chunks/webpack.js?ts=1665897162450" defer=""></script>
  <script src="/_next/static/chunks/main.js?ts=1665897162450" defer=""></script>
  <script src="/_next/static/chunks/pages/_app.js?ts=1665897162450" defer=""></script>
  <script src="/_next/static/chunks/pages/index.js?ts=1665897162450" defer=""></script>
  <script src="/_next/static/development/_buildManifest.js?ts=1665897162450" defer=""></script>
  <script src="/_next/static/development/_ssgManifest.js?ts=1665897162450" defer=""></script><noscript
    id="__next_css__DO_NOT_USE__"></noscript>
</head>

<body>
  <div id="__next"></div>
  <script src="/_next/static/chunks/react-refresh.js?ts=1665897162450"></script>
  <script id="__NEXT_DATA__"
    type="application/json">{"props":{"pageProps":{"properties":[{"propertyId":"OsDbKrOmE4wRRUMzalxG","propertyAvg":2.888888888888889,"landlordAvg":2.777777777777778,"imageUrl":"https://firebasestorage.googleapis.com/v0/b/student-property-1577144888882.appspot.com/o/property-images%2FOsDbKrOmE4wRRUMzalxG-ZkKIwuKwYua7ml8nEWOXYIV5tiK2-6214c8e0-4aec-11ed-b51b-75adb81e8353.png?alt=mediau0026token=2437767c-0877-470a-be6a-33f34c906a09","address":"312 Brooklands Road, Timperley, Manchester, UK"},{"propertyId":"NPwjd3YMPA8ddyzqBfmO","propertyAvg":3.888888888888889,"landlordAvg":4.111111111111112,"imageUrl":"https://firebasestorage.googleapis.com/v0/b/student-property-1577144888882.appspot.com/o/property-images%2FNPwjd3YMPA8ddyzqBfmO-ZkKIwuKwYua7ml8nEWOXYIV5tiK2-b8072400-4c4a-11ed-9e75-f5ca509826c3.png?alt=mediau0026token=28ef7da1-711a-485a-8282-ffa1940f767d","address":"1 Wharncliffe Road, Broomhall, Sheffield, UK"},{"propertyId":"rxabfAynk5CfTIPwdRN3","propertyAvg":3.5,"landlordAvg":3,"imageUrl":"https://firebasestorage.googleapis.com/v0/b/student-property-1577144888882.appspot.com/o/property-images%2FrxabfAynk5CfTIPwdRN3-ZkKIwuKwYua7ml8nEWOXYIV5tiK2-7a025420-4c24-11ed-bbda-e9dedbc50f17.jpg?alt=mediau0026token=1da2a00b-76d0-4371-a4e0-b0c77e995db2","address":"324 Grays Inn Road, London, UK"}]},"__N_SSP":true},"page":"/","query":{},"buildId":"development","isFallback":false,"gssp":true,"scriptLoader":[{"src":"https://maps.googleapis.com/maps/api/js?key=AIzaSyAyIxfU1kI6ODZLE80-_XXyK7tdmY3Gk50u0026libraries=places","strategy":"afterInteractive"}]}</script>
</body>

</html>

I was under the impression that next js would render full HTML pages on the server before sending them to the browser. I am not sure if there is a way to configure a "production" build option within the next.config.js file to make this happen, or whether this is a bug within next itself?

The following is my _app.js file:

import React from 'react';
import Head from 'next/head';
import { ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import theme from '../config/theme';
import { AppBar, Toolbar, Typography, Container, Box } from '@mui/material';
import { MapsHomeWork } from '@mui/icons-material';
import { Auth, RouteProtect, Link } from '../components';
import { AuthContextProvider } from '../context/authContext';



export const App = ({ Component, pageProps }) => {
  return (
    <AuthContextProvider>
      <Head>
        <meta property="og:locale" content="en_GB" />
        <meta property="og:site_name" content="Student Property Reviews" />
        <meta name="viewport" content="initial-scale=1, width=device-width" />
        <meta name="robots" content="index, follow" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <ThemeProvider theme={theme}>
        <CssBaseline />
        <Box>
          <AppBar position='static'>
            <Container maxWidth="xl">
              <Toolbar disableGutters>
                <Link href='/'>
                  <MapsHomeWork sx={{ display: { xs: 'flex', md: 'flex' }, mr: 1 }} />
                  <Typography
                    variant="h6"
                    sx={{
                      mr: 2,
                      display: { xs: 'none', sm: 'flex', md: 'flex' },
                      fontFamily: 'monospace',
                      fontWeight: 700,
                      letterSpacing: '.3rem',
                      color: 'inherit',
                      textDecoration: 'none',
                    }}
                    >
                    STUDENT PROPERTY REVIEW
                  </Typography>
                </Link>
                <Auth/>
              </Toolbar>
            </Container>
          </AppBar>
          <Container sx={{ marginBottom: '25px' }}>
            <RouteProtect>
              <Component {...pageProps} />
            </RouteProtect>
          </Container>
        </Box>
      </ThemeProvider>
    </AuthContextProvider>
  );
};

export default App;

Any help regarding this would be much appreciated!

2

Answers


  1. Chosen as BEST ANSWER

    I figured this issue out. I had tried everything I thought I could, but when commenting out the <AuthContextProvider/> it seemed to work completely fine!

    Within the auth context file, I was performing conditional rendering, depending on a loading state, which was causing SSR not to take place:

    Previously:

    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>
      );
    };
    

    Now:

    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>
      );
    };
    

  2. Well, there are many reasons why there is no rendering HTML the most common problem is there is something that is blocking the rendering, I give an example using Redux-Persist blocks totally the rendering so when you right-click on the page and click on page source you will see not HTML rendering, so you need to check what packages are blocking the rendering because not all NPM packages are very friendly with NextJS and make these behaviors.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search