-
-
Notifications
You must be signed in to change notification settings - Fork 419
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HTML renderer for Server-side / isomorphism #34
Comments
I was just about to raise an issue to discuss this. You can stringify a virtual-dom tree: https://github.com/alexmingoia/virtual-dom-stringify |
To share a bit what I have in my mind, in the server a DataFlowSource is built for the incoming request, which will be fed to the whole data flow system, and the response is asynchronously available through an HTMLRenderer, created with In the client-side, the client DataFlowSource will be fed to the same data flow system (in essence, this is app.js), and the Renderer will be the default one |
Perhaps we could start by working on the server side story, and then work on making the library work in an isomorphic way. |
Yes, but to make the server side "make sense" we need to have at least two pages, because the server needs to process the request and make an appropriate response. If we had one page, then server side rendering would be just about providing one static html that contains cycle.js app, and that is a no-brainer with what the framework already provides. I've done routing with cycle.js (in a closed source project), and it's not complicated. It is outlined here. So we need first that multi-page example, before putting it in the server. |
Has any progress been made on this? |
@OliverJAsh not yet, but I have been doing preparations. I've been discussing the matter with some people (beyond GitHub), and keeping it in mind whenever I implement current features. The plan is to implement The framework is evolving quickly, so I believe I'll be working on server-side rendering soon. The priority at the moment is to build features that bring breaking changes. Those need to come before as early as possible. |
|
Raynos/mercury#55 related |
+1 for this! |
I suppose to make all isomorphic the target runtime will be node/iojs? |
One core problem with the isomorphic story is deciding when the app is done requesting its initial data from all over: that's the point where you call it a day, serialize everything and send the UI down (the "isomorphic halting problem", if you will :). Do you have ideas on how to solve this in Cycle for specific cases? For the general case? Very interesting stuff! |
Yes, the "isomorphic halting problem" IHP (I like the name 😄) is the most important one to solve for the isomorphic story. The draft solution I have in mind will probably exploit the fact that all Rx Observables can have a "complete" event after it emits events. So one naïve solution is to apply combineLatest on all Views, then use last to get the final virtual tree on the complete event (notice the vertical line marking the complete). Most of the obstacles against this simplistic approach will probably be discovered while building, so I don't know yet. |
I was under the impression that Cycle Models would (under normal operation) never complete, though, so that the Views can keep on observing them..? Would there thus need to be some special condition on some server-side-aware Models that would allow them to complete, whereas on the client-side they wouldn't? It's very likely anything requiring server-side interaction on the client will want to be aware of where it's running, though, so that might be a nice place to fork at. |
I can see a situation where Cycle models would want to complete on the client side. A component could finish its useful lifespan, for instance an "Add item" component - when the user clicks add and all validation passes, the component's useful lifecycle is through, and it's final emission of the information about the item to add could be exposed, and its observable chain shut down. |
Very good point @jareware, I was actually supposed to mention that, but forgot. var Model = Cycle.createModel((InitialConditions, Intent) =>
({
name$: Rx.Observable.merge(
InitialConditions.get('name$'),
Intent.get('changeName$')
)
})
}); An Intent on the client-side is naturally an infinite stream, since the user could theoretically interact with the user interface for an indeterminate amount of time. On the server-side, though, we know for sure there is no ongoing user interaction, so we can set all Intent streams to empty. Actually the infinite nature of Intents is contagious: they make Model streams become infinite, and View streams (derived from Model stream) become infinite too. "User interfaces as an infinitely recursive experience" is one theme I want to explore in an upcoming conference presentation. So for the example above, on the client-side, InitialConditions.name$ is finite (has a complete event) and Intent.changeName$ is infinite (no complete event), hence the resulting merge will be infinite. On the server-side, both InitialConditions.name$ and Intent.changeName$ are finite, so the resulting merge will be finite. Check this rxmarbles for the semantics of merge with complete events (drag around the complete marker). The problem is then just figuring how to replace Intents on the server-side so that they always return an empty completed stream, while trying to minimize as much as possible the amount of changes a developer needs to do on his app codebase. |
Done in v0.20.4 |
Epic. :) |
Nice! |
Do we have any examples of this? Would make a good addition to https://github.com/vic/awesome-cyclejs! |
Has this been removed since? I can't seem to find this functionality in the current version. |
oh right, thanks |
References: https://github.com/yahoo/flux-examples, https://github.com/reactjs/react-page, https://github.com/yahoo/flux-examples/blob/master/todo/server.js
The text was updated successfully, but these errors were encountered: