Idea: Caching Meteor method results on client


#21

I do something similar - data over methods, cached in localstorage (through Ground:DB)

I use a local package with a factory for creating a collection. Using a factory from a package let’s me provide a separate method for server and client from one import location (import { makeCollection } from 'meteor/pixstori:collections'). Then I use that to create my collections. On the server, I just create a standard Meteor Mongo collection. On the client I create a Ground:DB collection, which uses minimongo and localforage.

To bridge the data, I grab data over a method, instead of pub/sub, and simply do a brute force replacement (Ground:DB doesn’t allow updating full documents, so I just delete and re-insert by ID). I do this mostly on componentDidMount, in a data provider component. I also have a second method set up for garbage collection - sends a list of IDs from local through a method, and gets back any IDs which are missing from the server - those are nuked in local. The server is always the single source of truth. Syncing is handled by normal component lifecycle in most cases, but any sort of more robust syncing can be implemented here. In some cases, after (or before for optimistic updates) a form update over a method, I do a little syncing in a Flex like action hook.

I really like having my local mini-mongo to feed my view tree. It’s super easy to work with. At some point I’ve been planning to move to SQL (denormalization is like writing to a cache - it’s the wrong approach in the data tier, IMHO, but well suited for local/offline document storage!) and apollo on the server, and only use Mongo client side through Ground:DB, and the same patterns I’ve already described above.

If your query really is the slow part of a tree re-render, and there’s something triggering the query to re-run, nothing I’ve described will help with that. But if it’s the react tree rendering itself, there are ways to optimize that. In thinking about it, there should be ways to avoid having that method called a lot using React’s optimization techniques, instead of writing your own caching system at this level. You can use PureComponent or implement a more robust shouldComponentUpdate specific to your needs. You could even hoist your data provider, and use the context api to deliver the data down the tree.