vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.83k stars 26.96k forks source link

Issue with Static generation and ISR #29546

Closed vitthalzephyr closed 3 years ago

vitthalzephyr commented 3 years ago

What version of Next.js are you using?

11.0.0

What version of Node.js are you using?

14.16.1

What browser are you using?

Microsoft Edge

What operating system are you using?

Windows

How are you deploying your application?

next start

Describe the Bug

I am observing inconsistent behavior with static generation and ISR (getStaticPaths & getStaticProps). My requirement is pull a list of reports available from the database for a certain Type and Category. For the example code given below, the code runs perfectly on my local machine (Node Version 14.16.1 on Windows). However on AWS server (Node Version 14.18.0 Ubuntu Linux), the build script only picks up 3-4 static paths and then while running, it says failed to getStaticProps - which possibly should be some exception that I am not getting on my local machine somehow. I also tried to run the database access code separately on my AWS server however it resulted the correct output.

Expected Behavior

The code should reflect same behavior whether Ubuntu or Windows. Also the fallback: true from getStaticPaths doesn't seems to be working. On Ubuntu, setting fallback: true results in getStaticProps error and fallback:false results in 404 error. I tried getStaticPaths both ways - pulling those from Db (as commented code) and hardcoding. But no difference.

To Reproduce

export async function getStaticPaths() { /* const reportMaster = await daos.getReportMaster(); const categories = await reportMaster.getAllCategories(); const paths = await categories.map((data) => ({ params: { category: encodeURI(${data.category}), reportType:${data.reportType}` }, })); return { paths, fallback: true } */ return { paths: [{ params: { category: 'Fixed Income And Currency Market', reportType: 'Research' }, params: { category: 'Credit Market', reportType: 'Research' }, params: { category: 'Credit Research', reportType: 'Research' }, params: { category: 'RBI Policy', reportType: 'Research' }, params: { category: 'Equity Market', reportType: 'Research' }, params: { category: 'Union Budget', reportType: 'Research' }, params: { category: 'Blogs', reportType: 'Knowledge' }, params: { category: 'Support', reportType: 'Knowledge' }, params: { category: 'Liquidity Cheat Sheet', reportType: 'MarketData' }, params: { category: 'Primary Corporate Bond Market', reportType: 'MarketData' }, params: { category: 'Corporate Bond and Money Market Traded Data', reportType: 'MarketData' }, params: { category: 'RBI Operations', reportType: 'MarketData' }, params: { category: 'Deposit and Credit Data', reportType: 'MarketData' }, params: { category: 'Forex Data', reportType: 'MarketData' }, params: { category: 'FII investment', reportType: 'MarketData' }, }], fallback: true }; }

export async function getStaticProps(context) { const reportMaster = await daos.getReportMaster() let articles = await reportMaster.getArticleDataByCategory(context.params.category); if(!articles) return {notFound: true, };

return {props: {articles: JSON.stringify(articles), reportType: context.params.reportType, category: context.params.category}, revalidate: 3600};

} `

balazsorban44 commented 3 years ago

The code you pasted in is broken. Is it just bad formatting, or could be the reason for failing?

You have a single object in the paths array, and that object has multiple params keys. Only one of those params will actually be used at the end.

const paths = [{params: "foo", params: "bar"}]
console.log(paths) // [{params: "bar"}]

You will need to rewrite your logic to produce something likes this:

const paths = [{params: "foo"}, {params: "bar"}]

fallback: false generating 404 in your case is intended, especially considering the above-mentioned formatting problem. With that option, you tell Next.js that any page not generated build time should be marked as not available/found.

Would be interesting to see the error you are mentioning, when you set fallback: true. Could be many reasons. Could you paste it in?

vitthalzephyr commented 3 years ago

Thanks for pointing that out. I have corrected the typo and it works fine. But I still have two questions:

  1. When I set fallback: true, it still works on my local windows machine. But on my Linux server, it results simply saying 'failed to getStaticProps()'. No more error info. I tried doing some try/catch OR console logs in getStaticProps, but it offers no more clue on the error.
  2. I then removed the hardcoded params and used reportMaster.getAllCategories() from my commented code above. Now the output is same (but some undefined reportType values). It still doesn't work and gives me the same error of failed to getStaticProps(). Below is the code from getStaticPaths:
    
    const reportMaster = await daos.getReportMaster();
    const categories = await reportMaster.getAllCategories();
    const paths = await categories.map((data) => ({
        params: { category: encodeURI(`${data._id.category}`), reportType: `${data._id.reportType}` },
    }));
    console.log(paths);
    return { paths, fallback: true }

And the paths are logged to console as :

[ { params: { category: 'Liquidity%20Cheat%20Sheet', reportType: 'MarketData' } }, { params: { category: 'Fixed%20Income%20And%20Currency%20Market', reportType: 'Research' } }, { params: { category: 'Deposit%20and%20Credit%20Data', reportType: 'MarketData' } }, { params: { category: 'Corporate%20Bond%20and%20Money%20Market%20Traded%20Data', reportType: 'MarketData' } }, { params: { category: 'RBI%20Operations', reportType: 'MarketData' } }, { params: { category: 'Credit%20Research', reportType: 'Research' } }, { params: { category: 'Union%20Budget', reportType: 'Research' } }, { params: { category: 'Primary%20Corporate%20Bond%20Market', reportType: 'MarketData' } }, { params: { category: 'Blogs', reportType: 'Knowledge' } }, { params: { category: 'Forex%20Data', reportType: 'MarketData' } }, { params: { category: 'Support', reportType: 'Knowledge' } }, { params: { category: 'FII%20investment', reportType: 'MarketData' } }, { params: { category: 'Credit%20Market', reportType: 'Research' } }, { params: { category: 'Equity%20Market', reportType: 'Research' } }, { params: { category: 'Market%20Gauge', reportType: 'Market Gauge' } }, { params: { category: 'Equity%20Market', reportType: 'undefined' } }, { params: { category: 'RBI%20Policy', reportType: 'Research' } }, { params: { category: 'Bond%20Tracker', reportType: 'undefined' } } ]

balazsorban44 commented 3 years ago

what's your url structure for these pages?

Assuming that it is in its simplest form, you have something like this: /[category]/[reportType],

by using "%20", is your intention really to create a page under this url?:

/Liquidity Cheat Sheet/MarketData

I also don't think undefined will work as a value for a param. 🤔 (update, I see you set it as a string, but that would produce a url /undefined which I'm not sure was your intention)

make sure you give a good read to https://nextjs.org/docs/basic-features/data-fetching#the-paths-key-required

vitthalzephyr commented 3 years ago

what's your url structure for these pages?

IT IS /[reportType]/[category]. Assuming that it is in its simplest form, you have something like this: /[category]/[reportType],

by using "%20", is your intention really to create a page under this url?:

/Liquidity Cheat Sheet/MarketData YES

I also don't think undefined will work as a value for a param. 🤔 (update, I see you set it as a string, but that would produce a url /undefined which I'm not sure was your intention)

I AGREE. BUT I WOULD EXPECT /undefined TO GENERATE ERROR, AND NOT OTHERWISE make sure you give a good read to https://nextjs.org/docs/basic-features/data-fetching#the-paths-key-required HAVE GONE THROUGH THIS AND DIDN'T FIND ANYTHING WRONG WITH WHAT I AM DOING

balazsorban44 commented 3 years ago

~I'll try to reproduce it locally. (I work from Linux). I cannot test with AWS, but I can try the hardcoded values.~

I, unfortunately, could not reproduce this with the code you provided. :confused: Do you have a repository maybe?

vitthalzephyr commented 3 years ago

~I'll try to reproduce it locally. (I work from Linux). I cannot test with AWS, but I can try the hardcoded values.~

I, unfortunately, could not reproduce this with the code you provided. 😕 Do you have a repository maybe?

Problem is even I cannot reproduce it on my local machine. It gives no problem with hardcoded values. Issue is only if I pull from database. Let me come back if I can create a small repo to reproduce.

vitthalzephyr commented 3 years ago

I tried creating a small repo, however it was just not getting reproduced there - can't guess what is the reason. Basically two problems still remain:

  1. Can't do getStaticPaths from database - evenif I remove all 'undefined'
  2. The fallback=true just doesn't help. Any other path given - valid or invalid, it results into an error 'failed to getStaticProps'

Anyways then as a part of my application, I had a requirement to change this whole thing to getServerSideProps, because I was expecting the same code to support some dynamic query parameters. So this issue is no more.

It would actually be a nice feature in Next.js to have some paths statically rendered while some dynamic - using the same piece of code.

balazsorban44 commented 2 years ago

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.