Okay, so I have this desired architecture for loading data with offline support. Here are the basic requirements, in no particular order:
- I don’t need full reactivity (actually, in this case I specifically don’t want it, since I’ll be doing pagination), and I want something which scales (uses less memory on the server) - and methods are faster anyway (in my experience - WAY faster). Any one of these requirements may not be enough to avoid pub/sub, but I think added up they make a compelling case. So I’ll be delivering the bulk of the data over meteor methods instead of using pub/sub.
- I’ll use Ground:DB on the client side, so I can still write nice queries. All views will be fed from Ground:DB instances - never directly from methods or subscriptions.
- I need to be able to render my React tree on the server, so on the server we’ll need to pull data directly from Mongo Collections, instead of Ground:DB. I figure some kind of sleight of hand should work for this - feed Mongo on the server, and Ground on the client.
- Since we are querying the Mongo sources for data during SSR, it would be a shame to query them again during hydration on the client - so I’m also looking for a way to capture all those queries, serialize it on the server, and hydrate the data on the client from there (like the old
fast-renderpackage does for Blaze).
- Once all this is working, I’ll probably use pub/sub sparingly for some realtime aspects - like subscribing to comments on active displayed content. Even there I’ll probably do something cheeky, like subscribe to one field, and when it’s updated, use a method to grab the full data (to avoid holding full documents in memory on the server). This may be a premature optimization though - I might just use DDP. Not sure yet.
For most of that I already have a solution - yay! But I don’t have a great way to do data hydration - is there a
fast-render like package for React based apps?
One other challenging thing is that for SSR, I need to know what data to wait for (and Ground:DB requires an additional wait step to make sure it’s stores are ready - I found that out the hard way on a previous project). With pub/sub it’s actually relatively easy to make that work by polyfilling the subscribe method (which normally doesn’t exist and throws an error on the server). For pub/sub, we can just capture all the subscription requests on the server, pass those parameters to the client, and do all the subscribing and wait for that to finish, before finishing up subscribe. But I’m not sure how to do that on the client side - but I have a rough idea.
I think I’ll probably do something similar to the subscribe model, but write my own method/actions. Since I’m pulling data from a Mongo Collection on both sides (ground:db on the client) I can leave that code alone. All I need then is an API which contains enough data to populate the Ground:DB collections from a method - and record that on the server to pass to the client, do all the method invocations (or hydrate that data from a fast-render like data source), and then continue on rendering! I think that’ll work. I won’t be able to invoke this action in my tracker wrappers (
withTracker) because it’ll run too often - instead I’ll have to write a Provider component, and do it on mount. This will actually be great - I can then use a Consumer to provide the mongo collections - Mongo on server, and Ground on client! I think this will work!
(Sometimes it helps to pretend I’m talking to someone to work these things out.) Wish me luck!