daniel.tosaba
daniel.tosaba

Reputation: 2563

NextJS & json-server loading slow on localhost using getStaticPaths

I am building tiny e-commerce site and have setup my index page to generate static props as well as my individual product page cause we don't have many products yet. Issue I am experiencing is very slow loading on every single user click as if I missed something crucial in how data fetching works in NextJS. So here are snippets below and full project can be found on: https://github.com/danieltosaba/framer-motion

INDEX PAGE

export default function Home({ blankets }: HomeProps) {
  const classes = useStyles();
  return (
    <motion.div exit={{ opacity: 0 }} initial={{opacity: 0}} animate={{opacity: 1}}>
      <div>
        <Head>
          <title>Framer Motion Transitions</title>
        </Head>
        <main>
            <Grid container spacing={2}>
              <Grid item xs={12}>
                <h1>CHOOSE YOUR BLANKET</h1>
              </Grid>
              {blankets.map((blanket) => (
                <Grid key={blanket.id} item xs={12} sm={6} lg={4}>
                  <Card>
                    <Link href="/product/[id]" as={`/product/${blanket.id}`}>
                      <a>
                        <img
                          src={blanket.imageUrl.cover}
                          alt={blanket.name}
                          className={classes.image}
                        />
                      </a>
                    </Link>
                  </Card>
                </Grid>
              ))}
            </Grid>
        </main>
      </div>
    </motion.div>
  );
}

export const getStaticProps: GetStaticProps = async (ctx) => {
  const response = await fetch(
    "http://localhost:4001/blankets/"
  );
  const blankets = await response.json();
  return {
    props: { blankets },
  };
};

PRODUCT PAGE

type ProductDetailsProps = Blanket;

export default function ProductDetails({ name, description, imageUrl, size, price }: ProductDetailsProps) {

  let images = [];
  imageUrl.url.forEach((img) => {
    images.push({
      original: img,
      thumbnail: img,
    });
  });

  return (
    <motion.div
      exit={{ opacity: 0 }}
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
    >
        <Grid container spacing={2}>
          <Grid item xs={12} sm={6}>
            <ImageGallery items={images} />
          </Grid>
          <Grid item xs={12} sm={6}>
            <Paper elevation={0}>
              <Card>
                <CardContent>
                  <Typography variant="h4" gutterBottom>
                    {name}
                  </Typography>
                  <Typography variant="subtitle1">
                    Price: {price.small}
                  </Typography>
                  <Typography variant="body1" gutterBottom>
                    {description}
                  </Typography>
                </CardContent>
              </Card>
            </Paper>
          </Grid>
        </Grid>
    </motion.div>
  );
}

export const getStaticProps: GetStaticProps = async (context) => {
  const id = context.params.id;
  const response = await fetch(
    `http://localhost:4001/blankets/${id}`
  );
  const blanket = await response.json();

  return {
    props: blanket,
  };
};

export const getStaticPaths: GetStaticPaths = async () => {
  const response = await fetch(
    "http://localhost:4001/blankets/"
  );
  const blankets: Blanket[] = await response.json();
  const paths = blankets.map((blanket) => {
    return { params: { id: blanket.id.toString() } };
  });

  return {
    paths,
    fallback: false,
  };
};

Any help is more than welcomed!!

Upvotes: 6

Views: 4137

Answers (3)

Abdullah
Abdullah

Reputation: 2111

The following solutions solves this problem by not pre-rendering any pages during development process.

Set environment variable SKIP_BUILD_STATIC_GENERATION to true for dev environments

export async function getStaticPaths() {
  // When this is true (in preview environments) don't
  // prerender any static pages
  // (faster builds, but slower initial page load)
  if (process.env.SKIP_BUILD_STATIC_GENERATION) {
    return {
      paths: [],
      fallback: "blocking",
    };
  }

  const posts = getAllPosts();// Could be you API request

  return {
    paths: posts.map((post) => {
      return {
        params: {
          slug: post.slug,
        },
      };
    }),
    fallback: false,
  };
}

Upvotes: 0

Zakaria
Zakaria

Reputation: 440

getStaticPaths will be called every single time you request a page in development. So if you have 500 products and if you are fetching all of them in getStaticPaths, means that on every page load you will loop through all of the items and you will create paths for each one of them. Just then getStaticProps will be called and your page rendered.

In production it will be different, because it will only build at "build time" and then rigenerate the pages on request from users, depending on the interval you set for the "revalidate" option.

But the best suggestion I can give is just to limit the number of data you request in getStaticPaths while developing. Hopefully we will get a better experience soon in development

Please correct me if I said anything wrong!

Upvotes: 4

daniel.tosaba
daniel.tosaba

Reputation: 2563

After thoroughly reading documentation I found that

In development (next dev), getStaticPaths will be called on every request.

Upvotes: 8

Related Questions