Firebase & GraphQL

FirebaseFirebase Realtime-DatabaseGraphqlGraphql Js

Firebase Problem Overview


Does anyone have any experience with GraphQL and Firebase? I figure one would place the firebase calls in the resolver of the relevant field, passing some variable from the props of the component into the arguments of the query.

How can we insert new data in Firebase using GraphQL?

Firebase Solutions


Solution 1 - Firebase

To answer your question, there are three ways you can deal with this.

1. Firebase & GraphQL

If you're set on using Firebase, you can make a one-to-one mapping of Firebase's API into GraphQL queries and mutations.

You can surely wrap the Firebase API into GraphQL resolvers, and make calls that way. This is a good example of that:

const ref = path => firebase.database().ref(path)
const getValue = path => ref(path).once('value')
const mapSnapshotToEntities = snapshot => snapshot.val().map((value, id) => ({ id, ...value }))
const getEntities = path => getValue(path).then(mapSnapshotToEntities)

const resolvers = {
	Author: {
		posts(author) {
	  		return getEntities('posts').then(posts => filter(posts, { authorId: author.id }))
		},
	},

	Post: {
		author(post) {
	  		return getEntities('authors').then(posts => filter(authors, { id: authorId }))
		},
	},
};

Essentially, what you're doing here is using Firebase as a database, which works until you want to query your data in a relational manner in your resolvers. Without the ability to perform joins on the server side on top of your data store, you'll be making tons of round-trip requests to Firebase in your resolvers to fulfill just a single request.

The reason most people use Firebase is for its real-time capabilities, and not primarily just as a data store since the data relational modeling tools in this aspect are fairly lacking. With that, you're probably better off migrating over to GraphQL using a different data source.

2. GraphQL Backend as a Service

Considering you're open to using BaaS products like Firebase, you might consider switching over to a GraphQL BaaS.

3. Self-hosted GraphQL

If you're open to changing over to a self-hosted solution using your own data store, there are many benefits to that as well. Here are a few big hitters:

  • Flexibility of using your own data store and perhaps multiple to suit your specific app's needs

  • Custom queries and mutations

  • Natively add custom logic instead of via microservices attached to webhooks in your API

  • Roll your own authentication and permissioning mechanisms

  • Likely a lower-cost solution

Solution 2 - Firebase

I strongly disagree with some recommendations here. GraphQL can be used in a relational way but it can also be used in a NoSQL way. Firebase, with its RTD (Real Time Database) and Firestore, should be modeled as a NoSQL database because it's a NoSQL database! There are tradeoffs to this approach:

1. Optimized read:

As a NoSQL database, the collections should be modeled as your views in your clients (mobile or web), so when you make a query, everything is already merged and you don't have to make computed props in the client nor Firebase functions. This approach makes reading really REALLY fast.

2. De-optimized write:

The main trade off here is that is your responsibility to update every document in the database if you touch related data (like updating the username, profile picture, etc). In this case you should find every document in your database (ie: posts, comments, etc) and ensure atomicity. This approach is recommended if you have an app that is going to have far more read operations than write operations (like a blog, 7000 reads to 1 write as an example).

3. Easy to scale:

As your collections do not have hard relationships with other documents, you can have a complete collection in only one server or split it among many of them. (That's why Firebase is cheap to scale, like DynamoDB.)

GraphQL is only a query language. It should make easy for you to query things, but it should not dictate how you model your database. You should dictate how to model your database, your queries, and mutations.

Solution 3 - Firebase

TL;DR: GraphQL shines where Firebase falls short. Powerful data modeling, flexible and efficient queries and the open specification are all essential parts of GraphQL that are lacking with Firebase.

Powerful Data Modeling

Firebase has received a lot of criticism based on its limited data modeling. Basically, your data is structured as a single, huge JSON that states the same data multiple times. What seems convenient at first results in unmanageable client code whenever you need to update data, as you have to keep track of all the references to the same data manually.

The data structure used in GraphQL on the other hand is very intuitive and familiar to think about, as it is modelled as a graph. Using the IDL syntax we can easily describe our data model, called the GraphQL schema. For a Twitter app, the schema could look like this:

type Tweet {
  id: ID!
  title: String!
  author: User! @relation(name: "Tweets")
}

type User {
  id: ID!
  name: String!
  tweets: [Tweet!]! @relation(name: "Tweets")
}

Here we defined two types Tweet and User with some scalar properties and also a one-to-many relationship between User and Tweet. Single data items are referred to as nodes - and a user node can be connected to many tweet nodes. This data structure is both simple and flexible, other than the JSON approach from Firebase.

Flexible and Efficient Queries

The flexible query capabilities of GraphQL is one its main benefits. Queries are hierarchical, that means you can specify data requirements that mirror the graph structure. In our Twitter example, we might have a query to fetch all users and their tweets:

query {
  allUsers {
    id
    name
    tweets {
      title
    }
  }
}

Note that we can freely include or leave out fields that we want to query, and we can even query across relations. This means that we neither need to do multiple queries nor are we querying unneeded data - making GraphQL queries extremely efficient.

Adding query arguments to the mix we can add features like a custom order or filters to obtain a powerful GraphQL API.

All of that is simply not possible with Firebase.

Realtime Data

Firebase's realtime capabilities have made it so popular - but since the GraphQL community is about to reach a consensus regarding realtime, Firebase's biggest advantage is nullified as well. I recommend this video tutorial on GraphQL subscriptions to get a better understanding of underlying concepts

Conclusion

So, to answer your question: GraphQL surpasses Firebases in most aspects making it the preferred choice.

If you're interested in GraphQL, I encourage you to check out Graphcool that combines the strengths of GraphQL with powerful features like built-in authentication and flexible hooks to AWS Lambda or other serverless functions to implement custom business logic.

Disclaimer: I work at Graphcool :)

Solution 4 - Firebase

You can use graphql & firebase locally. All the heavy lifting can be done in a webworker to avoid blocking the UI when resolving the request.

One word about the "many roundtrips necessary to resolve the request" : if you don't mind about the data transferred, that's not so much of a big deal since all the "roundtrips" are merged in the same socket frame. But if you do want to avoid big frames, you just have to put a little dataloader in front of your firebase database.

For realtime updates, you only have to subscribe to realtime events from firebase and send them to the webworker to convert them into real graphql subscriptions that can be resolved through your schema.

You can find more information on this very issue on my medium post : “Client-side only” realtime web applications with Firebase, GraphQL and apollo-client 2.0

Hope that helps !

Solution 5 - Firebase

Do you have to use firebase? There are services more specific to GraphQL that may offer what you're looking for. https://scaphold.io is a YC Fellowship Company that looks particularly promising and gives you a firebase like experience but it is powered by GraphQL.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionomgjView Question on Stackoverflow
Solution 1 - FirebasevinceView Answer on Stackoverflow
Solution 2 - FirebaseNicoView Answer on Stackoverflow
Solution 3 - FirebasemarktaniView Answer on Stackoverflow
Solution 4 - FirebasePierre CriulanscyView Answer on Stackoverflow
Solution 5 - FirebaseMichaelView Answer on Stackoverflow