-
-
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
Remove $page.stuff
and allow load
functions to run concurrently
#4911
Comments
Hi @Rich-Harris
I think one solution is to make stuff a function (same as props in your example) which it's first parameter is merged stuff from parent layouts export async function load({ fetch }) {
const res = await fetch('/some-data').then(res => res.json())
return {
stuff: (stuff) => ({ // merged stuff from parent layouts
b: stuff.a * res.multiplier,
apiKey: res.apiKey
}),
props: (stuff) => ({ // final stuff object
title: stuff.title
})
};
} |
Since svelte is already a compiler could you detect if From my view, the purpose of
the reason stuff is useful is that so if this would be a case where having the dependancy tree makes sense, however this could easily achieved without the dependancy tree simply by putting So the only way this wouldn't actually be rewritten without the nesting is if the parents fetch data and put it in params.stuff and you don't want to duplicate that fetching in I think one way to get around the series fetching in this case would be to just allow In a perfect world I guess only one fetch function would be run per route if this is an initial page load and the fetch function could determine how the parallelism is handled ( Let me know if I'm completely off here |
I typically pass some meta data through stuff from leafs components or better said pages to upper layouts, where I can use them. I even pass title of page through it. |
I use I‘d still welcome a solution in which these things could be done in SSR with a simple |
I use This should still be possible to do in any new situation. |
Also using To me it seems like the features of
It seems like 2 and 3 are mostly a convenience that could be done in user-land via a store + context, if I'm not missing something. |
I'm using this for breadcrumbs atm, if this is going to be removed please document how to replace this "upwards push" functionality elsewhere? I'd rather not have to re-engineer this system because of a svelte update. |
Almost. It could be made to work in a client-side situation, but not during SSR — by the time you set the store value in the leaf, the layout would already have been rendered. The only way to get that data to the layout in time for it to be SSR'd that I can see is a) with a SvelteKit-managed store (like // we can render this layout immediately, because it returns a props object
return {
props: {
answer: 42
}
}; // we wait to render this layout until we have accumulated `stuff` from the child layouts and the leaf
return {
props: (stuff) => ({
answer: 42,
breadcrumbs: stuff.breadcrumbs
})
}; If you do the first option, you opt out of the ability to read child |
I only just recently understood what Reading this thread, I'm reminded of how DOM events have 2 phases, bubbling and capture, to handle this type of logic where we want to push data up through the hierarchy of elements as well as annotate an event while it's being pushed down through the hierarchy. Maybe there's similar event pattern we can make use of for |
One thing to consider for nested layouts: if one of the layouts/endpoints errors out, do we throw the whole chain under the bus or cancel out only the layout stack at and below the error, and return (in SSR) only what succeeded? |
I like the idea of running the I think there might be alternatives to removing
A lot of the serialized data for hydration could be dropped if we introduced something like partial hydration. This is obviously not something that would happen in the near future, but Svelte's always avoided taking API shortcuts and focused on the long-term. In terms of The HTML for the top of the page could only be sent if we truly supported streaming. The HTML itself is unlikely to be that large, but may link to larger resources like images. Those could potentially be handled in a similar way to the The |
What if Layouts were able to receive all of the props of their children as slot props? This would remove the need for <!-- __layout.svelte -->
<script>
// These come from whatever page is rendered in <slot/>
// and are also available as slot props to a parent layout
export let user
export let navLinks
// These are passed down to pages
let var1 = 'some data from the layout'
let var2 = 42
</script>
<header>
Hello {user.name}
</header
<nav>
{#each navLinks as navLink}
<a href={navLink.href}>{navLink.text}</a>
{/each}
</nav>
<main>
<!--
user and navLinks are passed "up" to the layout from the page.
var1 and var2 are passed "down" to the page from the layout.
-->
<slot {bind:user} {bind:navLinks} {var1} {var2} />
</main> |
So not sure if this is related, but it seems like it is. I'm trying to do a new project and ran into a problem with how things currently are: nested layouts which have a Each level of the route structure has a Say, you were on I'm very new to SvelteKit so maybe there is a way to make this work as things currently stand? If not, it should definitely be factored in. |
Hi @Rich-Harris ,
Some psuedo code in the
and now in the specfic routes pages access it in the load and pass it down
Here is the logic which is primarily client side only (Depends on initialization of svelte stores on initialization)
|
Since this thread has been revived I'll weigh in because I've been learning stuff for my current project and came to quite enjoy it. I have come from SSGs so I use stuff like you would use Jekyll front matter: to pass all manner of things from pages up to layouts. Specific example: I have an app that displays a team's members on one page and clicking a person navigates to that person's profile page. Standard stuff (no pun intended, honest). Also standard stuff is passing the title of the page to its layout to be used in a heading and styled, obviously, by the layout. I have a Sidebar component in my top layout that needs different links depending on which page you're on. One set of links on the team list page, a different set on the person page (and other pages). These links I send via The sidebar also has an image at the top which is the person's profile pic on the person page and the team's logo on the team page. These come from data fetched by endpoints that relate to the pages, and are passed up to the layout in Once I got If I couldn't pass this data up, I would have to repeat the Sidebar over and over again on each page. Then what would be the point in having a layout if it doesn't keep my code dry? Having said that, I would happily do it with slot props or something else. I find |
The more I think about this the more I like the propsal - The majority of people seem to use Possible solution: |
Closing, as |
@dummdidumm sorry, perhaps I missed something, what would be the current recommended way to pass information from |
As Rich pointed out in his last comment, use |
Thanks a lot for you (instant!) reply. I was going to try this (basically setting a store with context in the layout) but I still don't quite get the pros/cons of each approach. I'm trying to do simple stuff like changing the title or a class of and element in the layout from a page component. I'll give a try to both approaches. Currently I solved it with a shared store between the layout and the page. |
Describe the problem
I've come to the view that
stuff
(as it's currently designed) is a mistake, because it forces nested routes to load serially and because it prevents us from taking advantage of nested routes to stream responses (see #4910).Ideally if we had a route like this...
...then two things would happen. Firstly, we'd fetch
one.json
,two.json
andthree.json
concurrently. Secondly, as soon asone.json
returned, we'd flushthen as soon as
two.json
returned, we'd flushthen as soon as
three.json
returned, we'd flush the remainder:At present, that's not possible. We run
load
functions in sequence for two reasons...load
functions should not runstuff
that was returned from an rootward layout...and we can't render anything until everything has loaded, because the root layout might make use of
$page.stuff
.Ideally, we'd be able to solve all these problems without relying on a design that forces serial loading and delayed rendering.
Describe the proposed solution
Honestly, I haven't really figured this out yet — I'm really just trying to articulate the problem in hopes that a solution will present itself. But here's a straw man:
This doesn't feel totally intuitive, but it would speed up performance in the common case where
load
isn't blocked on its parents, and$page.stuff
isn't used. And we would still have the ability to bail out if a parentload
redirects (maybeawait parent()
throws an error for non-200 responses?)Alternatives considered
I am all ears. (I'm also interested to know how people are using
stuff
)Importance
would make my life easier
Additional Information
No response
The text was updated successfully, but these errors were encountered: