How am I supposed to access my Firestore from the server side on Firebase?
Evertt opened this issue · 3 comments
For example, if I want to preload some data from Firestore, how would I access my firestore? Are the credentials stored in some secret environment variable? Since the whole thing is hosted at firebase, I would expect that they'd know that if someone tries to access the Firestore from within a firebase function, that they should be allowed, right? Is that how it works?
edit
The past few weeks I've also been working on another hobby project and there I was able to make Firestore work on both server-side and client-side, both locally and when deploying to Vercel. The magic is in this file.
Here's an explanation of how that code works:
- I check whether the code is currently being run in Node or in the browser by checking
process.browser - If we're in the browser then I know that Firebase was loaded globally, because I inserted a
<script>tag intemplate.htmlfor that.- In this case I can just hard-code the credentials in the code, because the client-side firebase's credentials would always be discoverable anyway when anyone takes a look in the code with their browser's developer tools.
- If we're in Node then I require the
firebase-adminpackage, which has a nearly identical API to the browser-version of firebase.- In this case I can't hard-code the credentials, because the credentials for
firebase-adminare much more powerful and therefor sensitive data. So instead I rely on environment variables to give me the credentials. I've set those up in both my GitHub repository's secrets and in Vercel's secret environment variables. (See here, here and here)
- In this case I can't hard-code the credentials, because the credentials for
- I initialize the Firebase app and Firestore using the correct credentials and I export those variables from the file.
The nice thing about having it this way is that I can just require store/firebase.js wherever I want and it doesn't matter if the code is run server-side or client-side, I will always get the correct version of Firebase.
Now I tried using the same approach with your template, but I can't get it to work. The environment variables don't seem to be available despite having them set up in my repo's secrets. Maybe the problem is that I haven't set any env vars up in firebase-functions yet, because I don't yet understand how that works.
edit2
If we can get this to work, it might be nice to include it in the template, don't you think? So that people have a super easy way to access their Firestore from both serverside and clientside.
And just to show off a bit, I also wrote some code that wraps a Firestore Query in a Svelte Readable store which subscribes to live snapshots of that query. The result is that I can write code like this in my components:
<script>
import { collection } from "../store"
export let roomReference // this will contain a Firestore document reference
// messages is now a svelte readable store
// and at the same time it's also a Firestore Query,
// which means you can keep chaining on more query constraints.
const messages = collection("messages")
.where("room", "==", roomReference)
.orderBy("created")
</script>
{#each $messages as message (message.id)}
<div>
<small>{message.author}</small>
<p>{message.body}</small>
</div>
{/each}Isn't that beautiful syntactic sugar? AND it updates live whenever the data in Firestore changes.
So far, I've only ever used Firestore server-side so it's only accessible through the GraphQL server.
In production (i.e. when it's actually running in a Cloud Function for Firebase), I don't need to specify any credentials because they're automatically set:
import { credential, firestore, initializeApp } from "firebase-admin";
initializeApp({
credential: credential.applicationDefault(),
});When I run the development server locally (or even npm run prod then npm run start to run a production server locally, as described in the README), that same code will find my credentials from a GOOGLE_APPLICATION_CREDENTIALS environment variable with the value being the path to a service account secret that has the admin credentials.
Thanks for that info, that's what I was looking for! :-D
Just out of curiosity, why would you use GraphQL as a middleman between the frontend and Firestore? I don't see any benefit in that.
Because I wanted an API that other people / sites can use.