Still waiting for someone excited to use this in production and become a maintainer!
If this is something you’re interested in, I’d be happy to walk you through building an integration.
Still waiting for someone excited to use this in production and become a maintainer!
If this is something you’re interested in, I’d be happy to walk you through building an integration.
Well, in fact, the reason for my question is that I’m starting a new project and I would like to use it in production, but I’d need it really soon, like in a next 2-3 weeks (for a pilot phase).
If you think it’s possible to do a usable version within said time frame, than I’d be willing to take that responsibility and would appreciate if you could help me out.
I think so - most of the complex stuff is inside the Apollo Client core, and the react/angular integrations are relatively thin. In fact, we’re actively trying to move more in this direction so that the integration layers are as small as possible.
I think you could get really far in 2-5 hours. The hard parts are (1) designing it to feel great to Blaze users, and (2) maintenance, bug fixes, and keeping up with new versions of Apollo Client.
How can we start? Perhaps I should create a repository for it, then we can discuss a design. Have you used Apollo or GraphQL before with React or Angular?
Please, anyone doing this integration, put much time and focus on this. I like this approach, but if this doesn’t work somehow, please have a smart interface, one that fits in with its current constructs.
Do you have any specific suggestions?
I won’t be of any use, as I don’t know a thing about Apollo or what the calls would look like. But if you don’t mind, I wouldn’t be shy about discussing how we should be thinking about this.
Very rough and simple example (please provide a better one if you like):
But typically I have a subscription in the onCreated:
var instance = this;
var reactiveVar = Session.get('reactiveVar');
var sub = instance.subscribe("persons", reactiveVar);
if (sub.ready()) {
// do something
}
Then in my helpers:
return persons: function () {
var cursor = persons.find();
return cursor;
},
or sometimes I’ll just get one value from the record (in helpers):
return fullName: function () {
var person = persons.findOne(userId: Meteor.userId());
return person && person.fullName;
},
Then in the template:
<div>
{{#with persons}}
<p>Authored by {{fullName}}</p>
{{/with}}
</div>
<!-- or just the value -->
<div>
<p>Authored by {{fullName}}</p>
</div>
According to your example we’d had something like the following:
{
person (id: "5") {
title,
first,
last,
address {
street,
...
}
}
}
I don’t know where something like this query would live.
This replaces both the subscribe
and the find
.
In the Meteor Guide, we’ve been saying: “It is best to place the subscription as close as possible to the place where the data from the subscription is needed.” https://guide.meteor.com/data-loading.html#organizing-subscriptions
GraphQL lets us embody this idea much more directly. So instead of:
Meteor.subscribe('x');
x = X.find({ x: true });
You get to do:
x = client.query(`
x {
field1
field2
}
`)
This gives you a lot of great benefits:
None of the code snippets you posted are surprising - that’s exactly what we recommend in the Guide as well, and I think the best we can do is carry those recommendations over, and add some stuff that takes advantage of GraphQL’s unique features too.
So… nothing about the subscription in the onCreated… we’d place the query in the helpers instead?
In the helpers:
return persons: function () {
var object = client.query(`
persons {
field1
field2
}
`)
return object;
},
Then in the template?
<div>
{{#with persons}}
<p>Authored by {{fullName}}</p>
{{/with}}
</div>
Yeah I think doing it in the helper would work! So I guess it’s the same as before, you just skip the subscription step.
So does this mean we should make a distinction between returning a cursor and a record for Blaze template consumption?
return cursor from helper:
return personsCursor: function () {
var personsCursor = client.query('
persons {
field1
field2
}
')
return personsCursor;
},
return just a field from helper:
return personFullName: function () {
var record = client.query(`
persons { fullName }
`)
return record;
},
And where is reactivity handled, within Apollo? So in the future, where would we turn off and on reactivity? For example, would we pass a isReactive on a field by field basis or something else?
return cursor from helper:
return personsCursor: function () {
var personsCursor = client.query('{
persons: {field1, field2}, reactivity: {field1: 1, field2: 0}
}')
return personsCursor;
},
Sounds good! Let’s start with a repo and some “quick start” docs to get me up to speed.
Unfortunately I’ve been too busy to fiddle with any of GraphQL and React/Angular beyond a few quick hacks out of curiosity, but I’m gonna dive into docs now so we can discuss it further.
I’m gonna dive into docs now so we can discuss it further.
This is probably the best thing to read: http://dev.apollodata.com/react/
We just rewrote it from scratch so it should be pretty complete.
So does this mean we should make a distinction between returning a cursor and a record for Blaze template consumption?
There is no concept of returning a “cursor” or “field” from GraphQL.
And where is reactivity handled, within Apollo? So in the future, where would we turn off and on reactivity?
Apollo Client has two methods: query
and watchQuery
. The first is a one-time fetch and the second is reactive. There’s no per-field reactivity right now and probably won’t be in the near future.
There is no concept of returning a “cursor” or “field” from GraphQL.
So this is where the integration would come in. Blaze is expecting something else?
Blaze is expecting something else.
I disagree - There’s no way Apollo will look like Minimongo, because it’s completely different. We need to find something that’s a natural way to use GraphQL together with Blaze, it’s going to necessarily be different from what we had before.
Blaze is expecting something else?
I disagree
Meant to be a question, not statement of fact.
I’m trying to grasp the obvious here…
There’s no way Apollo will look like Minimongo, because it’s completely different
So without a Apollo + Blaze abstraction, any query using straight Apollo client inside the helper would be a straight Rest API call out to the Apollo client, and it will return a raw Json object?
We need to find something that’s a natural way to use GraphQL together with Blaze
It would be natural to have the queries inside the helpers I think. The Apollo + Blaze client we are discussing will abstract out the calls to the Apollo client correct, and this will be all its doing (it won’t be modifying Blaze itself)? And there will be no reactivity in the Apollo client, so there’s no way this abstraction will have reactivity. Therefore all these queries will one once on Temple render?
It would be natural to have the queries inside the helpers I think.
Agreed!
And there will be no reactivity in the Apollo client, so there’s no way this abstraction will have reactivity.
Apollo client is reactive. We just need a really thin bridge to convert an observable into a Tracker-reactive function, which should be about 3 lines of code.
Anyway, let’s see what @miro comes up with, then we can talk in much more concrete terms.
Agreed! I’m excited to see what comes out of this.
As an aside, if people here are looking for well-constructed patterns that maintain the Blaze split of data/view, check out this post. No helpers, access to template-scoped functions and data, and an overall (in my opinion) cleaner implementation of some of the main pieces of blaze. Since adopting this pattern, it’s hard to look back.
Also – Seeing posts like this, incorporating incremental dom, etc. is amazing to see, especially in light of how many times I recall seeing that “blaze is dying”…
Please post concrete design ideas here:
https://github.com/apollostack/blaze-apollo
CC @miro
Please make sure you have an in-depth understanding of GraphQL, Blaze, and Tracker, and intend to use this integration if it’s built, before proposing designs.