16

I'm trying to do API calls in a SvelteKit page from the load function, but I don't want to proxy these calls with local endpoints because I want to keep the web server as light as possible.

What I want to do specifically is, when the call is made from the server, the API's URL should be different than when it's called from the client (e.g. "http://localhost:1234" vs. "https://example.com:1234", respectively).

But, more generally than this, is there a way to differentiate whether the current code is running on the server vs. the client?

cambraca
  • 27,014
  • 16
  • 68
  • 99

2 Answers2

32

Within the load function there is the option to use the browser flag after it's imported from $app/environment.

<script context="module">
    import { browser } from '$app/environment'; 
    ...
    export async function load({ fetch }) {
        if (!browser) {
            // code here runs only on the server
        }
        return {
           ...
        }
    }
    ...
<script>

Following comes from SvelteKit's docs:

browser is true or false depending on whether the app is running in the browser or on the server

phaleth
  • 569
  • 5
  • 7
  • 1
    is there anything wrong with just process.browser? – koo5 Jun 03 '21 at 21:12
  • @koo5 Wouldn't that mean adding the [process](https://www.npmjs.com/package/process) dependency? Not sure if that one is an ES module. A CJS module may not work for SvelteKit without some unnecessary workarounds ([FAQ](https://kit.svelte.dev/faq#packages)). – phaleth Jun 04 '21 at 16:33
  • can i use `browser` outside of load function? – chovy Feb 14 '22 at 23:07
  • @chovy The `browser` var gets initialized and that way gets it's value outside of the `load` function. So this var's scope is surrounding that `load` function's scope. You can of course pass the var as an arg to a scope even more outside to a custom function to use it's value in the scope of that custom function. – phaleth Feb 16 '22 at 16:50
6

Disclaimer: what I'm writing is not the real answer to the title, but it is the specific answer to the described problem.

There's a targeted hook function (handleFetch) that's build to address resources differently if client or server:

https://kit.svelte.dev/docs/hooks#server-hooks-handlefetch

/** @type {import('@sveltejs/kit').HandleFetch} */
export async function handleFetch({ request, fetch }) {
    if (request.url.startsWith('https://api.yourapp.com/')) {
        // clone the original request, but change the URL
        request = new Request(
            request.url.replace('https://api.yourapp.com/', 'http://localhost:9999/'),
            request
        );
    }

    return fetch(request);
}
Jacopo Pace
  • 460
  • 7
  • 14