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?
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>
this.fetch is meant to be used only in routes (think asyncData in Nuxt).
Using Axios is a common solution too, as it allows to write code that execute the same in both environments without patching fetch (like you would with node-fetch).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With