Search code examples
sveltesapper

How to use fetch in a Sapper project outside of routes?


In Sapper it's possible to use this.fetch in the preload() function inside <script context="module">. Sapper then figures out whether to use the client or server version of fetch.

<script context="module">
    export async function preload() {
        const res = await this.fetch(`something.json`);
    }
</script>

Writing all your requests in your routes doesn't scale well so it becomes a necessity to create an api service to do something like:

<script context="module">
    import {getJson} from 'api';

    export async function preload() {
        const res = await getJson();
    }
</script>

This creates a problem since outside of the preload() function there is no this context provided by Sapper and hence no this.fetch available when running in the Node context (when loading the first page of the application and doing SSR). Afterwards all requests are made from the browser so regular fetch is available.

A solution could be to use an HTTP client for Node like node-fetch in the api service and then determine at runtime with process.browser if we need to use fetch or node-fetch.

Is there a better way to overcome this Sapper limitation?


Solution

  • The solution you came up with is the most common one. An alternative would be to pass this.fetch as an argument along others to the the getJson method:

    <script context="module">
        import {getJson} from 'api';
    
        export async function preload() {
            const res = await getJson(this.fetch);
        }
    </script>