admin管理员组

文章数量:1406144

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":".appspot/o/property-images%2FOsDbKrOmE4wRRUMzalxG-ZkKIwuKwYua7ml8nEWOXYIV5tiK2-6214c8e0-4aec-11ed-b51b-75adb81e8353.png?alt=media\u0026token=2437767c-0877-470a-be6a-33f34c906a09","address":"312 Brooklands Road, Timperley, Manchester, UK"},{"propertyId":"NPwjd3YMPA8ddyzqBfmO","propertyAvg":3.888888888888889,"landlordAvg":4.111111111111112,"imageUrl":".appspot/o/property-images%2FNPwjd3YMPA8ddyzqBfmO-ZkKIwuKwYua7ml8nEWOXYIV5tiK2-b8072400-4c4a-11ed-9e75-f5ca509826c3.png?alt=media\u0026token=28ef7da1-711a-485a-8282-ffa1940f767d","address":"1 Wharncliffe Road, Broomhall, Sheffield, UK"},{"propertyId":"rxabfAynk5CfTIPwdRN3","propertyAvg":3.5,"landlordAvg":3,"imageUrl":".appspot/o/property-images%2FrxabfAynk5CfTIPwdRN3-ZkKIwuKwYua7ml8nEWOXYIV5tiK2-7a025420-4c24-11ed-bbda-e9dedbc50f17.jpg?alt=media\u0026token=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":"\u0026libraries=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 '../ponents';
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!

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./v0/b/student-property-1577144888882.appspot./o/property-images%2FOsDbKrOmE4wRRUMzalxG-ZkKIwuKwYua7ml8nEWOXYIV5tiK2-6214c8e0-4aec-11ed-b51b-75adb81e8353.png?alt=media\u0026token=2437767c-0877-470a-be6a-33f34c906a09","address":"312 Brooklands Road, Timperley, Manchester, UK"},{"propertyId":"NPwjd3YMPA8ddyzqBfmO","propertyAvg":3.888888888888889,"landlordAvg":4.111111111111112,"imageUrl":"https://firebasestorage.googleapis./v0/b/student-property-1577144888882.appspot./o/property-images%2FNPwjd3YMPA8ddyzqBfmO-ZkKIwuKwYua7ml8nEWOXYIV5tiK2-b8072400-4c4a-11ed-9e75-f5ca509826c3.png?alt=media\u0026token=28ef7da1-711a-485a-8282-ffa1940f767d","address":"1 Wharncliffe Road, Broomhall, Sheffield, UK"},{"propertyId":"rxabfAynk5CfTIPwdRN3","propertyAvg":3.5,"landlordAvg":3,"imageUrl":"https://firebasestorage.googleapis./v0/b/student-property-1577144888882.appspot./o/property-images%2FrxabfAynk5CfTIPwdRN3-ZkKIwuKwYua7ml8nEWOXYIV5tiK2-7a025420-4c24-11ed-bbda-e9dedbc50f17.jpg?alt=media\u0026token=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./maps/api/js?key=AIzaSyAyIxfU1kI6ODZLE80-_XXyK7tdmY3Gk50\u0026libraries=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 '../ponents';
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!

Share Improve this question edited Oct 17, 2022 at 0:36 J. Whitehead asked Oct 16, 2022 at 5:36 J. WhiteheadJ. Whitehead 5314 silver badges28 bronze badges 4
  • What does your _app looks like? You're most likely forcing client-side rendering somehow. – juliomalves Commented Oct 16, 2022 at 11:32
  • What would cause client-side rendering in _app? All that ponent does is return markup (using MUI ponents) – J. Whitehead Commented Oct 17, 2022 at 0:31
  • That's what I'm trying to understand. You must have some code that's causing it. Sharing the code for _app and the page you're rendering would help clarify it. – juliomalves Commented Oct 17, 2022 at 0:34
  • I will add it to the original post – J. Whitehead Commented Oct 17, 2022 at 0:36
Add a ment  | 

2 Answers 2

Reset to default 4

I figured this issue out. I had tried everything I thought I could, but when menting out the <AuthContextProvider/> it seemed to work pletely 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>
  );
};

Well, there are many reasons why there is no rendering HTML the most mon 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.

本文标签: