SSR Only Routes
Describe the problem
In the fine-print of many API services, there is a clause to not re-distribute the data of the service API in another API. Sometimes parts of our apps will need to use these third-party data-sources. We may not necessarily have the license to distribute said data as json.
Another example: needing to show advertisement along with articles! We don't want someone to directly access our API and just read articles without our ability to monetize with ads! With full HTML render, ads will also be sent along.
Describe the proposed solution
SSR-only routes--routes without __data.json or that do not respond to application/json request headers, insure that we are not re-distributing API data in a way licensing does not allow.
Old school SSR. No API endpoints. Also, all endpoint point to this route should not try __data.json. With regard to prefetching, the browser does have a <link rel="prefetch" href="foo/bar" /> option, and perhaps a mouse over could get the browser to start a prefetch the HTML5 way for SSR only routes.
SSR-only routes living along side with smart hybrid rendered routes. It would be glorious.
Alternatives considered
Hand-crafting GET exports to fail on JSON requests use a proxy server to prevent JSON content going out from certain routes. Bleh.
Also needing to place sveltekit:reload on all inbound links as well. May even need to write custom logic to include HTML5 prefetching as well (ie, <link rel="prefetch" href="foo/bar" />). Tedious bookkeeping. Would be great if there was a compiler that could do this for us.
Importance
would make my life easier
Additional Information
No response
You can already workaround with simple if condition in hooks or endpoints. Anyway I agree this would be good if it would be configurateable.
One possible idea: +page.server.svelte. This wold tell SvelteKit to exclude the route from the client-side manifest, which would cause it to always reload the page.
The wrinkle is that in cases of ambiguity...
src/routes/static/+page.server.svelte
src/routes/[dynamic]/+page.svelte
...where /static should be matched by the +page.server.svelte file and not the +page.svelte file, the client-side router still needs to be aware of the existence of the SSR-only route. But that seems achievable.
@Rich-Harris That sounds perfect. Currently the static route takes precedence with +page.svelte seems consistent to do the same here.
https://stackblitz.com/edit/sveltejs-kit-template-default-mndnrh?file=src/routes/[test]/+page.svelte
Also, a request--can we not label this as p3-edge-case and something more on the radar?
@Rich-Harris
Like this?
| Data SSR Only | Data SSR & CSR | |
|---|---|---|
| Hydrate | +page.server.svelte |
+page.svelte |
| Don't Hydrate | +page.server.svelte and +page.js exports csr = false |
+page.svelte and +page.js exports csr = false |
I'm wondering if a +config.js or +config.json for options like csr = false, prerender, etc... might not scale better and be less confusing as routes gain features.
I've also read some feedback that template names in the files, like foo@(bar) are prone to error. Perhaps having a route-based config option would better support this or at least give the option to declare layout there instead of in the path name.
Added this discussion.
https://github.com/sveltejs/kit/discussions/6587
+config.js would enable type checking on template names where ornamented file-name lack this type safety when template names change. Type safety would make refactoring and overall maintenance easier.
We talked about this in more detail recently. The conclusion is that we're not sure what's the best API yet, given that changes to Svelte core might affect the outcome.
The ideas:
add new value to ssr option
export const ssr = 'always' would mean "always render this on the server". Combined with export const csr = false you would get server rendered HTML without hydration. There's on inconsistency with naming between the page options though: prerender has true/false/auto, with true meaning "always". This would be inconsistent with the ssr option where true means "sometimes" and "always" means "always"
add +page.server.svelte
The idea is that this would always render on the server and never hydrate, allowing you to do stuff like directly calling the database, importing private environment variables without fear of them being exposed to the client etc. It's more flexible than +page.server.svelte because you can also always render on the server first but do hydration. It's less powerful because you couldn't use private environment variables (right now validity are checked using the file name, changing this is probably impossible given the timing where it happens).
Why we can't decide yet
Svelte 4 might provide async rendering or streaming rendering, which could affect this feature. For example, it could be possible to use #await blocks in a +page.server.svelte component which streams out the other stuff and streams the rest once the promise is completed and rendered.
I'm not saying anything of this will happen in Svelte 4, but it's one possibility
In the meantime, the problem of always rendering on the server can be worked around by having all incoming links with data-sveltekit-reload so they always do SSR. Furthermore - THIS IS NOT LEGAL ADVICE - I don't think that a __data.json call that contains JSON-like data serialized through devalue counts as "redistributing the API".
I really like the behavior of these at the same time
export const csr = false;
export const ssr = true;
Getting pure HTML is nice and sure I can include scripts through svelte:head but it's a shame to lose the functionality of simple "reactive" things like clicking a button and seeing a counter go up. Not sure if there's a way to both keep pure HTML output from my "sensitive data" (instead of __data json) while also keeping "simple" reactivity, but would be nice
I really like the behavior of these at the same time
export const csr = false; export const ssr = true;Getting pure HTML is nice and sure I can include scripts through svelte:head but it's a shame to lose the functionality of simple "reactive" things like clicking a button and seeing a counter go up. Not sure if there's a way to both keep pure HTML output from my "sensitive data" (instead of __data json) while also keeping "simple" reactivity, but would be nice
Is this something achievable, a mode where using ssr, we can say if we would like some part of the layout should still be using hydration ?
Right ideally we can control:
- Only load this query as part of the page (full page render, SSR) never independently. Not remote call eligible, data source is not an API.
- Load this with the page; but then only refresh if the page is revisited after 5 minutes.