Optimizing route templates for Glimmer

One of the highly touted features of ember’s glimmer rendering engine is that, similar to React.js, it does “DOM diffing” and only modifies the actual DOM when it has to. My question is, does this functionality carry through to the route level, i.e. when moving to a completely different route with its own template and component heirarchy, are only the actual needed DOM changes performed?

I ask this because, I am thinking about structuring my app’s routes and their templates in such a way that each is fairly self-contained, i.e. each top level route template contains the main app navigation, sidebar, ect, and I want to make sure that when moving between routes, ember is not having to essentially re-render the entire page and component tree, when only, in most cases, only a small amount of content nested deeper in the template has changed.

Here is a simple illustration of how the route templates are structured:

templates/application.hbs

{{outlet}}

templates/about.hbs

{{app-navbar}}
{{app-sidebar}}
{{#page-content}}
    this is the about page content...
{{/page-content}}

templates/contact.hbs

{{app-navbar}}
{{app-sidebar}}
{{#page-content}}
    this is the contact page content...
{{/page-content}}

The main reason why i want duplicate those common elements (app-navbar component, ect) in each top level template, is that in other routes of the app I want to customize certain aspects of them, or maybe even leave them out completely (on a login route for example). To keep my code DRYer, I may even create a {{#simple-page}}{{/simple-page}} component which renders the entire basic page structure, for those cases where no customization to those global elements are needed.

So, considering that basic structure, will ember/glimmer only update the DOM inside of page-content, or will it re-render the entire DOM from top to bottom when I navigate between routes?

2 Likes

You can simply check if the didInsertElement lifecycle triggers for those components when switching routes. On the first glance I’d say it doesn’t

It doesn’t. We’re developing a fairly ambitious dashboard app where the essential structure of the application is persistent, and using routes to manage high level model control depending on user focus (you can move between saving and browsing checkouts and navigating the search component with high level actions passed up to the route and back down through the controller, which informs where to retrieve the data to pass into components).

Sadly, despite the template being conceptually identical except for passed in values, Ember interprets the distinct route templates as cause for reinitialisating all components and redrawing the application DOM from scratch.

Yeah, I can confirm that from my impromptu tests (monitoring DOM nodes in the Chrome dev tools Elements tab) @barneycarroll is correct, the entire DOM tree is ripped out and rebuilt from scratch when moving between routes, even when the model was the same (in my case there was no model specified) and their templates were exactly the same, with the same component structures.

Since this is the case I guess I will probably need to re-organize my route hierarchy, with more nesting so that at least certain parts of the app can share more of the global app layout/chrome components. It just feels wrong to have the entire page redrawn for each route transition.

How do other people go about this, especially when you have some top-level routes that are vastly different in layout (for example a /login route), such that all your big app layout components (header, navigation, footer, ect) can’t go in application.hbs? Do you just nest things under an additional level of route hierarchy? E.g. instead of routes of about and contact, maybe you have page.about and page.contact or something like that, so that the page.hbs route template is where you put the layout/chrome components?