Query with Apollo in SSR and Dynamic URLs (Next.js) - reactjs

I'm developing a project that uses dynamic URLS like [slug].js what I'm trying to do is: when someone access some url like domain.com/my-post my page should query for available slugs (that contains data like SEO metatags) in a graphql endpoint and load the page if the url exists in my database.
I`m using SSR, apollo hooks and etc.
My question is: on production when someone share that url on facebook or things like that the metatags on that url (domain.com/my-post) will be the empty ones (before query looks for available slugs) or after the metatags and contents was full filled? considering that when I use useQuery from apollo I need to return something in order handle loading and error from that query. I'm some point when users access that url will show a "loading" message.

My question is: on production when someone share that url on facebook
or things like that the metatags on that url (domain.com/my-post) will
be the empty ones (before query looks for available slugs) or after
the metatags and contents was full filled?
It depends on where you make the request for the slug.
If you make the request server side (ex. inside getInitialProps) pages will wait to fetch data before pre-rendering, that means that when the page will render, it will render with metatags.
If you are following the with-apollo example it should render server side obviously only if you are using your HOC in pages else if you are importing your HOC deeper in your component Tree, getInitialProps will be ignored (since it work only in pages)

Related

NextJs how am I supposed to handle 404 errors in client side fetched dynamic routes?

So I have the a dynamic route lets say it is "exercise/[id]/". When this route is accessed I take that id from the url like this:
const router = useRouter()
const id = router.query.id
Then I run a SWR fetch (client side fetching) hook to fetch some data from the server with the provided id.
If the user types an id that doesn't exist in the server or if they typed an invalid id like some letters and characters, what's the right way to handle this situation? And is there a way to redirect the user to the default next's 404 page?
What you are describing is not possible in a purely client-side rendered environment.
If you are getting data from the URL, you should be able to server-side render the page and return a 404 before the page ever gets client-side rendered.
If SSR isn't an option, you have to return an entirely different component client-side based on the SWR output. At that point you're not returning a true 404 (as far as the network status code) and would just be rendering a different component based on your API's output.
https://nextjs.org/docs/api-reference/data-fetching/get-static-props#getstaticprops-return-values
If you CANNOT server-side render, then you would have to conditionally render a different component/set of components based on the SWR output. That is entirely dependent on how your code is set up, and even that would not be a true 404 if that matters to you.

How can I enable refreshing dynamic routes in my Next.js app without using `getStaticPaths`?

In my Next.js application, I'm having the well-known problem of being able to navigate via <Link> to dynamic routes, but when I refresh that page, I get a 404 error since the page was rendered client-side. The app is serverless, so a custom server isn't an option, and the paths I need can indeed be fetched from an API, but that API requires token authentication first so I can't populate the paths I need to pre-render with getStaticPaths either. This app is dynamic, and the pages I'm trying to access through dynamic routes use a lot of Client-Side Rendering anyways, so I don't have a problem with pushing rendering over to the client. I just need to know how to do that if that's the solution, and those two solutions (custom server and getStaticPaths) are the only two I've been able to find.
EDIT: I also use next export to deploy.

Best way to paginate data with Firestore and Next.js for SEO

I use only firestore admin to access the database.
I have a function to retrieve the data from firestore. Given a collection name and option parameters (orderBy, startAt, endBefore, limit or limitToLast), it returns the resulting data in an array as well as a string with the url for the next page query and another one for the previous page. Something like this:
export interface FirestorePaginatedResponse {
data: any[],
nextParams?: FirestoreQueryOptions,
prevParams?: FirestoreQueryOptions,
}
export async function paginatedQuery(
collectionPath: string,
basePath: string,
options: FirestoreQueryOptions,
) {
[...]
return {
data,
nextParams,
prevParams,
}
}
So, considering that Static Page Rendering is not an option for Firestore pagination, what would be best for SEO A or B?
A. Do the pagination client side. One landing page with getStaticProps to load the initialData, and then use useSWR hook to retrieve and prefetch the data client side for the next pages. With useSWR probably we would save some reads to firestore due to caching and due to static generation the loading time of the first page would be faster.
B. Do the pagination with server side rendering. The landing page would have a getServerSideProps function to load the data directly given the query parameters before the page is rendered. I think that server rendering might be better for SEO, but maybe the loading of the page would be slower.
In any of those cases the query parameters are read from the url, and the pages are navigated using next/link with href to do the client transition between pages.
EDIT:
I tested 2 pages for pagination with the same content one with getServerSideProps and another one with getStaticProps. The initial loading time of the page is almost the same, so I think I'll be going with the server side rendering as xBurnsed said, for SEO it's better ssr than csr.
As far as I am concerned, the best approach for pagination when it comes to Firestore is to start at the first page, and then cycle through the results using startAfter() with the info of the doc where the last page ended. You can find more information in the following documentation.
Since pagination is meant to prevent loading all documents, I would choose to fetch the documents for each page on demand using the above described method.
Server-side rendering is considered a better option for SEO than client-side rendering. This is because server-side rendering can speed up page load times, which not only improves the user experience, but can help your site rank better in Google search results.
Server-side rendering is also better for SEO because it removes the burden of rendering JavaScript off of search engine bots, which makes it faster for them. Also, not all search engine bots are able to run JavaScript, as stated here.

Data fetching with nextjs 'catch all' routes

With nextjs 10, you can have a catch all route, which looks something like this [...id].tsx. The idea is that this will allow for dynamic pages. So it should match /example, /example/new, /example/new/latest etc.
The issue im facing is that a specific matched routes (for example /example/new) may need extra data in order to correctly render. Seeing as i only really have one file in my pages folder, i only have access to one getStaticProps call. Fetching all possible data for all possible routes seems quite wasteful.
Server side data fetching at the component level would solve his issue but this doesn't seem to be a supported feature in nextjs
Is there a recommended way around this? Conditional data fetching based on context inside getStaticProps ? 🤔
Where you should fetch data depends on the nature of your data. Also, when a user needs the data. You can use getStaticProps, getServerSideProps or fetch data on the client-side. See documentation to learn differences between the methods.

Build Next.js multi-language application with client-side routing

I'm currently working in a multi-language application with Next.js that I intend to host in an S3 bucket.
In this site, I need to maintain an application state across routes, by doing client-side routing from one route to another.
Since I need to support 40+ languages and internationalization, the process to do so is the following:
In next.config.js, use exportPathMap to generate /[language] routes with a variable inside "query" that contains that particular locale for the language.
Load this locale in getInitialProps of _app and pass it down with a Provider, to be consumed in any part of the application using the context API.
To support client-side routing, I've wrapped the next/link component in a custom Link that passes down all props and sets the "as" prop to "/[language]/[route]".
This solution works for now, but ideally, I wouldn't need to "mock" the routing with the "as" prop. I have found that dynamic routing in next does not allow client-side routing in a way to avoid refreshing the page to a new .html file that matches the dynamic path.
E.g:
Using the following directory structure:
/pages
index.tsx
/[lang]/
home.tsx
dashboard.tsx
From index.tsx, clicking on a link from next/link that redirects to /en/dashboard will trigger a request to the server and refresh the page completely. Thus, losing the client state.
Is there a better solution for this? It seems like a very common problem to solve, yet I cannot find an elegant solution using Next.js.

Resources