Next.js: Next.js pages with dynamic content do not server side render

Created on 15 Feb 2019  路  11Comments  路  Source: vercel/next.js

Not sure, if posting my question here is appropriate. Sorry about that in advance. I have tried to get some answers on spectrum here, but so far no luck :-(

I just started using zeit "now" for deployment, not sure if my question is coming from the lack of understanding or the limitation of the "now"

I built an app using Next.js (Typescript version) + AWS AppSync. Here is a deployed version of it. Locally, the app works as expected. The deployment process went smoothly, no errors were showed up. The issue I have is with pages that have dynamic content. Please try first to visit the home page and then a page with dynamic content. Basically, those pages with dynamic content do not server-side render.

Here is a content of some of my files:

"now.json":

{
  "version": 2,
  "builds": [
    {
      "src": "package.json",
      "use": "@now/next",
      "config": { "maxLambdaSize": "40mb" }
    }
  ],
  "routes": [
    {
      "src": "^/chitat?kniga=(?<bookCode>[^/]*)&glava=(?<chapterNumber>[^/]*)",
      "dest": "/chitat?kniga=$bookCode&glava=$chapterNumber"
    }
  ],
  "public": false
}

"next.config.js":

const withTypescript = require("@zeit/next-typescript");
const withCSS = require("@zeit/next-css");
const withSass = require("@zeit/next-sass");

const WithSass = withSass({
  target: "serverless",
});

const WithCss = withCSS(WithSass);

module.exports = withTypescript(WithCss);

"package.json":

{
  "name": "with-typescript",
  "version": "1.0.0",
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start",
    "type-check": "tsc",
    "now-build": "next build"
  },
  "dependencies": {
    "@material-ui/core": "^3.8.3",
    "@material-ui/icons": "^3.0.2",
    "@sentry/browser": "4.5.2",
    "@zeit/next-css": "^1.0.1",
    "@zeit/next-sass": "^1.0.1",
    "@zeit/next-typescript": "^1.1.1",
    "apollo-cache-inmemory": "^1.4.2",
    "apollo-client": "^2.4.8",
    "apollo-link": "^1.2.6",
    "apollo-link-state": "^0.4.2",
    "aws-amplify": "^1.1.19",
    "aws-amplify-react": "^2.3.0",
    "aws-appsync": "^1.7.0",
    "classnames": "^2.2.6",
    "graphql": "^14.0.2",
    "graphql-anywhere": "^4.1.27",
    "graphql-tag": "^2.10.0",
    "immutability-helper": "^3.0.0",
    "isomorphic-unfetch": "^3.0.0",
    "jss": "latest",
    "jump.js": "^1.0.2",
    "lint": "^1.1.2",
    "lodash.debounce": "^4.0.8",
    "lodash.groupby": "^4.6.0",
    "next": "^8.0.1",
    "next-compose-plugins": "^2.1.1",
    "react": "^16.7.0",
    "react-apollo": "^2.3.3",
    "react-dom": "^16.7.0",
    "react-jss": "^8.6.1",
    "react-swipeable-views": "^0.13.0",
    "uuid": "^3.3.2",
    "yarn": "^1.13.0"
  },
  "devDependencies": {
    "@types/graphql": "^14.0.4",
    "@types/lodash.groupby": "^4.6.4",
    "@types/next": "^7.0.2",
    "@types/react": "^16.4.16",
    "@types/react-dom": "16.0.8",
    "@types/react-tooltip": "^3.9.0",
    "eslint": "^5.12.0",
    "typescript": "3.2.1"
  },
  "license": "ISC"
}

here is how I am initializing AWSAppSyncClient to make api requests to AWS AppSync:

"withApollo.js"

import Amplify, { Auth } from "aws-amplify";
import { AUTH_TYPE } from "aws-appsync";
import Head from "next/head";
import PropTypes from "prop-types";
import React from "react";
import { getDataFromTree } from "react-apollo";
import AppSyncConfig from "../src/aws-exportsToUse";
import initApollo from "./initApollo";

if (process.env.NODE_ENV === "development") {
  Amplify.Logger.LOG_LEVEL = "INFO";
}

Amplify.configure({
  ...AppSyncConfig
});

export default App => {
  return class WithData extends React.Component {
    static displayName = `WithData(${App.displayName})`;
    static propTypes = {
      apolloState: PropTypes.object.isRequired
    };

    static async getInitialProps(ctx) {
      const {
        Component,
        router,
        ctx: { req, res }
      } = ctx;

      const apollo = initApollo(
        {},
        {
          url: AppSyncConfig.aws_appsync_graphqlEndpoint,
          region: AppSyncConfig.aws_appsync_region,
          auth: {
            type: AUTH_TYPE.AWS_IAM,
            credentials: () => Auth.currentCredentials()
          }
        }
      );

      ctx.ctx.apolloClient = apollo;

      let appProps = {};
      if (App.getInitialProps) {
        appProps = await App.getInitialProps(ctx);
      }

      if (res && res.finished) {
        // When redirecting, the response is finished.
        // No point in continuing to render
        return {};
      }

      if (!process.browser) {
        // Run all graphql queries in the component tree
        // and extract the resulting data
        try {
          // Run all GraphQL queries
          await getDataFromTree(
            <App
              {...appProps}
              Component={Component}
              router={router}
              apolloClient={apollo}
            />
          );
        } catch (error) {
          // Prevent Apollo Client GraphQL errors from crashing SSR.
          // Handle them in components via the data.error prop:
          // https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-query-data-error
          console.error("Error while running `getDataFromTree`", error);
        }

        // getDataFromTree does not call componentWillUnmount
        // head side effect therefore need to be cleared manually
        Head.rewind();
      }

      // Extract query data from the Apollo's store
      const apolloState = apollo.cache.extract();

      return {
        ...appProps,
        apolloState
      };
    }

    constructor(props) {
      super(props);

      // `getDataFromTree` renders the component first, the client is passed off as a property.
      // After that rendering is done using Next's normal rendering pipeline
      this.apolloClient = initApollo(props.apolloState, {
        url: AppSyncConfig.aws_appsync_graphqlEndpoint,
        region: AppSyncConfig.aws_appsync_region,
        auth: {
          type: AUTH_TYPE.AWS_IAM,
          credentials: () => Auth.currentCredentials()
        }
      });
    }

    render() {
      return <App {...this.props} apolloClient={this.apolloClient} />;
    }
  };
};

"initApollo.js"

import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloLink } from "apollo-link";
import { withClientState } from "apollo-link-state";
import AWSAppSyncClient, {
  createAppSyncLink,
  createLinkWithCache
} from "aws-appsync";
import fetch from "isomorphic-unfetch";

import { defaults, resolvers } from "../resolvers";

// Polyfill fetch() on the server (used by apollo-client)
if (!process.browser) {
  global.fetch = fetch;
}

let apolloClient = null;

export let innderStateLink;

export const stateLink = createLinkWithCache(cache => {
  innderStateLink = withClientState({
    cache,
    defaults,
    resolvers
  });
  return innderStateLink;
});

function create(initialState, appsyncConfig) {
  const appSyncLink = createAppSyncLink({
    ...appsyncConfig
  });

  const link = ApolloLink.from([stateLink, appSyncLink]);

  const client = new AWSAppSyncClient(
    {
      disableOffline: true
    },
    {
      ssrMode: true,
      link
    }
  );

  if (initialState) {
    client.cache.restore(initialState);
  }

  return client;
}

export default function initApollo(initialState, appsyncConfig) {
  // Make sure to create a new client for every server-side request so that data
  // isn't shared between connections (which would be bad)
  if (!process.browser) {
    return create(initialState, appsyncConfig);
  }

  // // Reuse client on the client-side
  if (!apolloClient) {
    apolloClient = create(initialState, appsyncConfig);
  }

  return apolloClient;
}

Most helpful comment

I'm having the same Issue, NextJs is not server rendering, it totally defeats the whole purpose of using Next JS

All 11 comments

Not sure what the issue is here, you've posted it correctly on spectrum.chat as per the issue template, so I'm going to close this issue.

@timneutkens, the issue is that pages with dynamic content do not server-side rendering. Please open the issue.

I'm having the same Issue, NextJs is not server rendering, it totally defeats the whole purpose of using Next JS

I have the same issue. When I click on "View page source" in the browser, dynamic data isn't prepared. Did I miss any special way to do?

I am having the same issue as of now. I am able to render a dynamic page through linking to it, but if i do a refresh and attempt to load the dynamic page directly, it does not link and I get a 404.

That sounds like you're doing something wrong in <Link> and or custom server. Did you try Next.js 9 which has dynamic routes built in.

I'm having this issue too. Why is this issue closed? Was there any possible solution to solve this problem?

Why is this issue closed?

Read the comment. https://github.com/zeit/next.js/issues/6304#issuecomment-464020002

I'm having the same Issue, NextJs is not server rendering, it totally defeats the whole purpose of using Next JS

Please create an issue with a full reproduction. Saying the equivalent of "It doesn't work for me" where "it" is not defined in a clear way makes it hard, if not impossible, to help you. We have a test suite with hundreds of tests that ensure Next.js works correctly.

Did you check API endpoint is pointing to any server, Not local host.

@sakhmedbayev did find the solution. im using awsAppsyncSDK too

@anarerdene I ended up using heroku, but it was a while ago...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

timneutkens picture timneutkens  路  3Comments

rauchg picture rauchg  路  3Comments

sospedra picture sospedra  路  3Comments

lixiaoyan picture lixiaoyan  路  3Comments

ghost picture ghost  路  3Comments