hallgren / reactize-todo

todomvc in reactize
5 stars 0 forks source link

Feedback #1

Open christianalfoni opened 9 years ago

christianalfoni commented 9 years ago

Hi @hallgren !

Just wanted to first tell you that this is a very creative and cool idea. It is very interesting how you give all the responsibility to the server and still have optimized DOM handling. The feedback here will be more questions about challenges that I think might occur, but that is not to take the motivation out of the project. It is very cool :-) And in advance you have to excuse me if I have misunderstood anything.

  1. All frameworks, tools an solutions have different areas of use, but there is one very common concept on the web and that is: "optimistic updates". I do not quite see how you would be able to pre-update the browser to give that "instant feel" which is kind of a big deal these days
  2. When updating a list I believe that the backend will always send the complete HTML of the list whenever an element is added/removed/changed? That will be quite a bit of traffic over the wire if you have like a table
  3. One good thing about the modern web is that the backend becomes stateless. The backend does not have to know that f.ex. "user1" is currently at this page. I do not have any examples, but I fear that you would have to bring back a lot of state to the backend
  4. When f.ex. clicking the "select all" you should both change the HTML of that checkbox and of course the list, to ensure the state of the application. What I try to point out is that a click might require rerender in different parts of the application, causing it to probably need a complete rerender on most changes
  5. To do a diff you seem to grab the html from the existing DOM. It would be better to keep a reference to the previously received HTML from the server and diff it with that instead?

This is what I got so far :-) I think this kind of solution definitely has its use, though as a general framework there is an issue with perceived performance, meaning that the GUI does no instantly update when you click etc. You are also not able to do all the good stuff with JavaScript in the browser to build a really nice UI it seems.

What could be even cooler is hooking this up to WebSockets and use a text diff algorithm (like GitHub code diff), creating this flow:

  1. I request the initial page and keep a reference to the HTML as a string
  2. I do some kind of form request
  3. The server has a reference to my previous HTML string and creates a new HTML string based on my request
  4. The server does a string diff and produces a small object that points to what text in the string has actually changed (index from, index to, String)
  5. The message is pushed on the websocket over to the client
  6. The client receives the message, changes its cached HTML string using the diff-object and then does what you basically do now in your library

Now there is a lot less going over the wire, also due to limited overhead on websockets, and you do not have to set up HTTP requests all the time. More importantly you could actually when posting the form first pass a message from the server producing a loading indication and disabling the input. Then a message would arrive later opening up the input and adding the todo to the list.

Sorry if this is just annoying suggestions, hehe, but I think you need to speed up the perceived performance of the tool or it will be hard to adopt.

hallgren commented 9 years ago

Hi @christianalfoni and thanks for your feedback =) First of all I would give all the recognition to @ssorallen who is the creator of the initial reactize.js version in the https://github.com/ssorallen/turbo-react project.

Now to your questions:

1: Optimistic updates as I understands it are nothing more than pre-fetched data that could be inserted to the DOM on a specific senario. What reactize does is that it updates the DOM with html formated data their is no constraints in doing additional data fetching and altering the DOM by javascript. Progressive enhancement for the win =)

2: This depends on how you structure the page. I have chosen to use the list of todos as a (reactize area) it could be the case that one todo in itself would be an area and only the html for that todo would be sent on a change. The inspiration of structure the page in areas are taken from Ryan Singer from 37signals/Basecamp => http://vimeo.com/10875362

3: HTTP is meant to be stateless regardless of technique using it. The "user1" should be passed along in or referenced in a cookie to make it stateless. I think the modern web also needs to consider this not only send it as a parameter in the request?

A cool thing with HTML is that it includes the hypermedia part in REST, making the client more dumb just following link and submitting forms. (browser) instead of having to construct the links client side if pure json with only data is used. (There are json-HAL etc. that decorate json with hypermedia, but that is not testable directly in the browser.)

4: You are totally correct. I use a DOM event from the "select all" widget that informs other widgets in the DOM that something has happened. And other widgets that are interested in the event do that they want, in this case re-render themselves. This adds up extra get requests for each widget but also decouple the code in a nice way (I think).

5: What if the element in the DOM has changed from the time the last HTML was fetched. It would create extra DOM manipulations that otherwise would not be needed. Are you thinking of some other case that I'm missing?

The next face could be to try this out with a js framework on top. As I see it reactize speeds up the DOM manipulation on standard HTML requests. This doesn't prevent you from using a js framework on parts that requires more instant UI feed-back.

The journey I have taken are:

  1. pure HTML and page loads
  2. added javascript to only fetch and re-render part of the page.
  3. could be to try out applying a js framework to make some parts feel more snappy.

WebSockets is something I'd like to try out in the future but I haven´t had the use case yet.

I hope I have answered some of your questions and lots of thanks for your feedback

/Morgan

christianalfoni commented 9 years ago

Hi again @hallgren :-)

I will just continue the discussion as it is really interesting. Feel free to just drop out at any minute, you will not hurt my feelings ;-)

  1. By optimistic updates I mean that if you f.ex. add a new todo you do not wait for the backend to create the new todo. You create it in the browser, feeling optimistic about the backend doing its part. That would instantly put the new todo in the list. At the moment it takes a few hundred milliseconds before it is visually added to the list. If the backend gave an error you would have to remove it from the browser again. Is it possible to instantly update the UI with this method or do you always depend on the HTML coming from the backend?
  2. Ah, yeah, I see that one single item in a list could of course be updated directly. Though a removal of an item from the list or addition to the list would require a complete HTML of the list I suppose?
  3. Hm, okay, I see. But how would you f.ex. handle opening a Bootstrap dropdown? That would not work without JavaScript? Would you avoid using libraries and frameworks requiring JavaScript?
  4. Okay, but am I right stating that it would have to wait for a server response before it could show any changes in the UI?
  5. Good point, and I suppose getting HTML from the DOM is not one of the most expensive operations you can do. Though it is more expensive than using React JS only in browser as it will never touch the DOM, except on changes I believe

I would suggest trying this out on f.ex. Backbone. That is a framework that already has a community that would not mind switching the view layer :-)

Good luck with developing!

hallgren commented 9 years ago

Hi mate! Love to discuss stuff like this, so no problem on my side.

1: I miss understood you sorry, to solve this issue you probably need a client side template to decorate and append to the DOM. Another thing that can be an issue is that you have to fake the identifier of the todo that you add and keep somehow track of it on the backend. This can be solved by storing the faked identifier created by the client, but I don´t like the idea that the client is responsible for that. (never trust code that the user can temper with).

Is it possible to instantly update the UI with this method or do you always depend on the HTML coming from the backend?

Sure you can update the UI instantly, capture the event that triggers the save and append something to the DOM before the request is sent. It could be possible to fetch a template of a todo and decorate it with the text and append it to the list and let reactize do its magic on it?

var todo-list = document.getElementById("todo-list")
todo-list.node.appendChild(decorated_todo); 
Reactize.applyDiff(document.getElementById("todo-list"), todo-list);

But its a lot of complexity for the speed increase I think.

2: As in answer 1 on removal of a todo you could remove the element directly from the DOM and on add you could add it to the todo-list element and Reactize.applyDiff on the todo-list element and it should work, I hope ;)

3: It would be optimal to append it after document.ready but that maybe hard if bootstrap requires some specific html structure to work? select2 for example use this technique to enhance select boxes: http://ivaynberg.github.io/select2/

4: Yes if you want to show data that is created by the request.

5:

I´ve never played with Backbone but that may be a winner. I´m having some ideas testing it with angular and its dirty checking. But I haven´t thought it through yet.

Hope to be abel to give this idea some time, thanks

hallgren commented 9 years ago

One other thing I thought of thas is neat with reactize is if you have to translate a site to multiple languages you don´t have to do much to make it work when you do the rendering server side.

christianalfoni commented 9 years ago

Hi again @hallgren!

I will definitely keep all this in mind. It is very exciting stuff. I am actually working on a project now where we have a backend that is the "hive brain". The clients are really dumb. When you click a button or something similar in the client it will send an "action" as a websocket message to the "hive brain" (backend). Then the backend will create a new state for the client. It tells it everything. What page to display, what data is related to that display etc.

What is reeeeeally cool about that is if someone else joins the same session from a different client. They will actually get the same messages back from the backend, changing page, updating the DOM etc. Its kind of a shadow client.

Whats even more awesome is that all messages sent to the clients are "recorded". So if you want to play back what the client did in a specific timeframe you could just replay the messages sent to the client and you would see all buttons clicks, updates of DOM etc. in a live client. Really cool stuff :-)

hallgren commented 9 years ago

Cool, is it possible to send actions from the shadow clients or do they only show whats happening on the main view?

What is "recorded" on the backend? I guess its not the HTML changes =)

Have you looked at Event Sourcing? I´m part of the Sandthorn project, a ruby project that store state changes on objects as events. There´s a Demo page if you want to look how is store data.

christianalfoni commented 9 years ago

They are actually not "shadow clients" by definition as you actually can send actions from them as well. The reason behind the architecture is for administrators to easily go in and help out normal users without having to walk over to them while they are "on the floor" working with the clients :-)

The recordings is the data passed to the clients. The client just generically handles any data passed from the backend. It contains info about what page to display, what to display etc. So when that datastream is played back you will see all page changes, button clicks (which resulted in new data passed from backend) etc.

Hah, did not know about the concept of Event Sourcing, but that is basically what we are doing, yes :-)

hallgren commented 9 years ago

Cool =)

Is it correct that you store the hole page and the hole event that makes the page change? Or how do you handle if the page structure changes?

christianalfoni commented 9 years ago

Hi @hallgren :-)

We only store the event itself. It has basically two properties: "urlState" and "dataState". The urlState tells the client application what page to go to and the dataState is just general data related to the urlState. So if you want to play back the events you just fire up an instance of the client and push out the stored events to that client and it will display what was done.

No worries making changes to the layout, but changes to urlState and dataState could cause a problem :-)