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