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

Mark endpoints as prerenderable #4093

Closed
Rich-Harris opened this issue Feb 23, 2022 · 11 comments
Closed

Mark endpoints as prerenderable #4093

Rich-Harris opened this issue Feb 23, 2022 · 11 comments
Labels
breaking change feature / enhancement New feature or request size:large significant feature with tricky design questions and multi-day implementation
Milestone

Comments

@Rich-Harris
Copy link
Member

Describe the problem

If an endpoint loads data from the filesystem...

import fs from 'fs';
import marked from 'marked';

export function get({ params }) {
  const markdown = fs.readFileSync(`content/${params.slug}.md`, 'utf-8');

  return {
    body: marked(markdown)
  };
}

...then in most environments it will won't work in production — it's only suitable for prerendering. SvelteKit doesn't know that, and will include the endpoint in the built app. This is bad for two reasons:

  • it means deploying unnecessary code
  • a mistyped URL will 500 instead of 404

We're experiencing this right now with https://kit.svelte.dev/docs/nope.

Describe the proposed solution

If we could mark the endpoint with export const prerender = true, just like we do with pages, we could avoid including the endpoint in the deployed app.

The semantics are slightly different to export const prerender = true in pages, where it means 'you can prerender this page' as opposed to 'you can ONLY prerender this endpoint', but I think that's probably fine.

Alternatives considered

No response

Importance

would make my life easier

Additional Information

No response

@Conduitry
Copy link
Member

Would this mark all defined HTTP methods for that endpoint as needing to be prerendered? Do we need more granularity than that?

@Rich-Harris
Copy link
Member Author

On most platforms, it goes to the filesystem first — if there's a foo.json then it will either respond with that when you POST /foo.json or it will 405. So I think we have to treat the existence of export const prerender = true alongside export function post etc as an error

@vwkd
Copy link

vwkd commented Feb 28, 2022

'you can ONLY prerender this endpoint', but I think that's probably fine.

I think that’s probably confusing. If there are two things which are true by default, then saying one is true doesn’t usefully imply the other is false.

The option should likely say it disables the opposite. Maybe dynamicRendering = false or something like that.

@Theo-Steiner
Copy link
Contributor

Theo-Steiner commented Mar 3, 2022

I think this would be a great feature, especially for apps where a part of the data from let's say a CMS changes only occasionally.
Right now, you can return maxage from load functions to not fetch on every subsequent navigation, but according to the docs this only works in non __layout.svelte routes and therefore isn't really an option for all use cases. (Especially if you would want to eliminate boilerplate by fetching the data in the layout and pass it down using stuff)
Since to my understanding maxage only works for the entire load function, this also breaks down once you mix fetching rarely changing data and frequently changing data inside a single load function. Now you no longer can return maxage, since it would mean you would miss out on the frequent changes and you end up having to make many unnecessary requests to the rarely changing data.
One can work around this at the moment, by fetching the rarely changing data in a prebuild step, writing it as json to the file system and importing that with vite.
However, I think this is a common enough use case (in fact it came up on discord just yesterday) that having a svelte kit solution for this would be great!
The proposed export const prerender = true would already solve those issues, as it provides more granular control on a per endpoint basis than the load function's maxage property. Even better than having a prerender=true would be having a maxage = milliseconds or regeneration_maxage = milliseconds inside the endpoint though. (Or perhaps even a webhook to regenerate?)
This would in a way be kind of similar to next's Incremental Static Regeneration (minus the prerender part), which is also a feature that comes up on the discord quite a bit.

@joeldrake
Copy link
Contributor

joeldrake commented Apr 21, 2022

Im calling an endpoint from a load function in a svelte layout, to fetch a dynamic navigation structure from a headless CMS.

Having this endpoint being prerendered at build time would be excellent.

Btw, I think opt in to endpoint prerender at build time is important. Some endpoints might fetch data from sources with dynamic content.

@furudean
Copy link
Contributor

furudean commented Apr 21, 2022

This would be a huge performance boost for those managing content inside Svelte Kit (with e.g. MDSveX), where only a new build would actually require endpoints to update their content. Game changer for listing content, RSS feeds, sitemap, etc.

@Rich-Harris
Copy link
Member Author

One thing that just occurred to me: in order to have prerendered endpoints that serve non-prerendered pages, we'll need the prerenderer to render every page it crawls, not just the prerenderable ones. In practice I think that's totally fine — we find the bits we need to prerender as a side-effect of prerendering the bits that we then discard — but it needs to be noted since it's technically a breaking change.

@Rich-Harris
Copy link
Member Author

From #4942: we might also need a way to declare that an endpoint should never be prerendered (i.e. prerendering /foo doesn't mean that /foo/__data.json is also prerendered, even though the data is inlined into the HTML)

@kyllerss
Copy link

Quick proposal to solving this: pattern-based config to include/exclude crawled URLs.

@benmccann benmccann added the size:large significant feature with tricky design questions and multi-day implementation label Aug 26, 2022
@dummdidumm
Copy link
Member

Right now prerender is allowed in +page.server.js, but the semantics are not as proposed here ("prerender only the end point, not the page"), so this would be a breaking change.

@dummdidumm
Copy link
Member

Closed via #6392

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change feature / enhancement New feature or request size:large significant feature with tricky design questions and multi-day implementation
Projects
None yet
Development

No branches or pull requests

9 participants