question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Research about replacing Knockout.js by a virtual DOM with maintaining full back compat

See original GitHub issue

We 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() and ko.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:open
  • Created 6 years ago
  • Reactions:1
  • Comments:33 (26 by maintainers)

github_iconTop GitHub Comments

2reactions
tomashercegcommented, Jan 3, 2018

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!

2reactions
zulqcommented, Jul 19, 2017

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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Creating custom bindings that support virtual elements
Knockout provides the following functions for working with virtual elements. ... An object whose keys determine which bindings are usable with virtual elements....
Read more >
Knockout.js vs React.js vs Vue.js: Features & Performance ...
To track changes in field states, Knockout uses standard Document Object Model (DOM) events and can easily erase your events — or you...
Read more >
Million: less than 1kb virtual DOM that is fast
Carefully handcrafting the minimum number of DOM manipulations for a given state change makes it possible to run much less code than virtual...
Read more >
Virtual DOM for Knockout?
The one place where React blows knockout out of the water, is performance, due to the virtual DOM implementation. Has anyone thought of...
Read more >
Knockout.js Reviews 2023: Details, Pricing, & Features
It is a best way to build complex UI structures. Knockout implements customized behaviors in just a few lines of code as new...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found