ok, next video: https://youtu.be/uxI2XVgdDBU How to build reusable components in Om Next/Untangled. Includes an automated tool for converting HTML to React (in the references github source), tips about Chrome, local reasoning, visual development with devcards, making mutations more usable in IntelliJ (doc strings and "jump to" navigation).
This video helped me a lot to understand how to develop a component in devcards.
Keep up the good work!
good! Glad they’re helping 🙂
@tony.kay do yo do code splitting on routes for large production apps ? (Trying to think about how that will work using the approach in the video on routing)
An approach that I've seen in js react boilerplates, is to have the root app receive the page as a component from the router and just mount it again on the div (leverage react diff), are there any limitations to this approach with om.next/untangled. ?
Seems to be a lot simpler and also easier to implement code splitting on routes.
(defn render-page [component]
(rum/mount (app/app (layout/main component)) (.getElementById js/document "app")))
played with rum
and got a example running like this (on route change, I find the component and then call render-page)
@claudiu That is kind of incompatible with co-located queries. Simpler is a relative term. What you are suggesting is simpler if all you're doing is rendering. Throw in state management, remoting for full stack, dealing with UI updates for components that show the same data, support VCR viewer, etc...Well, then what you're suggesting loses all those benefits and ends up much more complex in the end
This is a challenge of understanding Om Next and Untangled: They're shooting to make your overall life simpler. In isolation (e.g. making a UI) some of the "extras" seem like overhead and extra complexity.
But in the large, these additions enable all sorts of things nearly for free (e.g. no additional incidental complexity in your app)
For example, we've done a tech spike here where, using websockets and Datomic tx events, we can get Meteor-like UI updates on database changes (i.e. subscriptions to UI queries) with almost no client code (a couple of lines to merge the incoming message). The server code is also small (remember the set of IDs a client is interested, and re-send them the result of their query when any of those IDs changes...which Datomic will tell us via the tx events). How cool is that? A framework that is not thinking about meteor-like features getting them as an add-on with no new library code, no complications in the UI (in fact nothing needed in the UI at all), and very little server-side code (see Meteors nightmares with their rendering stack they had to rewrite to make this easier to work with).
So, the higher level concepts and additions serve as a global simplifying mechanism in the large, while initially looking like complications in the small.
@tony.kay, if you remember from my blog post, sounds like you have something like us (but probably better). Could you talk more about how you did the subscriptions to UI queries? Do the subscriptions change based on what is rendered in the client? And is your client merge strategy the same as ours?
For reference you can see these code snippets. https://medium.com/adstage-engineering/realtime-apps-with-om-next-and-datomic-470be2c8204b#.59rwwwp79
@claudiu we independently arrived at the same meteor like benefit without planning for it at all, using Untangled and Om next.
@tony.kay Thank you for the detailed response. Just switched from react/redux and was just trying to see what approaches that are popular in the js community and if they can be applied to untangled
With webpack it's very easy to do code-splitting on routes and I found a lot of resources. For clojurescript it seems a bit more complicated and there seem to be very few resources around. Trying to think of how the routing video would look with google modules code splitting 🙂
The personal project that I'm trying to build with untangled is a mobile first website, a lot of traffic from google, and would really like to optimize on js/css size as much as possible.
@currentoor Really interesting blog post.
@claudiu thanks! But IMHO Untangled is great when your client is “thick” and needs a way to handle complicated state management. If you’re going for short bursts of interaction from google maybe this isn’t the best fit. I could be wrong though.
@claudiu oh, that kind of code splitting. as in: demand loaded code. I think you'd have to use dynamic queries of Om and change the queries. Doable. And yes, if the thing you're trying to build is some tiny thing that can be thrown together without much hassle, you can get stuff done in just about anything.
@currentoor We did a tech spike, not production-ready code. Yours is almost certainly better 🙂
Subscription scheme was like this:
for a query: [:db/id {:thing/x [:db/id :y]}]
you'll get back a tree of data {:db/id 4 :thing/x {:db/id 66 :y "value"}}
a simple recursive walk of this can be used to gather up a set of IDs: #{4 66}
. Let this be subscription-ids
Now notice: The datomic tx log will tell you 4 changed if you ADD/DELETE through a join (because the ref updated), any property change to any entity will also report that entity's id.
So, to "subscribe to a query" is to remember the query + subscription-ids
When you see any of those IDs change via the tx log event:
1. Re-run the query (getting a NEW set of IDs). This is your new subscription-ids
2. Push the new graph to the client (possibly calculate a delta from the prior response to eliminate chattiness). The client knows the query, and query + tree-of-data => app state update and re-render (via merge!
)
3. Update the subscription to use the new subscription-ids
To do this with an SQL database, just make a centralized in-memory component that manages all mutations and track changes there. It is more work than Datomic, but just as easy on the client...basically you just need a way to know that the stuff a client is interested in changed
@currentoor @tony.kay yep. Trying to find the right tools (clojurescript definitely seems to be the right language). I want for some of the public side to load really fast, but untangled should help me out a lot for when the user is logged in (and if the user is logged in on the public website). I guess I'm trying to build something like wikipedia + facebook.
oh, thus the desire to have dynamic code loading...an app that lets others write plugins/portals
@tony.kay yep, do you think for these kinds of apps, untangled might not be the best fit ?
There are all sorts of approaches. So, "good fit" is hard to say
For example, you can put more than one untangled app on a page
or anything written in any other thing for that matter
so composition could just be: write something that targets such-and-such div
at that point it is composable with whatever people want to use
and selling your external devs on cljs and Om Next is probably hard...so just make it flexible
It's a personal project that I'm refactoring now. It's also important that I build a very scalable & maintainable codebase, and choose a solution that I can pitch at my workplace for new complex projects.
Asking these questions, just to get a sense if there are some things that I'm trying to accomplish where I might be working against untangled rather that it helping me 🙂
@tony.kay as usual thanks for sharing!
It seems like our solution is easier to setup but more chatty. We agreed to do a subscription style thing if our simple implementation ever got too slow. So far it’s been acceptable just sending over and merging more data than might actually be needed.
@currentoor thanks for sharing your experience, I am tinkering with something in that neighborhood
@sova you’re welcome! I hope it helps. FWIW we were pleasantly surprised by how easy it was to do this in a reliable way.