Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout JS and large models

I am trying to figure out the best ways of using KnockoutJS and I need your advice.

My view model contains a set of "documents" each of them has a set of "values". Each "document" is rendered as a separate table using the following template:

<div data-bind="foreach: Documents">
        <table data-bind="foreach: Values">
            <tr data-bind="foreach: $data">
                 <td data-bind="attr: {colspan: Colspan}">
                    <label data-bind="text: Label"></label>
                    <br />
                    <span data-bind="html: Value"></span>
                </td>
            </tr>
        </table>
</div>

Everything works fine except when view models are big.

For example, if the size of a view model is about 1 megabyte (and contains 80 documents with 60 values each) then the rendering takes more than two minutes on my machine.

I am wondering if there is a way to significantly improve performance... Or will it be faster to give up on Knockout and just build html on a server side and just push it to the browser...

Rendering "just" 300kb view model takes close to 30 seconds.

The "documents" are defined by users, so there are even >2 megabytes scenarios (I don't know why do they do it).

Does anyone have an experience with large view models in JavaScript?

like image 633
Alexey Raga Avatar asked Oct 08 '22 08:10

Alexey Raga


1 Answers

With your current requirement of being unable to lazy-load (load on demand) data, you are pretty limited.

SERVER SIDE HTML

Generating the HTML server-side will be the fastest method. But even so if the model is huge there's going to be a delay. Consider downloading a 5MB HTML file, it's going to take your browser some time to parse and render something so large.

STILL USE KNOCKOUT JS

If you want to still use your Knockout JS framework then my best suggestion is put each Document in an IFRAME. This isn't really recommended and would put extra load on your server, but if implemented correctly would speedup your user experience.

www.mysite.com/view/1

<div>
    <iframe src="www.mysite.com/view/1/document/1"></iframe></div>
<div>
    <iframe src="www.mysite.com/view/1/document/2"></iframe></div>
...

www.mysite.com/view/1/document/1

<!-- Just the single Document template -->
   <table data-bind="foreach: Values">
        <tr data-bind="foreach: $data">
             <td data-bind="attr: {colspan: Colspan}">
                <label data-bind="text: Label"></label>
                <br />
                <span data-bind="html: Value"></span>
            </td>
        </tr>
    </table>

The client browser will initially get all the HTML containing all of the IFRAMEs it will dispatch requests for each asynchronously. Each single Document request will be rendered using Knockout JS in its own frame asynchronously.

To improve the user interaction you could even set up load events on the IFRAMEs. The load event could either re-size the IFRAME so there's no scroll bar, or extract the HTML from the IFRAME and replace the IFRAME element with the extracted HTML.

like image 137
Louis Ricci Avatar answered Oct 12 '22 12:10

Louis Ricci