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

Nextjs 14.2 Full RSC method with two spaces - Sometimes <StoryblokComponent/> pages do not load content #1255

Open
1 task done
esilver-automox opened this issue Oct 18, 2024 · 34 comments
Assignees
Labels
investigation [Issue] The Storyblok team is investigating

Comments

@esilver-automox
Copy link

Describe the issue you're facing

I'm following the guide in the storyblok-react README for Nextjs with full react server components with one main difference - I am trying to use two storyblok spaces in the same app.

I can see that my setup is fetching the correct story data for each page but the <StoryblokComponent blok={data.story.component}/> occasionally does not return anything other than <div></div> (instead of the whole component I wrote for that story type).

This is only happening in my deployed environment with Netlify, not on my local development server, and I'm not sure why.

When the issue happens I get a page that only has my header and footer per my layout.tsx, no page contents as would be rendered with my components.

The issue is happening for random pages per build, not the same pages consistently. It changes from build to build.

Sometimes I see no errors in my server logs, sometimes I see component individual_resource_blog does not exist or component worklet-individual does not exist or similar, which should not happen because the page types complained about are in their respective component mappings.

Reproduction

https://github.com/esilver-automox/storyblok-react-test

Steps to reproduce

Deploy the code with Netlify
Navigate to /worklets and click on an item from the list (or see mine at https://issue-test.netlify.app/worklets)
Most pages show up, some do not.
Navigate to /blog and click on a blog from the list (or see mine at https://issue-test.netlify.app/blog)
Most pages show up, some do not.
View ALL pages working in local dev server (npm run dev) regardless of whether they show up or not when deployed

Bonus - deploy again and see different pages rendering/not rendering

System Info

System:
    OS: macOS 15.0.1
    CPU: (11) arm64 Apple M3 Pro
    Memory: 57.52 MB / 18.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.15.0 - ~/.nvm/versions/node/v20.15.0/bin/node
    npm: 10.7.0 - ~/.nvm/versions/node/v20.15.0/bin/npm
  Browsers:
    Chrome: 129.0.6668.101
    Safari: 18.0.1

Used Package Manager

npm

Error logs (Optional)

Screenshot 2024-10-18 at 2 42 41 PM

no error logs from my local server (everything works fine there)
no console logs from browser at time of issue

Validations

@esilver-automox esilver-automox added pending-author [Issue] Awaiting further information or action from the issue author pending-triage [Issue] Ticket is pending to be prioritised labels Oct 18, 2024
@edodusi edodusi self-assigned this Nov 4, 2024
@edodusi edodusi removed pending-author [Issue] Awaiting further information or action from the issue author pending-triage [Issue] Ticket is pending to be prioritised labels Nov 4, 2024
@edodusi
Copy link
Contributor

edodusi commented Nov 4, 2024

hi @esilver-automox, we just released version 4.0.0 with some changes for RSC, can you please use this (follow the README for some breaking changes) and get back to this issue when you have the new implementation? Thank you!

@negprof
Copy link

negprof commented Nov 4, 2024

@edodusi hey, i tried the 4.0 package, followed the Next.js 14 App Router guide, and so far im getting Component page doesn't exist. I tried to rename it to import { StoryblokServerComponent } from "@storyblok/react/rsc";. Is the guide maybe not complete?

@esilver-automox
Copy link
Author

@edodusi there's no steps for a full RSC method anymore in the README, is that correct?

@edodusi
Copy link
Contributor

edodusi commented Nov 4, 2024

@esilver-automox for RSC starting from v4 we have only this method https://github.com/storyblok/storyblok-react?tab=readme-ov-file#nextjs-using-app-router which gives you full RSC and Live Editing

So if you are following this correctly, the error you see component worklet-individual does not exist could be related to something else, I think this needs an investigation

@edodusi edodusi added the investigation [Issue] The Storyblok team is investigating label Nov 4, 2024
@edodusi
Copy link
Contributor

edodusi commented Nov 4, 2024

@negprof the imports from storyblok rsc module are correct, so probably what is not working is the imports of your own components inside your app, please understand that the code that I provided is just a demo and you can find a working implementation in the playground app in playground-next13-live-editing

@esilver-automox
Copy link
Author

esilver-automox commented Nov 4, 2024

@edodusi using the new method I am seeing component does not exist and blank page contents for every component locally (except for my worklets-main component somehow).

I just pushed to my repo, so please check it out - this does not require deployment to reproduce, just npm run dev and navigate to localhost:3000/worklets and select any item or navigate to localhost:3000/blog and see nothing but the header and footer.

You can also see the bug (empty state) in my deployed version linked in the body of this issue.

@negprof
Copy link

negprof commented Nov 5, 2024

@edodusi i made for you and Alvaro Saburido an example of my project with the same bug:
https://stackblitz.com/edit/stackblitz-starters-epynnx?file=my-app%2F.env

@edodusi
Copy link
Contributor

edodusi commented Nov 5, 2024

@negprof in your code I see that you are mixing implementations because in fetchData in app/page.js you are using a custom call.

Can you start from the playground code in this repo?

@Jeykom
Copy link

Jeykom commented Nov 6, 2024

@edodusi , i upgraded to 4.0.0 and there is no 'StoryblokComponent' on the rsc package. Only on the normal react package, which are not working with the latest example in my case.
But i make it work with the 'StoryblokServerComponent' from the rsc package. I have to use it on my Client Components too. Its a little confusing

@edodusi
Copy link
Contributor

edodusi commented Nov 6, 2024

@Jeykom you have to always use StoryblokServerComponents when you use RSC. I will make the docs more clear.

Look at the playground code for examples.

@Jeykom
Copy link

Jeykom commented Nov 6, 2024

ok, i found the problem :D
in your readme, you have the following part:

"To try this setup, take a look at the Next 13 Live Editing Playground in this repo."

this leads to:

'https://github.com/arorachakit/storyblok-react/tree/main/playground-next13-live-editing'

which is a outdated example :D

@negprof
Copy link

negprof commented Nov 6, 2024

@negprof in your code I see that you are mixing implementations because in fetchData in app/page.js you are using a custom call.

Can you start from the playground code in this repo?

Everything is working well with the example repository, but for production, I need next:revalidate: x seconds. How can I integrate this into the storyblokApi? I had to implement a custom cache validation before version 4.0 because next:revalidate wasn’t available, leading to stale cache issues, so I created a custom cv call and fetch. Any guidance on transitioning to the built-in next:revalidate would be appreciated.

fetch('https://...', { next: { revalidate: 3600 } })

@Jeykom
Copy link

Jeykom commented Nov 6, 2024

@negprof you can use 'export const revalidate = 3600' on page/layout layer

@negprof
Copy link

negprof commented Nov 6, 2024

@negprof you can use 'export const revalidate = 3600' on page/layout layer

@edodusi @Jeykom I wrote something like this, need to test it on vercel, what you think?

export async function fetchData() {
    let cacheParams;
    let preview = process.env.SB_SSR;
    let sbParams = { version: preview };

    if (preview === 'published')   {
        cacheParams = {
            cache: 'force-cache',
            next: { revalidate: 720 }
        }
    }

    if (preview === 'draft')   {
        cacheParams = {
            cache: 'no-cache',
            next: { revalidate: 0 }
        }
    }

    const storyblokApi = getStoryblokApi();
    return storyblokApi.get(`cdn/stories/home`, sbParams, cacheParams);
}

Edit:

cache: 'force-cache', is not needed when using next: { revalidate: 720 }

@edodusi
Copy link
Contributor

edodusi commented Nov 6, 2024

@negprof this is unrelated to the new release with Server Components support. The http calls and behavior are exactly the same, and your issue is related to the CDN cache, not the Next.js cache for routes. Please refer to this docs https://www.storyblok.com/tp/optimize-your-caching-strategy-with-storyblok and the API docs

@alexjoverm
Copy link
Contributor

@negprof to extra clarify - your approach looks good generally. You have the extra layer of the Next.js cache, and using the no-cache and revalidate: 0 in draft, but activating it in production is definitely a great practice 👍

We're going to work on more in-depth docs for "caching" in general, as we know it can be a bit confusing as there are multiple layers and approaches. Also @edodusi just released the v4 of this SDK with solid foundations for RSC, but rest assured that proper Docs will follow soon

@negprof
Copy link

negprof commented Nov 8, 2024

@negprof to extra clarify - your approach looks good generally. You have the extra layer of the Next.js cache, and using the no-cache and revalidate: 0 in draft, but activating it in production is definitely a great practice 👍

We're going to work on more in-depth docs for "caching" in general, as we know it can be a bit confusing as there are multiple layers and approaches. Also @edodusi just released the v4 of this SDK with solid foundations for RSC, but rest assured that proper Docs will follow soon

hey @edodusi and @alexjoverm , I refactored our project from the custom call to your provided storyblokApi way. This time everything works fine including with the next cache. We already rocking 4.0 in production. Thank you!

@brightonmike
Copy link

brightonmike commented Nov 8, 2024

I'm having the same problem as @negprof - and it is because we're using custom data fetching but removing our custom data fetching isn't an option as it would be a major rewrite.

I can't figure out why this would/should matter, as it didn't before. Is there anything I can try to debug/resolve the issue besides being forced to adopt apiPlugin?

Edit: Did a bit of digging and setComponents works correctly but when getComponent is run, componentsMap is empty.

Edit 2: Looks like my problem is related to: #952
If I import my API method into my route file, the page component works:
import { getStoryblokApi } from '~storyblok/helpers/getStoryblokApi';

It also works if I import and run it in the root layout file. But it will not work in a Provider.

@edodusi
Copy link
Contributor

edodusi commented Nov 8, 2024

@negprof I'm glad to read this! If you have any other issue please open a new one here, we will be ready to discuss and investigate!

@brightonmike I think your issue deserves a bit more investigation on our side, would you mind opening a new issue with some code snippets and steps for reproduction? We will try to figure out the best solution, if we can improve the SDK we will totally release a new version. Thank you!

@brightonmike
Copy link

brightonmike commented Nov 8, 2024

@negprof I'm glad to read this! If you have any other issue please open a new one here, we will be ready to discuss and investigate!

@brightonmike I think your issue deserves a bit more investigation on our side, would you mind opening a new issue with some code snippets and steps for reproduction? We will try to figure out the best solution, if we can improve the SDK we will totally release a new version. Thank you!

I've very quickly thrown together a crude representation here: https://codesandbox.io/p/devbox/wl76rz
If you uncomment line 74 it works, but this is strange as we're effectively needing to run the method twice.

We use GraphQL because many of our projects are complex and it's crucial to be able to only retrieve the data we need. I should add, we have a full codegen setup, the query method I've added here is just to show the issue. I'm not sure it actually matters - I think the issue is simply that if you don't use getStoryblokApi, it doesn't work.

I also can't get draft mode to work - that's possibly unrelated though.

@edodusi
Copy link
Contributor

edodusi commented Nov 11, 2024

@brightonmike I see your code, that brings to my attention another topic (highlighted also by @negprof): the need to use the SDK to bootstrap the Storyblok client and then the flexibility to call custom REST or GraphQL APIs, like you did.

I will investigate the best way to extend the JS Client to allow custom calls using the same instance, that should solve your issues. In the meantime, I think the quicker workaround is adding getStoryblokApi() before every API call (like you did in line 74 - there is a singleton so it should not duplicate instances).

I will keep you posted, for the moment thanks for reporting this.

@brightonmike
Copy link

@brightonmike I see your code, that brings to my attention another topic (highlighted also by @negprof): the need to use the SDK to bootstrap the Storyblok client and then the flexibility to call custom REST or GraphQL APIs, like you did.

I will investigate the best way to extend the JS Client to allow custom calls using the same instance, that should solve your issues. In the meantime, I think the quicker workaround is adding getStoryblokApi() before every API call (like you did in line 74 - there is a singleton so it should not duplicate instances).

I will keep you posted, for the moment thanks for reporting this.

This would be really great, thank you - look forward to an update 🙌🏻

@esilver-automox
Copy link
Author

@edodusi I am trying to follow the updated instructions in the readme for Nextjs with app router and full RSC but it seems like StoryblokBridgeLoader is no longer exported by @storyblok/react/rsc. Is there a different component that I should be using there?

@unckleg
Copy link

unckleg commented Nov 17, 2024

Any news on this one lol? How can you do release and produce this kind of regression.

@edodusi
Copy link
Contributor

edodusi commented Nov 18, 2024

Hello @esilver-automox, the link you provided is to an outdated fork of our repo, please be sure you are following the updated instructions. If you need the StoryblokBridgeLoader please tell me why you need it and what you are planning to implement, I can help you and check if we can provide that object.

@edodusi
Copy link
Contributor

edodusi commented Nov 18, 2024

Hello @unckleg, could you please clarify which regression you're referring to? We're doing our best to release new features and improve the DX. We apologize if, with new releases, there are occasionally some bugs. If you encounter one, we'd be very grateful if you could report it to us. You could help us by opening an issue and describing the problem you're facing, if you think it's related to the SDK.

Thank you.

@esilver-automox
Copy link
Author

Thank you @edodusi I am following the updated instructions now, not sure how I got to that fork. Using the updated instructions, I am seeing "Component {component name} does not exist" in my server for almost all of my page types and blank pages in my browser. I believe I am doing everything correctly per the instructions. Would you be able to look at https://github.com/esilver-automox/storyblok-react-test and tell me what I'm doing wrong?

@edodusi
Copy link
Contributor

edodusi commented Nov 18, 2024

@esilver-automox this is most likely because you are using custom fetch calls instead of the methods provided by the SDK (like .get())

Do you have any specific reason why you are using custom fetch calls?

@esilver-automox
Copy link
Author

@esilver-automox this is most likely because you are using custom fetch calls instead of the methods provided by the SDK (like .get())

Do you have any specific reason why you are using custom fetch calls?

because with two spaces in my project I was originally getting a lot of unreasonable 404s. I think the .get() method was getting confused with the two storyblok inits I had in the project.

@edodusi
Copy link
Contributor

edodusi commented Nov 19, 2024

@esilver-automox it could have been. Have you also tried with v4 and the two spaces, but using only the .get() method?

@esilver-automox
Copy link
Author

@edodusi I have tried with v4 and using only the .get() method, and for one of my spaces most pages return 404

@edodusi
Copy link
Contributor

edodusi commented Nov 20, 2024

@esilver-automox seems to me that this issue cannot be solved in our current SDK, which is designed to work with a single space. The most reliable solution would be to work with a custom approach, fetching directly from the API.

Do you have a specific reason why you need to use two spaces?

@esilver-automox
Copy link
Author

@edodusi we are using two spaces because each space has a distinct set of content editors and we didn't want that to overlap

@edodusi
Copy link
Contributor

edodusi commented Nov 21, 2024

@esilver-automox thank you, I can now understand your challenge, but I believe your case is quite uncommon. Our SDKs are designed to work with a single space, so in this scenario, I would recommend using custom roles and permissions in a single space.

Of course, you have the freedom to implement custom code to handle your case if you would like. However, I think at least for the moment, we cannot work to implement this feature in the SDK. If things change, we will surely let everybody know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
investigation [Issue] The Storyblok team is investigating
Projects
None yet
Development

No branches or pull requests

7 participants