question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Server-only load functions

See original GitHub issue

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:

<!-- /recipes/[slug].svelte -->
<script context="module">
  export const load = async ({ page: { params }, fetch }) => {
    const { slug } = params

    if (!slug || typeof slug !== 'string') {
      return {
        status: 400,
        error: 'Recipe not found',
      }
    }

    // No way to click to open endpoint definition
    const recipe = await (await fetch(`/api/recipes/${slug}`)).json()

    if (!recipe?._id) {
      return {
        status: 404,
        error: 'Recipe not found',
      }
    }

    return {
      props: {
        recipe,
      },
    }
  }
</script>
// /api/recipes/[slug].js
import getFullRecipe from '$lib/queries/getFullRecipe'

export const get = async (request) => {
  const { slug } = request.params

  // Duplicated error handling
  if (!slug || typeof slug !== 'string') {
    return {
      status: 400,
      error: 'Recipe not found',
    }
  }

  const recipe = await getFullRecipe(slug)

  if (!recipe?._id) {
    return {
      status: 404,
      error: 'Recipe not found',
    }
  }

  return {
    status: 200,
    body: recipe,
  }
}

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:

<script context="module" context="server">
  import getFullRecipe from '$lib/queries/getFullRecipe'

  export const load = async ({ page: { params }, fetch }) => {
    const { slug } = params

    if (!slug || typeof slug !== 'string') {
      return {
        status: 400,
        error: 'Receita não encontrada',
      }
    }

    const recipe = await getFullRecipe(slug)

    if (!recipe?._id) {
      return {
        status: 404,
        error: 'Receita não encontrada',
      }
    }

    return {
      props: {
        recipe,
      },
    }
  }
</script>

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 🙏

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:20
  • Comments:10 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
Rich-Harriscommented, Feb 2, 2022

Closing in favour of #3532

2reactions
kevmodromecommented, Jan 24, 2022

@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.) 😉

This looks really cool! You should add it to the newsletter that’s coming up in a bit! 👍

Read more comments on GitHub >

github_iconTop Results From Across the Web

Loading data • Docs • SvelteKit
A load function in a +page.js file runs both on the server and in the browser. If your load function should always run...
Read more >
Execute load function on server side only #3270 - GitHub
I need to do some web scraping and struggle with how the load method in Sveltekit is triggered both in server and client...
Read more >
How to make server only functions in SignalR - Stack Overflow
I want to use SignalR to push data to web clients. However, I don't want clients to be able to invoke this function....
Read more >
Loading Data – Vercel Docs
A server-only load function must return data that can be serialized with devalue such as anything that can be represented as JSON or...
Read more >
15: 9.27. System Administration Functions - PostgreSQL
Table 9.87 shows the functions available to query and alter run-time configuration ... Returns the currently-loaded WAL resource managers in the system.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found