Data From Endpoint To Layout and Pages In SvelteKit

Overview

In this article, we will create a standalone endpoint in SvelteKit and fetch data from the endpoint and load the fetched data into a layout page so that we can access the same data from any descendant pages that are wrapped around by the layout page.

Standalone Endpoints

According to the official SvelteKit doc, Endpoints are:

Endpoints are modules written in .js or .ts files that export request handler functions corresponding to HTTP methods. Their job is to make it possible to read and write data that is only available on the server (for example in a database, or on the filesystem).

There are two types of endpoints in SvelteKit:

Type of EndpointExplanation
Page Endpointan endpoint that has the same filename as a page(except for the extension)
Standalone Endpointan endpoint that is separate from pages

Let's say there is a configuration json file in your OS home directory and you want to display that information in a main page of your SvelteKit web application. For example, I created the following file in the home directory on my Mac mini.

1{
2 "name": "Youngjae Jay Lim",
3 "description": "Human"
4}

To read the configuration json file and return as data, you need to create config.js file in the ./src/routes/ directory like this:

./src/routes/config.js
1import os from 'os'
2import fs from 'fs'
3import path from 'path'
4
5const config = JSON.parse(
6 fs.readFileSync(path.join(os.homedir(), 'config.json'), 'utf-8')
7)
8
9export async function get() {
10 if (config) {
11 return {
12 body: config,
13 }
14 }
15
16 return {
17 status: 404,
18 }
19}

Please open up your web browser and access http://localhost:3000/config. You should see a result as following:

sveltekit

This is a standalone endpoint because it is not tied to a page with the same filename(say, ./src/routes/config.svelte). We will fetch data from this enpoint in a layout page in the next section.

Layout Data Loading

What is Layout Page

Now that we've created the endpoint, we can fetch data in a layout page. The layout is an element that should be visible on every page you navigate, which could have a navigation bar or a footer. Without layout components, you have to repeat the nav bar or footer for every page. Due to this nature of layout page, you can also fetch data from any endpoint that will be accessible to any nested pages and components.

How to fetch data in a page

To fetch data in a page, we will utilize a SvelteKit built-in function called load() that runs before the component is created. This way, we can fetch and manipulate data before the page is rendered. The SvelteKit official documentation puts an emphasis on:

  • The load() function runs both during server-side rendering and in the client.
  • load applies to only page and layout components(not components thay import). In other words, you can't use load() in a regular component(for instance, a component in ./src/lib/ directory).

To create a default layout in SvelteKit, you create __layout.svelte in ./src/routes/ directory.

./src/routes/__layout.svelte
1<script context="module">
2 export async function load({ fetch }) {
3 const url = "/config";
4 const res = await fetch(url);
5
6 if (res.ok) {
7 const config = await res.json();
8 return {
9 props: {},
10 stuff: { config },
11 };
12 }
13
14 return {
15 status: res.status,
16 error: new Error(`Could not load ${url}`),
17 };
18 }
19</script>
20
21<slot />

What this does

First, we have a script tag <script context="module"> that allows load() to run before the page is rendered.

Secondly, as you see, load receives an implementation of SvelteKit-provided fetch wrapper. This fetch made a request to our app's own endpoint /config that we've created earlier without issuing an HTTP. As a result of fetch, we get a copy of the response that is sent embedded in the initial page load.

Please also pay attention to props and stuff variables in the return object. I intentionally put config variable to stuff, not props because props will be an empty object for:

  • layout components
  • pages without endpoints

The stuff is passed from the layout page to any nested pages, you can literally put any stuffs to stuff that will be available to subsequesnt load functions. We will see how we can access stuff from the nested page in the next section.

Page

Now that we have config data available through stuff in our layout page, we can use it in a main page of our app. In similar to what we did in the layout page to fetch data from an endpoint, we will use the same load() to retrieve stuff object that is already available to the nested main page via the layout page.

./src/routes/index.svelte
1<script context="module">
2 export async function load({ stuff }) {
3 const { config } = stuff;
4 return {
5 props: { config },
6 };
7 }
8</script>
9
10<script>
11 export let config;
12</script>
13
14<main>
15 <h1>Who am I?</h1>
16 <p>Name: {config.name}</p>
17 <p>Description: {config.description}</p>
18</main>

Make sure to spin up dev server and access http://localhost:3000 in a browser:

sveltekit

That's all for this article. Now you can create a simple endpoint and fetch data from it and pass it onto other pages all happenning withing a single SvelteKit web application. If you have any questions, please feel free to leave a commnet below.

Comments

© 2022 Youngjae Jay Lim. All Rights Reserved, Built with Gatsby