Slow performance with page templates in separate HTML-files



  • Hello,

    I’m use Onsen UI with pure JavaScript version.

    I see performance degradation on the opening page when page templates saved in separate HTML-files.
    For example if from page1 (index.html with <ons-navigator>) I do “pushPage()” for new page2 and this page contains tabbar with 3 tabbed pages (tab1, tab2, tab3) and all of these pages stored in separate HTML-files page2.html, tab1.html, tab2.html, tab3.html - I see big time lag before page opened.
    If all page templates stored in index.html (with <ons-template>) - page2 and its tabs opened very fast.
    As I understand Onsen UI load 4 pages (page2.html, tab1.html, tab2.html, tab3.html) each time when page2 should be opened. After that these files readed and its content appended to DOM in index.html. When I do “popPage()” for page2 - content of page2.html, tab1.html, tab2.html, tab3.html completely removed from index.html and these operations (load 4 files, read, append to index.html) repeated when I want show page2 again?
    Your tutorial contains examples for popup and dialog - these objects can be loaded only once (on first call) and after this I can check existing object via “ID” and invoke “show()” method without template loading.
    Is there any way to use a similar algorithm for pages? This would significantly reduce the opening time for pages in the second and subsequent calls.
    Moreover, could it be possible to load all of the templates on app startup and make the first call fast too?

    Thanks for your help.


  • Onsen UI

    @Sergey Hi! There’s no way right now to cache external files, but this sounds like a nice feature to me. Can you please create an issue on Github and just explain this? I think we can implement it quite easily since there’s already an internal template cache. We just need to save the new files in the cache the first time they are requested and perhaps provide public API to do it manually as well :)



  • @Fran-Diox thanks for reply! Very glad to hear that you are open to new ideas :smile:
    Maybe I can tell you more interesting and more complex idea? :wink:
    I want to use Onsen UI with Meteor for some kind of “realtime” app. For example we can talk about classic tutorial - chat app. Imagine that this app have main page (with list of chats) and page for chat (list of messages). What happen when I tap on chat on main page? Main page go to background and chat page created and displayed. Before chat page will be displayed I should receive list of messages and insert its to the template. At this moment main page invisible but live - Meteor can update page content with changed data. When I press Back button main page displayed again very fast and this page contains actual data. But what happen with chat page? Very sadly - content of this page completely destroyed :cry: So if I want to see this chat again - Onsen UI will load and create this page again, I need to fill template with data again etc. … As we understand it is very common scenario for most apps. Yes it will be cool if you can implement template cache for external HTML files (from my previous question) but it can save maybe only 20-30-40% time to display the page.
    What is my crazy but interesting idea? What about feature for cache of active pages? In other words - don’t destroy page on “popPage()” but only hide? In this case chat page will be hidden but live, Meteor can update content of this page in background and when I tap on this chat again - chat page will be immediately displayed with actual latest data! With this technique we can create ULTIMATELY FAST applications. We need only some additional kilobytes of RAM for each hidden page and some piece of CPU power for background update but we can receive very high speed for apps.
    Yes I know that we have only one “chat.html” template and can have several instances of chats (with Bob, with Alice etc.). So you can use “chat.html” as a key for template cache and maybe some composite key for array of chat pages instances. For example some kind of “templateID”+“objectID”. I.e. for chat with ID=“123” we can have have “chat.html_123” ID for instance of chat page.
    Yes I know that it sound a bit crazy… but what you think about this idea? :wink:


  • Onsen UI

    @Sergey Hi! I understand the situation and this is something that was suggested long ago but at the end not implemented in this way at least. There are few ways to accomplish this right now in Onsen UI:

    • First, by using the bringPageTop method. When hitting ons-back-button you can override its behavior (onClick prop) to perform a bringPageTop with the main page. This won’t kill the chat page. When you want to bring it back into view, just call bringPageTop again. The only “issue” is that, by default, bringPageTop performs a ‘push’ animation but you can write your own animator (there’s already a pop example with ES5) to do it as you want.

    • Use the pageLoader prop to create a new way to load pages. This is probably quite easy to implement. The current pageLoder for navigator is like this. That basically takes a string, reads the file/template associated and creates an element from it. You can do the same and also detect if the argument is already an HTMLElement, for example. In that case, simply attach it to the parent. For the unload method, instead of destroying the page element you can save it somewhere in order to push it afterward.

    There are many different possibilities with the current core library. Perhaps we should add something like this by default but in any case, it’s possible with some little effort :)

    Hope it helps!

    P.S: By the way, you can also use the pageLoader hook to create your own template cache (as mentioned in the op) if you want. But this is something that I think we should add to the core anyway.



  • @Fran-Diox Thanks for answer!

    • I understand about bringPageTop method. This method can solve problem with cache for external files but will be great if you can add cache algorithm to the core. And bringPageTop can’t solve problem with destroyed data because if I have two different chats I need to fill template with appropriate data from scratch each time when I want to display one or other chat.

    • Thanks for pageLoader information! It looks that my idea can be implemented with this property :smile:


  • Onsen UI

    @Sergey In order to make things simpler, bringPageTop assumes there’s only 1 page per template in the stack but this has a workaround as well. You can create new chats with pushPage, which always creates new pages, and then pass an index number to bringPageTop instead of a string. If you save your chat pages somewhere you can easily get the index with navi.pages.indexOf(chatPageElement).



  • @Fran-Diox thanks for new idea!

    As I understand in this case I have to do some manipulations with id attribute for each chat page and modify animation for popPage as mentioned above.
    I will investigate it.

    P.S. Issue for template cache was created ;)