sveltejs / kit

web development, streamlined
https://kit.svelte.dev
MIT License
18.51k stars 1.9k forks source link

Offer a way to avoid the waterfall because of nested layouts, `await parent()` to retrieve `locals` / Bring back `session` #11587

Open GauBen opened 8 months ago

GauBen commented 8 months ago

Describe the problem

Let's say I have a few layouts that fetch data using session credentials.

// hooks.server.ts
export const handle = ({event, resolve}) => {
  if (hasACertainCookie) {
    event.locals.session = getSessionFromCookie()
  }

  return resolve(event)
}

// Root +layout.server.ts
export const load = ({locals}) => locals; // Expose all locals to layouts and pages

// Many +layout.ts and +page.ts look like this
export const load = ({parent}) => {
  const {session} = await parent();
  return { thing: fetch(..., session) }
}

This will unfortunately create a waterfall, despite the only needed data are the one from local.session

Describe the proposed solution

Svelte-Kit < 1 had a session feature which allowed constant-time access to a bag of top props, and it can be used as inspiration

Alternatives considered

No response

Importance

would make my life easier

Additional Information

No response

mustofa-id commented 8 months ago

Instead of using parent, doesn't LoadEvent.data work for you?

GauBen commented 8 months ago

LoadEvent.data only contains the data from the .server.js parent file, not hook and layout data

GauBen commented 5 months ago

I'm upping this issue with a design proposal that's not just reverting #5883.

This will allow performant initial/subsequent load as we no longer have an await parent() waterfall:

// hooks.server.ts
export const handle = ({event, resolve}) => {
  if (hasACertainCookie) {
    event.session = getSessionFromCookie()
  }

  return resolve(event)
}

// Many +layout.ts and +page.ts will look like this
export const load = ({session}) => {
  // No await parent()!
  return { thing: fetch(..., session) }
}

I'm not sure about introducing a $session store, that should be feasible but would make the API surface bigger with no clear benefit. A developer interested in exposing session to pages would create a route +layout.js with export const load = ({session}) => ({session})

feus4177 commented 5 months ago

I have the same problem described here. If parent just exposed the raw merged result of previous load functions, you could selectively await what you wanted.

GauBen commented 2 months ago

I made a reproduction on SvelteLab to showcase the issue at stake: https://www.sveltelab.dev/62cm9uymsj5oso6

In this reproduction, the page takes 2s to load because there is no easy way to retrieve locals. It could take 1s if requests were properly parallelized.

Does that make sense?