We have a 3.2M LOC application (107 top-level routes, dynamic composition only within each of those routes) that we’re migrating from Aurelia 1.0 to 2.0 (the application actually began back in the days of Durandal, but it was much smaller then). As the first step in the journey, I used npx makes aurelia
to scaffold a default Aurelia application (the first option).
I’m encountering issues that are discussed in this topic by others (minus the dynamic composition aspect). To synopsize, use of the @customElement
decorator prevents the leaking of memory from one route to the next, but sacrifices nested custom elements. Omitting @customElement
and simply running with conventions as discussed by @huochunpeng brings back nested custom elements, but causes the leaking of memory.
I can both cause and resolve these issues at will by going back and forth between @customElement
on each component, and commenting them out. This is true without even using au-compose
.
I’m using the nightly build (“dev”) of Aurelia, but the problem exists even in the “latest” build.
From main.js (configured for direct routing):
import Aurelia from 'aurelia';
import { MyApp } from './my-app';
import { RouterConfiguration } from '@aurelia/router';
Aurelia.register(RouterConfiguration.customize({ useUrlFragmentHash: false }))
.app(MyApp)
.start();
From my-app.html:
<template>
<import from="./t1-shell"></import>
<t1-shell></t1-shell>
</template>
From t1-shell.html:
<template>
<import from="./some-component"></import>
<import from="./another-component"></import>
<a load="/some-component">Some Component</a>
<a load="/another-component">Another Component</a>
<au-viewport></au-viewport>
</template>
There is nothing significant about another-component.html, but some-component.html sports a nested custom element, like so:
<template>
<import from="./nested-component"></import>
<div class="some-component">We're in some component!</div>
<nested-component></nested-component>
</template>
SCENARIO 1: Using @customElement
on each component:
You can see above when I navigate to the some-component
route, nested-component
does not show up. Note the heap snapshots:
Off to the left (offscreen), I’m going to each route, and then making sure the previous route doesn’t show up in the snapshot.
So, then, with the decorator present, we don’t leak. Consider the next scenario.
SCENARIO 2: Commenting out @customElement
You can see above the nested custom element when I navigate to some-component
. However, take a look at the heap snapshots:
So, then, without the decorator, the nested component is present, but we leak from route to route.
(Just to clarify, when I typed in the component name to check the heap, I was typing in the component I navigated away from).
CONCLUSION
This seems like a bug to me (or perhaps I’m missing something). The same is true if I use dynamic composition. But I thought that for the sake of this post, I would keep it simple.