Should You Make The Switch? Using Apollo Inside Your Meteor App
When Meteor first launched back in 2012, it was a pioneer in many areas: whether it was the build tool, front-end library, state management, or data layer, the framework could hold its own against any alternative out there.
Four years later though, things are different: React has taken over the view layer, Webpack is the dominant bundling tool, Redux takes care of managing state… Pretty much every part of the Meteor stack now has a more popular independent competitor.
Every part that is, except for the data layer.
A New Mission
Facebook did introduce a promising technology called GraphQL, but GraphQL was only a specification, not a ready-to-use solution. And Facebook’s own implementation, Relay, was receiving mixed reviews.
So the Meteor Development Group had a brilliant idea: instead of waiting for someone else to come up with the perfect GraphQL data layer and disrupt Meteor’s final stronghold, they would piggy-back on their years of experience in that domain and build it themselves. And thus, the Apollo project was born.
So what does this mean for your average Meteor developer? Should you use Apollo from now on? And should you be thinking about porting your current apps? Read on to find out.
The Benefits of Apollo
Let’s start by examining what Apollo brings to the table. The first benefit of Apollo is the amount of control it gives you over your data. Unlike Meteor’s all-real-time-all-the-time model, Apollo gives you fine-grained control over how and when your data should be synced from the server.
You can choose to only sync it manually, sync it at a pre-defined interval, or even emulate Meteor’s real-time sync using Apollo subscriptions. And as you can imagine, requesting data less frequently from your servers can also have big performance implications.
The second benefit is the fact that Apollo uses GraphQL. Many smart people consider GraphQL a superior alternative to REST because of its flexibility: instead of setting up multiple API endpoints each offering a fixed range of data, you define your entire app’s data schema and then let each client specify exactly what data it needs, down to the individual object fields.
The third benefit is that unlike Meteor and its tight integration to MongoDB, Apollo is database-independent. You can use it with MongoDB, but you can connect it just as well to MySQL, PostegreSQL, or even external APIs.
Finally, the fourth and possibly most important benefit is portability. Unlike publications and subscripitons, using Apollo doesn’t tie you down to Meteor, and makes each pieces of your stack much more independent. This is something to keep in mind if you ever want to migrate out of the Meteor ecosystem.
Case Study: Nova
The reason I wanted to write about this topic is because I recently migrated a fairly large app myself, Telescope Nova.
Altogether the migration took about two months, although to be fair it also involved a lot of unrelated codebase refactoring and rethinking.
That being said, if you’re starting from scratch I would probably budget at least 6 weeks of time to learn GraphQL and Apollo, migrate your app, and work out any kinks.
Apollo vs Meteor
First, it’s important to understand how Apollo fits in the Meteor ecosystem. In practice, Apollo replaces the following components of your app:
- Publications & subscriptions
- Meteor methods
This can have pretty drastic consequences. For example, in the Meteor land we’re used to luxuries like automatically synced data, or being able to write database queries using the same syntax on the client and server. On the other hand, Apollo gives you a lot more control, but also requires you to write a lot of this logic yourself.
To help you understand whether the trade-off will be worth it or not, let’s take a deeper look at how each area of a traditional Meteor app would work in an Apollo app.
In Meteor, data loading works through publications and subscriptions. On the server, you declare a publication that makes a subset of a database collection available publicly, while on the client you subscribe to it to load its data into Minimongo.
The pub/sub system has the following important characteristics:
- It’s real-time by default.
- It’s tied to the database (your database defines the shape of the data you publish).
- It (usually) uses multiple publications.
- It’s isomorphic (same Mongo API on the server and client).
By contrast, data loading in Apollo is very different:
- It’s not real-time by default (although subscriptions can change that. More on this in an upcoming article!).
- It’s not tied to the database (you can give any shape you want to your published data).
- It uses a single GraphQL endpoint.
- It’s not isomorphic (there is no API in common between server and client).
In practice, when migrating from pub/sub to Apollo, the first three points are mostly a concern if your app depends heavily on Meteor’s real-time aspect. The lack of an isomorphic API, on the other hand, can have big consequences for all codebases, especially when it comes to mutating data.
In “traditional” Meteor, everything is based around the assumption that your data comes from a MongoDB database. So when a new document is added to a collection, Minimongo knows which collection it belongs to, and which cursors to update.
Apollo on the other hand only deals in single documents, and doesn’t have any concept of a “collection”. This means that whenever a new document is inserted, you have to make sure to update the queries that should contain it manually.
Apollo includes a few mechanisms to achieve this, such as triggering a callback after a mutation, running a query reducer after every action, or even refetching the entire query. But in any case, updating the queries that govern your container components will have to be handled explicitly.
Apart from this important caveat, Apollo mutations work similarly to Meteor methods, with the difference that (in keeping with the overall GraphQL philosophy) the client can define the shape of the data it needs the mutation to return (whereas with pub/sub this is handled automatically by the publication you’re subscribed to).
Another big factor to consider when looking at Apollo is how it deals with Meteor’s Accounts system.
Right now, the truth is that it mostly doesn’t. Despite some early attempts like meteor-apollo-accounts, most apps will probably end up keeping the traditional, DDP-based Meteor Accounts system at least for the near future.
Beyond that though, new promising projects like the js-accounts initiative could provide a path to a global framework-agnostic GraphQL accounts system. And of course, Passport.js is also an option if you’re able to migrate your Meteor accounts.
Meanwhile In Meteor Land
To make the choice even harder, the Meteor ecosystem hasn’t been standing still either. You can fine-tune the way Livedata works for better performance, and there are also attempts to use Redis to improve Meteor’s oplog tailing to help with scalability.
Finally, if you’re after a more GraphQL-like syntax, Grapher offers just that while remaining fully compatible with Meteor’s original data layer.
To sum things up, migrating a Meteor app from pub/sub to Apollo does require a sizable amount of work, both because you’ll need to migrate existing parts of your app, and also because you’ll need to create new parts (especially when it comes to handling data on the client) from scratch.
So should you make the switch or not?
To be honest, it’s probably not worth it for self-contained, fairly static apps. If your codebase works fine as it is, and you don’t foresee any major evolutions in the future, then keep what you have now.
If on the other hand you’re working on a growing, evolving project and would like the option to one day migrate out of the Meteor ecosystem, migrating is a safe bet: even if Apollo somehow doesn’t work out, GraphQL isn’t going anywhere. And decoupling the client/server in general is probably a good idea for larger apps.
As you can see, there is sadly no one-size-fits-all answer here. But don’t despair: over the next few weeks, Tom and I will keep writing more about our Apollo experiences, and hopefully this will help nudge you in the right direction!