Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic pages with uncertain paths #1005

Closed
pablohpsilva opened this issue Mar 1, 2021 · 8 comments
Closed

Dynamic pages with uncertain paths #1005

pablohpsilva opened this issue Mar 1, 2021 · 8 comments

Comments

@pablohpsilva
Copy link

pablohpsilva commented Mar 1, 2021

Describe the bug

Currently, I have dynamic routes that should follow the pattern:

/client/[id]/edit

I honestly don't know what [id] is here. I can't predict them. Therefore, using

export const getStaticProps = async ({ locale }) => ({
  props: {
    ...(await serverSideTranslations(locale, ["common"])),
  },
});

will force me to use

export const getStaticPaths = async () => {
  return {
    paths: [], //indicates that no page needs be created at build time
    fallback: true, //indicates the type of fallback
  };
};

But I have no idea what paths can be. If I change it to something like paths: ['/client/*/edit'] or any variation to make * part a wildcard, nextjs will complain that it Error: ReactDOMServer does not yet support Suspense. (obviously).

My question is: how can I go around this issue? I honestly don't want to have SSG (this is expected by business and it is fine), but I want to use translations.

Occurs in next-i18next version

"next-i18next": "^8.0.2"

Steps to reproduce

I am considering this repository's basic setup was made (README was followed).

Create a page like:
pages/[id]/index.tsx

As a sample, use the following page component:

import {useState} from 'react'
import { useRouter } from 'next/router'

const MyPage = () => {
    const [item, setItem] = useState();
    const { query: { id } } = useRouter();

    // not really important
    const fetchItem = (id:string) => {window.fetch(`/item/${id}`).then(data => data.json()).then(item => setItem(item))}

    return item ? (
    <div>
        {item.name}
    </div>
    ) : <span>loading...</span>
}

// Here I have to use getStaticProps for the i18n to work
export const getStaticProps = async ({ locale }) => ({
  props: {
    ...(await serverSideTranslations(locale, ["common"])),
  },
});

// Because I used getStaticProps, I am forced to use getStaticPaths.
// I don't know what [id] can be. This is a dynamic value coming from BE.
export const getStaticPaths = async () => {
  return {
    paths: [], //indicates that no page needs be created at build time
    fallback: true, //indicates the type of fallback
  };
};

Now, if you run the very basic nextjs-typescript project, nextjs will complaint it can't generate the static paths, because there are none. But, also, I don't really care about the paths, since they are dynamically coming from BE.

Expected behaviour

To work without the SSG option

@TKone7
Copy link
Contributor

TKone7 commented Mar 2, 2021

I was having the exact same issue. I was also skipping the static generation by returning { paths: [], fallback: true }. This worked fine but whenever I then visit the site under /1234 I see that the props are being retrieved (1234.json is downloaded), but the content of the translation is empty:

{
	"pageProps": {
		"_nextI18Next": {
			"initialI18nStore": {
				"en": {
					"common": {},
					"footer": {}
				}
			},
			"initialLocale": "en",
			"userConfig": {

			}
		}
	},
	"__N_SSG": true
}

I already created a reproduction case based on the next-i18next sample:
https://github.com/TKone7/next-i18next/tree/master/examples/simple
It is deployed on vercel:
https://repro-dynamic-routing-c0737olgy-tkone7.vercel.app/de/1234

@pablohpsilva
Copy link
Author

Meanwhile, I moved back to next 10.0.5 and nextjs-i18next 7.0.0
@TKone7

@isaachinman
Copy link
Contributor

@TKone7 I don't see any issues with the repo you've linked at all. What you seem to be observing is the fallback page behaviour. If I add this to your [id]/index.js file:

if (isFallback) {
  return null
}

The behaviour seems a bit more acceptable. Are you aware of how fallback and fallback page replacement works? It sounds like what you're after is probably SSR, via getServerSideProps. Otherwise, you'll need to actually set up a fallback page.

@pablohpsilva Also, my suggestion is to either use fallback the way it was intended, or use SSR.

Let me know if I can help in any other way!

@TKone7
Copy link
Contributor

TKone7 commented Mar 6, 2021

Hi @isaachinman, thanks a lot for your response.

I am affraid, I think I explained myself not clearly. I adapted the repo to make it clear. Repro: https://repro-dynamic-routing-tkone7.vercel.app/blog/blog-post

When you visit the url /blog/blog-post (which is one of the declared paths) you see that the heading and buttons are translated. As soon as you visit a path that's not returned by getStaticPaths (e.g. /blog/new) the fallback is shown (since fallback: true). However, according to the vercel documentation, in the background the 'missing' page should be generated including the execution of getStaticProps. I can observe this behaviour in the browser's network tab, however the JSON returned containing the props does not contain any translations. See here:

{
	"pageProps": {
		"_nextI18Next": {
			"initialI18nStore": {
				"en": {
					"common": {},
					"footer": {}
				}
			},
			"initialLocale": "en",
			"userConfig": {

			}
		}
	},
	"__N_SSG": true
}

I did a little more analysis of the working of the function serverSideTranslations. I see that in order to generate the static props it uses the file located in localePath, which is ./public/locales per default. This folder is available during build time, however once the deployment is completed those files are no longer available, causing the re-execution of getStaticProps to return empty translations.

@isaachinman
Copy link
Contributor

@TKone7 That again sounds like the fault of whichever serverless platform you are using. You will need to ensure that your locale data remains in the filesystem.

@TKone7
Copy link
Contributor

TKone7 commented Mar 6, 2021

Thanks for that hint, @isaachinman.
Found this article that presents a solution that works for the Vercel platform. Just adapt the file next-i18next.config.js as follows:

const path = require('path')
module.exports = {
  ns: ['common', 'footer', 'second-page'],
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'de'],
  },
  localePath: path.resolve('./public/locales')
}

path.resolve(...) instructs vercel to include this directory into your function's execution environment. @pablohpsilva, check if this works for you too.

@SalahAdDin
Copy link

@TKone7 That again sounds like the fault of whichever serverless platform you are using. You will need to ensure that your locale data remains in the filesystem.

I have this problem in OsX.

1 similar comment
@SalahAdDin
Copy link

@TKone7 That again sounds like the fault of whichever serverless platform you are using. You will need to ensure that your locale data remains in the filesystem.

I have this problem in OsX.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants