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

Prerendering overhaul #6356

Closed
Rich-Harris opened this issue Aug 28, 2022 · 10 comments · Fixed by #6197
Closed

Prerendering overhaul #6356

Rich-Harris opened this issue Aug 28, 2022 · 10 comments · Fixed by #6197

Comments

@Rich-Harris
Copy link
Member

Describe the problem

There's a few improvements that need to happen to prerendering that, while separate, are probably best tackled in one go. The broader context for this is #6197, in which it will be possible to set export const prerender in a layout — e.g. the root layout — such that it will be inherited by all pages within.

  • Instead of being a boolean, prerender should be an enum so that we can distinguish between pages that can be prerendered from those that must be prerendered. The latter can safely be excluded from the SSR manifest, whereas presently we can only exclude prerendered pages without dynamic parameters
  • +server.js files should be able to declare their prerenderability (or otherwise) as well. +server.js files with POST etc cannot be prerendered.
  • Throw an error (or warn?) if using adapter-static with invalid routes #4287

Describe the proposed solution

Must-prerender pages could be declared with

export const prerender = 'always';

I'm not sure what a great name is for the current prerender = true (i.e. can-prerender). One suggestion was this...

export const prerender = 'maybe';

...though I would be interested in alternative suggestions. (This isn't something you'd use often — only in cases where, for example, you want to prerender your 1,000 most popular blog posts or whatever and let the long tail be SSR'd, though #661 would be a better solution in the longer term.)

Since +server.js files are standalone — i.e. they don't have a +layout to inherit from — the naive approach would be to make it necessary to declare the setting for every file individually, which is a pain. Instead, I think +server.js files should inherit their prerenderability from the pages that request them during prerendering (i.e. if an endpoint is only fetched by a must-prerender page, it can be excluded; if it is fetched by a can-prerender page or isn't fetched at all, it must be included). If necessary, it can be made explicit with export const prerender = value.

Alternatives considered

No response

Importance

would make my life easier

Additional Information

No response

@inudge
Copy link

inudge commented Aug 28, 2022

always, never and sometimes seems logical to me, maybe a little odd.

@david-plugge
Copy link
Contributor

What about auto?

@Rich-Harris
Copy link
Member Author

Normally I like 'auto' for this sort of thing, but only if it's the default, and the default has to be false (or rather, 'never')

@PatrickG
Copy link
Member

PatrickG commented Aug 29, 2022

I think auto makes the most sense.
Maybe even boolean | 'auto' instead of 'always' | 'auto' | 'never'.

Normally I like 'auto' for this sort of thing, but only if it's the default, and the default has to be false (or rather, 'never')

Think of CSS margin, it is not auto by default, but you can set it to auto.

@benmccann
Copy link
Member

In the maybe/sometimes case, what controls whether the prerendering actually occurs? If the user has control then selective might be an option. If it's SvelteKit then auto isn't bad

@madeleineostoja
Copy link

I don't think auto has to be the default for it to be a good option, because (if I understand it correctly) it's an accurate descriptor of what is happening if set.

I also like the simplified boolean | 'auto' idea @PatrickG suggested. It's easy to intuit what it's meant to do (yes/no/maybe). Especially since 'auto' or whatever would be the edge case, so the majority of users keep their simple export const prerender = boolean

@Rich-Harris
Copy link
Member Author

In the maybe/sometimes case, what controls whether the prerendering actually occurs?

At prerender time, 'maybe' and 'always' are identical, i.e. if the crawler can reach the page, it gets prerendered. The difference is whether the route is included in the SSR manifest — instead of only excluding routes with no dynamic parts (as currently happens), we can exclude all routes that are always prerendered, resulting in slimmer deployments.

I can definitely see the appeal of boolean | enum. 'auto' for a non-default value still feels a little odd to me but I'm clearly in the minority!

I don't think it affects this proposal, but just going to throw this out there anyway: it's possible we'd want to use this value for incremental static regeneration (ISR) as well in future:

export const prerender = {
  incremental: true,

  // cache for all users based on pathname (disregard cookies/searchParams/etc)
  key: (event) => event.url.pathname, 

  // enable selective cache purging
  tags: ['recipes']
};

@madeleineostoja
Copy link

In that case why not make it an optional opts object now for the advanced case?

export const prerender: boolean | {
  enabled: boolean;
  excludeSSR: boolean;
}

@Rich-Harris
Copy link
Member Author

enabled would always be true, so it would be more like this...

export const prerender: boolean | {
  excludeSSR: boolean;
}

...which feels a bit to me in the absence of other options. If we do end up using this for ISR then it would be easy enough to treat 'auto' as a shorthand for an options object, but until such time as that happens I worry this would feel like an unnecessary hoop, and there's more pressure to make it forward-compatible with an API we haven't designed yet

@madeleineostoja
Copy link

That makes sense 👍🏼

Keen for auto then, especially if this unblocks the PR to set ssr etc from layouts vs hooks and config

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