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?