Research about replacing Knockout.js by a virtual DOM with maintaining full back compat
See original GitHub issueWe plan to replace the Knockout.js library by an immutable viewmodel with virtual DOM - something similar to React.
Motivation
Although knockout.js is IMO well implemented and stable library, the UI updating architecture is a bit glitchy - for example, the <select>
binding made us a whole bunch of problems because it’s bound to multiple properties that are not changed atomically and the combination of properties between the changes is invalid, so the control breaks. And even though we came up with few hacks to fix the concrete problems, we can IMHO expect similar issues with other controls.
The second problem is client side performance with larger than the small data set. I have no idea how to make it better with knockout and sometimes it is a real problem. And again, the problem lies in the observable notifications.
Another problem is rendering a template without wrapper tag - although knockout has a concept of virtual elements, the performance is really bad (~6x), not all bindings are supported and HTML comments are sometimes stripped off by compression proxies.
How would it work with DotVVM
I propose migration to virtual DOM architecture. https://github.com/Matt-Esch/virtual-dom library looks lightweight and extensible enough, so let’s talk about it, but all the V-DOM implementations are quite similar, so we can choose the better one later.
ViewModel
The viewmodel would be a simple JS object without the observables that will never mutate (maybe we could use a immutable object library but I think it’s unnecessary). Because the properties can’t be mutated, there is no need to observe the property changes and the viewmodel must be replaced by a completely new one. On the first glance this may look like a crazy performance hit, but as you can reuse parts from the old one, it only does O(number of changes)
allocations, and has completely superior performance in comparison with the change notifications. It would also enable us to track old states for debugging purposes and has IMO much simpler to understand architecture.
Rendering
Now DotVVM controls render HTML enriched by the knockout data-bind
attributes, which is intuitive to read and understand. The knockout binding handlers are tightly integrated with the DOM and are created based on the data-bind
attributes on page init. React and other V-DOM frameworks on the other hand use Javascript functions instead of enriched html to create the virtual DOM and update the real one, which is quite incompatible with the DotVVM control architecture. I think the best solution would be to generate enriched html by a data-render
attribute and generate the render function from that. But there is a bunch of other possible options like rendering plain html with the render function on the server.
Compatibility
Now, you probably think that all this is nice, but this is going to break everything or how the hell do you want to maintain backward compatibility. Of course this change is going to break a lot of things, but I’d like to maintain compatibility for basic usage of the Javascript API and for simple controls. I’d reimplement part of the knockout API for the immutable viewmodel and export ko
global.
dotvvm.viewModels.root.MyProperty().Prop123()
andko.contextFor
- we can return something that will look like a ko.observable and the subscriber will be notified when the entire viewModel is changed.- Knockout Binding Handlers - This is a bit more tricky, but I think it’s possible. As the binding handler is manipulating the DOM directly, it will have to bypass the V-DOM. The mentioned virtual-dom library supports a concept of hooks which are functions ran when the real element is created, so we can apply the old binding handler on it. It will basically update the DOM after it is created from the v-dom. And because the V-DOM only updates only parts that needs to be changed, it should not wipe the handler’s element on every re-render.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:1
- Comments:33 (26 by maintainers)
Top GitHub Comments
I think that we should use React or Preact. All major companies that develop controls support React right now. And being a framework based on React, we’ll look cool!
Really was thinking to use DotVVM as main framework but this issue is making me skeptical. I have just added it to my asp.net core app and was impressed how it integrate seamlessly. I believe not to scare away potential users, you should put a proper roadmap and any other ways of restoring potential/existing users confidence. Nonetheless, kudos for such a great framework.