-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Add incremental static regeneration #661
Comments
This can essentially be done now by returning cache headers and having a proxy sitting in front of the Kit app that understands those cache headers. I'm not entirely convinced this needs its own implementation solely in Kit. |
Your pages can return cache headers via the Cache invalidation is always going to be platform-specific. We've vaguely talked about adapters being able to do cache invalidation for you (i.e. |
If I understand correctly, the difference to what @Nick-Mazuk is proposing would be that one unlucky user has to wait for the server side requests to complete everytime the cache header expires. In the worst case scenario that unlucky user would experience this on every single (unique) route while navigating the website. |
I must say that I like the proposed non-solution from @Conduitry. It seems better to leave this kind of implementation to the developer, hence avoiding SvelteKit turning into yet another unconfigurable one-size-fits-all monolith, *cough* nextjs *cough* @lukasIO what you're mentioning is actually one of the worst things with the implementation in NextJS. It essentially makes an environment dependent on itself since it prerenders these pages in the build-process. |
@skrhlm I get your point that this might not be suitable in all situations, or rather it's probably only suitable in few situations, but as far as i understood, the static prerending/generation is exactly the point of this proposal. I could see the value for this proposal for less frequented sites, where the proposed cache-header solution would have a rather negligible effect if every second or third user hits the site with an expired cache header (and thus has to wait for the server side requests to complete instead of being served a static build). |
If there aren't many users then you also don't need to worry about performance very much |
That would work if you controlled the production environment. I'm deploying on Vercel, so I'm not entirely sure that would be possible. Could be wrong, though.
I'm not terribly concerned with this, though I can see how it would be important to others. I'm actually more concerned with high-traffic sites where every single user visits either an uncached page or an out-of-date page. |
@lukasIO Good point! Actually my main problem is with the implementation of it in next, not precisely the idea of it. But as @benmccann said the problem diminishes with the size of the crowd. |
@skrhlm, out of curiosity, what's your issue with the implementation of it in Next.js? |
Imho the point about performance impact for less frequented sites boils down to what you are doing in |
The thing I'm having a hard time getting my head round is what is doing the regeneration? E.g. you can't have long-lived timeouts in a serverless environment. Or are we just talking about adding a <script context="module">
export async function load({ page }) {
const props = await whatever(page.params);
return {
props,
maxage: 1,
revalidate: 59
};
}
</script> ...could translate to |
Next's docs suggest that's not what's happening in their case, but I don't yet understand how what they describe could work in an environment-agnostic way. Is this actually a Next+Vercel feature? And if so what advantages does it have over stale-while-revalidate? |
At least for the use cases that I had in mind, this doesn't sound like a bad option... For the arguments sake: In the case that edit:
Apart from the node-adapter, I have no idea how that could work. Thinking out loud: Optionally expose a server-route to trigger regeneration and leave it up to the app developer how to trigger it regularly or on demand (e.g. cronjobs, a seperate service, CMS content update hooks etc.) |
After some research, I'm guessing that incremental static regeneration (ISR) might have originally been just a Next.js on Vercel thing, but other platforms are adopting it. For instance, the original opennextjs/opennextjs-netlify#151 But in December, Netlify announce a new plugin, Announcement: https://www.netlify.com/blog/2020/12/07/announcing-one-click-install-next.js-build-plugin-on-netlify/ Repo: https://github.com/netlify/netlify-plugin-nextjs Code for ISR (potentially): https://github.com/netlify/netlify-plugin-nextjs/tree/main/src/lib/pages/getStaticPropsWithRevalidate So it seems like ISR is possible in a serverless environment outside of Vercel, but perhaps the implementation will be platform-specific… and not all platforms will support it.
@Rich-Harris With Next.js, the server is doing the regeneration. I could be wrong, but I think this is now Next.js works for static pages with this option.
I don't think this will do what I was asking for. I believe this will cache the HTML on the client, not on the server? |
Or the CDN — if HTML were suitable for caching by the server, it would be served with a |
Well, it's the lack of environment agnosticity ( is it a word !? ) that bothers me. If you're using
As a concluson I really do not see the reasoning behind even optimizing the pages in build-time. Doing it on the first request in runtime and caching the result makes a lot more sense. |
I'm an avid user of Next.js and it has always bothered me that Next.js can't share it's ISR cache between nodes in a container-like architecture. I like the idea of letting a CDN (or any reverse proxy for that matter) handle the caching and just sending the right cache headers for pages that can be cached. Maybe to avoid some confusion in @Nick-Mazuk's answer: Next.js just keeps a rendered version of the page on disk and serves it whenever a user requests the page, so it's platform independent. (I do think they use another tactic for hosting on Vercel, which uses serverless functions per page, so there the CDN might actually handle it, don't know). I do think it might be worth spending some time on this use case, because Next.js users might be looking for this when trying out SvelteKit (at least I was, hence why I ended up in this thread). Maybe an easy way to add the cache headers to a page like suggested in this comment and explaining that using a CDN in between will probably yield the same result as Next.js's ISR with the added benefit of a shared cache? |
I too am a recent migrant from Next.js and was looking for this feature. This issue thread explains it, and adding a quick way for setting the cache headers per page (i.e. a |
I commented regarding this on a different issue about editing headers, because I didn't know there was an established name for it, but in my view @Rich-Harris is correct in that cache headers probably should be enough to address this on their own, and I think would be a totally acceptable stance for svelte to take, but given the "adapter" design, and the individual strengths of the deployment platforms you are building adapters for, there are opportunities for specific improved user experiences that people are right to investigate. For cloudflare in particular, because of the very large number of edge servers in their network, if we rely on "the one unlucky user" to rebuild cache, you are actually relying on hundreds of different unlucky users, multiplied by the number of now stale pages. Or, to put it another way, a huge strength of the cloudflare workers architecture, totally separate from any potential request logic, is that all of your static assets (including html files) are replicated to their entire network, and so all requests are served directly from the edge, avoiding any interaction not just with an origin server, but also with their (region specific) cache API. This "just works" for static sites, but with svelte's load function, even with appropriate cache headers, you are breaking that perk. To me, this sounds like something that should be configurable as part of the individual adapter rather than svelte itself, as the particulars are likely to be different for different platforms. (eg cloudflare workers provides cron triggers that could be used to compare and rerender the SSR pages, but this may not be possible or the most efficient route on another platform.) |
I still have found this one here: #2369 Or is the difference that this issue is more about the "runtime-oriented" approach and #2369 is more about the "build-time-oriented" approach? What do you think? |
Is there a way to break cache of previously built files for static? Example, I build the site, deploy, visit, this caches the pages, then make a change, re-build, deploy, re-visit but don't see the change without reloading. Sorry this is slightly different issue, but can't seem to find some sort of build versioning. |
Hello, Just leaving here a possible use case with ISR : ISR with next kinda looks like a "Continuous Delivery" (update on demand) feature handled by vercel Best regards |
It is NextJS On-Demand Revalidation. It works with a hook to a Next API, no longer the NextJS has to poll or work with expiring cache headers. This is something Svelte does not have but would worth to have. |
I was looking for a use case where at build time SK would prerender the page and then every X minutes (or a webhook) SK would re-render the page in the background while still serve the static page until the re-render is done. (My renders take a good 15-30 mins - web scraping) |
I would like to add some details and update information regarding the state of ISR with current Vercel (v3) API. In v2:
The benefits compared to just playing around with
Now in v3:
So, what's the difference now between ISR and just playing around with Cache header?It's not clear if each Edge Network region keep each other updated when an ISR endpoint is updated. But let's assume not. Some benefits still remain:
I agree with that. I'm not familiar with SvelteKit bundle API yet, but having any exported const in any And if exports are not easily accessible, perhaps a mapping in the adapter configuration based on the route id or path could do it? |
Have you updated |
I'm getting the following error during build:
adapter-vercel version: 2.1.0 |
Could you please open a new issue for that with a reproduction? |
@tcc-sejohnson Yep, working for me now. |
Maybe I'm completely off, so any clarity would be appreciated. I thought with ISR, a page is pre-rendered into HTML during build (let's say the page calls an external API via the load function on export const config = {
isr: { expiration: 60, allowQuery: ['search'] },
}; |
That is exactly what I also expect to happen (but I am currently not able to achieve this behavior with the latest version of Sveltekit (1.8.4) and adapter-vercel (2.1.1). Would be great if someone from the Sveltekit dev team can bring light into the darkness and also show all possible/impossible use cases, and describe how to invalidate the ISR cache manually. |
Read through all of the posts and I think I am missing a key workflow. Back in the days I've implemented something like this in PHP:
This was, unsurprisingly, super responsive for the end user as they just get the end result. I saw some questions in this thread about what triggers the regeneration and I think the optimal way would be to trigger those on particular events on the site (comment added, post created, post edited etc.). And regenerate just the corresponding path (or even just the components?). There are of course some use cases for the incremental regeneration in an interval, but I would say for most of the cases having control over when this happens would be optimal. I have no idea how difficult would it be in the modern stack to implement, I am just learning the whole backend-in-JS thing, but if there would be a way I imagine having a function to call with a path as a argument? So after doing all the database requests, I just call Or maybe those latest changes are exactly this? I have to admit I haven't yet played with the latest changes and just gone through the documentation and this thread. |
Need this feature in our project as well. Thanks in advance! |
ISR completely works in sveltekit with vercel now, tested it and works like a charm |
Is there a way to invalidate a whole ISR cache rather than a single path? I have a use case where a user can publish large sets of changes to data that’s used throughout the public facing app using ISR. Invalidating every path where all the new data could appear would be non-trivial, and it’d be cleaner to just bust the whole cache and force a “rebuild” of their site. These changes happen infrequently, hence the strong use case for non-expiring ISR in general |
I'm also interested knowing if what @madeleineostoja wants is doable, and if this is the best approach to do it? In my case a preview-implementation from sanity is not worth the time having multiple environments etc. It's a portfolio-site that will be updated a few times / month, and while they're adding content, I'd like to invalidate the cache with a webhook each time they save, instead of rebuilding the sveltekit app over and over (with the pain of waiting for the deploy) |
The first Problem is. When you try to save with a form submit POST, the post is also cached, so your update isn´t working. So you locked in. |
I don´t think you can invalidate a path. You can just revalidate a path. So revalidation only works if the page/data behind has changed. |
I mean that's just semantics no? The pain point I'm raising is that it's not always trivial to know which URL paths to revalidate when changing data, so ideally we would need a way to set every path to revalidate on next request. If the path revalidates and no data has changed that's fine and dandy. Is this possible? Can someone from the sveltekit team weigh in as to whether this would be considered for the roadmap? Happy to go into more details on the use-case, I imagine it's not a terribly uncommon one. |
Second @madeleineostoja request. On a related but perhaps slightly different note, is it covered anywhere on revalidating "dependent" pages. Simply for testing, I've got a products route at the root, and then a /product/[id] route. The slug route is using await parent() in the load function. Unfortunately, revalidating the root route does not automatically call revalidation to the slug route. Probably intended, but manually managing any dependencies like this could become a pain point in a real-world, more complex application |
I would love to see isr for adapter-netlify as well. |
Form submit POST request should never be cached, yet it is being cached when I use vercel isr. This should be marked as a BUG. |
ISR is primarily used for blog posts, product detail pages, and similar content. A common UX in these pages is a Call to Action (CTA), such as a form where users can provide their email address to receive updates. However, if ISR cannot be disabled on POST requests, it becomes completely useless. Do you have any suggestions on how to solve this? |
I also agree vercel should not cache POST requests on ISR. |
Thanks. We can't have a non-JS fallback with this. |
So both ISR and ISR cache invalidation on demand work for Sveltekit now ? |
Where can I see more info on that?
|
I made a test repo: https://github.com/jdgamble555/isr-test https://isr-test-ten.vercel.app/ J |
ISR would also be very desirable for |
Hi, understandably it's early days but since Netlify just released Durable Caching, will we see an ISR implementation compatible with |
ISR could be feasible on Cloudflare non-Enterprise plans soon. Cloudflare just announced expansion of cache purge options for non-Enterprise plans, and intends to roll it out for all plans in early 2025 (can track it here). |
Overview
One of the best features of Next.js is incremental static regeneration. It would be great to have something similar to it.
https://nextjs.org/docs/basic-features/data-fetching#incremental-static-regeneration
The core features being:
In the ideal world, there would also be some way to invalidate the cache. vercel/next.js#16488
As I understand Sveltekit, currently, this is not possible.
Proposed solution
Extend the prerender API with a revalidate parameter.
The text was updated successfully, but these errors were encountered: