Closed hdoro closed 2 years ago
Sounds related to https://github.com/sveltejs/rfcs/pull/31 (RFC talks about Sapper, but the same could be applied to SvelteKit)
It's exactly the same use case as this RFC, Simon! Thanks for sharing :D
I wonder if that will circle back to SvelteKit, the RFC seems to be quite stale 🤔
I could see potential issues with Vite seeing import statements in a .svelte
file and wanting to treat them as client code, rather than server code; e.g. https://github.com/sveltejs/kit/issues/1570 and the like. I don't think it would be reasonable to expect Vite's heuristics to learn the difference between <script context="module">
and <script context="module" context="server">
; that seems like it would be the job of Svelte-Kit to detect that case and adjust the Vite config in svelte.config.js
to treat those modules as server-side code. I don't know exactly how that could be handled during the build process, but perhaps people more familiar with Svelte-Kit's internals will have an idea.
Or maybe something like this might work as well..
The idea is to pass the data from server-side load
method to client-side load
similar way like SvelteKit's fetch
does, but using some parameter (e.g. data
). It could work similar way like stuff
parameter for __layout
s, but in this case between server and client...
UPDATE:
Oh, i previously didn’t notice, that stuff
should work for all subsequent load
methods, so my code should probably work with the stuff
parameter instead of data
, right? (or subsequent does not mean server-client in this case?)
From the docs:
For the root __layout.svelte component, it is equal to {}, but if that component's load function returns an object with a stuff property, it will be available to subsequent load functions.
<script context="module">
import getFullRecipe from '$lib/queries/getFullRecipe'
export const load = async ({ page: { params }, fetch, data }) => {
const { slug } = params;
if (!slug || typeof slug !== 'string') {
return {
status: 400,
error: 'Receita não encontrada',
}
}
let { recipe } = data;
if (!recipe) {
recipe = await getFullRecipe(slug)
}
if (!recipe?._id) {
return {
data: { recipe: {} },
status: 404,
error: 'Receita não encontrada',
}
}
return {
data: {
recipe,
},
props: {
recipe,
},
}
}
</script>
A year later, what's the status on this? I haven't seen any progress on the proposed RFC or other issues.
@rubybb Someone please correct me if I’m wrong but I believe this is incompatible with the “serverless” route SvelteKit’s taken.
I’m working on a tightly coupled Node.js server that’s basically designed around this pattern with NodeKit. It has a much narrower focus and is at a VERY early stage right now, but in case it helps, check out https://github.com/small-tech/nodekit
For example, this what you can do today (but, again, NodeKit is nowhere ready for actual use yet):
<data>
if (db.greetings === undefined) {
db.greetings = { count: 1 }
}
export default () => {
return {count: db.greetings.count++}
}
</data>
<script>
export let data
</script>
<h1>Hello, world!</h1>
<p>I’ve greeted you {data.count} times.</p>
(That’s a fully functional example. Clone the repo, run ./install
, pop the above code into a file called index.page in some folder and run nodekit
in the folder and hit https://localhost to have a play by refreshing the page. Restart the server, note the count is retained. See the greetings.js file in the .db folder for how.) ;)
A year later, what's the status on this? I haven't seen any progress on the proposed RFC or other issues.
I'd like to suggest taking a look at Svemix in the meantime: https://svemix.com
@rubybb Someone please correct me if I’m wrong but I believe this is incompatible with the “serverless” route SvelteKit’s taken.
I’m working on a tightly coupled Node.js server that’s basically designed around this pattern with NodeKit. It has a much narrower focus and is at a VERY early stage right now, but in case it helps, check out https://github.com/small-tech/nodekit
For example, this what you can do today (but, again, NodeKit is nowhere ready for actual use yet):
<data> if (db.greetings === undefined) { db.greetings = { count: 1 } } export default () => { return {count: db.greetings.count++} } </data> <script> export let data </script> <h1>Hello, world!</h1> <p>I’ve greeted you {data.count} times.</p>
(That’s a fully functional example. Clone the repo, run
./install
, pop the above code into a file called index.page in some folder and runnodekit
in the folder and hit https://localhost to have a play by refreshing the page. Restart the server, note the count is retained. See the greetings.js file in the .db folder for how.) ;)
This looks really cool! You should add it to the newsletter that's coming up in a bit! 👍
@kevmodrome Thanks, Kevin, but might be better to hold off a bit. It’s very early, I’d hate to get people too excited while it’s evolving rapidly. If anything, maybe with a huge warning that it’s not ready for use yet but might be fun to start playing with :)
Closing in favour of #3532
Describe the problem
Thanks for building kit and all the heroic efforts in dealing with this amount of issues!
As the load function runs in both client & server, we always find ourselves creating an extra endpoint for fetching data with server credentials. This is laborious and tedious, leads to duplication of error handling and makes it harder to reason about data flow.
In the example below, notice how
/recipes/[slug].svelte
and/api/recipes/[slug].js
have a lot of duplication:Describe the proposed solution
Ideally, Kit's adapters would automatically transform server-only functions into their own endpoints, without us having to think about it. This would be similar to Next's getServerSideProps.
To annotate a function as server only, we could pass a
context="server"
tag to the module<script>
tag. Here's the example above with this approach:Single file, ~50% code reduction (29 LOC vs. 55 in the example above), one less file to manage ✨
Alternatives considered
I'm considering creating my own abstractions to make this slightly easier to reason about. For example, I could condense all data-fetching server endpoints into a single
get
function that takes whatever query I need to perform and returns the data accordingly.The issue here is that it still wouldn't be as simple as a native solution and we'd be opening up a lot of dissonance between different codebases.
I understand this is potentially a very hard issue to tackle, but if doable it feels like a pre-v1 feature to make dynamic routes easier to build & onboard new people.
Importance
would make my life easier
Additional Information
Sorry if I double posted this - searched hard through issues and couldn't find another. So many issues coming in, thanks for putting in the work to deal with all this pressure 🙏