What's the best way to run some code only client side?
Asked Answered
M

3

8

I'm trying to implement firebase in Sapper. I installed the modules (@firebase/app, @firebase/auth, @firebase/firestore) and then I wrote a configuration file:

import firebase from '@firebase/app';
import '@firebase/firestore'
import '@firebase/auth'

const config = {
    // ...
};

// Initialize Firebase
firebase.initializeApp(config);
export { firebase };
// Initialize db
export const db = firebase.firestore();
export const auth = firebase.auth();

When I "npm run dev", I got an error saying that those firebase modules are intended only for client side and not for Node.js.

So, I tried to fix this problem in many ways and the only one that seems to work so far is using onMount.

onMount(async () => {
    const {auth} = await import('../firebase/config');
    auth.signInWithEmailAndPassword("[email protected]", "test").then((res) => {
        // do some stuff
    })
})

Now it works, but I've 3 questions:

  1. is this the right way?
  2. should I remove those modules from server side or is better to keep them anyway?
  3. should I use both client side and server side versions of firebase and use client side one to retrieve all the data that are different for each visitor and server side to all the data in common?
Metheglin answered 14/7, 2019 at 20:24 Comment(0)
S
6

I'd say you are pretty close, but you can keep the import out of the onMount callback:

<script>
import { auth } from '../firebase/config';
import { onMount } from 'svelte'

onMount(() => {
    auth.signInWithEmailAndPassword("[email protected]", "test").then((res) => {
      // do some stuff
    })
})
</script>

If you do it this way, your firebase code won't be called during the SSR and you won't have to deal with async module loading.

With that said, I'd argue that placing your firebase code in a server route, and calling that route from the client is probably a cleaner and more efficient way to do it.

Stratton answered 29/7, 2019 at 14:17 Comment(0)
O
4

I would check process.browser

onMount(async () => {
    if (process.browser) {
        const {auth} = await import('../firebase/config');
        auth.signInWithEmailAndPassword("[email protected]", "test").then((res) => {
            // do some stuff
        })
    }
})

or

if (process.browser) {
    onMount(async () => {
        const {auth} = await import('../firebase/config');
        auth.signInWithEmailAndPassword("[email protected]", "test").then((res) => {
            // do some stuff
        })
    })
}
Oversubtlety answered 8/11, 2019 at 19:42 Comment(0)
R
1

You can use:

typeof window === 'undefined' // server
typeof window !== 'undefined' // client

Source

Raising answered 26/9, 2022 at 8:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.