Quick win: Defer loading secondary data
Two tips for speeding up the perceived performance of your UI
Summary
The model()
hook on routes can get big and slow down initial rendering. To fix this, identify secondary data and defer loading it until after the initial render.
We looked at two easy ways to do this:
- Move part of the query to
afterModel
, but don't return it (so Ember doesn't block rendering) - Co-locate part of the query with a component that's responsible for the secondary portion of the UI
Removing the expensive part of the query from our model()
hook:
export default Route.extend({
model({ user_id }) {
let include = [
'coverage-group',
'department',
'employee-level',
+ 'employer',
- 'employer.subscriptions.product.supplier',
'geography',
'licenses.subscription.product.supplier'
].join(',');
return this.get('store').loadRecord('user', user_id, { include });
}
});
Running the new query in afterModel
without blocking the UI:
export default Route.extend({
afterModel(user) {
this.get('store').loadRecord('user', user.get('id'), {
include: 'employer.subscriptions.product.supplier'
});
}
});
Co-locating the new query with the <select-product-form>
component:
// select-product-form/component.js
didInsertElement() {
this._super(...arguments);
this.get('loadData').perform();
},
loadData: task(function*() {
return yield this.get('user').load('employer.subscriptions.product.supplier');
}),
{{! select-product-form/template.js }}
{{#if loadData.isRunning}}
{{#ui-button style="small disabled"}}
Add Product...
{{/ui-button}}
{{else}}