cc @jwx @Sayan751
Hello @bigopon. Good to see you on this project still after all of these years!
I had already tried what you suggested…with one exception: in the code fragment you provide, you actually declare dependencies with the dependencies
property. That gave me food for thought. When I do the following in SomeComponent
, and use @customElement
explicitly, not only do I see NestedComponent
rendered inside of SomeComponent
correctly, but I also see no memory leaks:
import { customElement } from 'aurelia';
import template from './some-component.html';
import { NestedComponent } from './nested-component';
@customElement({
name: 'some-component',
template,
dependencies: [NestedComponent], <== I hadn't tried this before
})
export class SomeComponent {
constructor() {}
}
I do have to use @customElement
in every case, though. If I comment out @customElement
, then that component leaks. I can create, and then resolve, the issue at will by going back and forth with @customElement
commented in and commented out.
What’s not clear from the documentation, if indeed it was your intention in the design of the framework, is that dependencies must be declared in the decorator when taking over with @customElement
. Importing them in the template will not work. Global registration only partially solves the problem in that the nested component will render, but will still cause its parent to leak.
In the post I made here, Nested & dynamic custom element composition - #13 by estaylorco, do I answer your question? (I wasn’t aware if you had seen it).
I still think this might be a bug. We should be able to use convention without fear of a leak. I’m not averse to declaring my dependencies in the component—might even be clearer than doing so in the template—but others may not feel that way.
Does this help?
UPDATE
(Further investigation beyond what I described above).
I’m not sure if what I’m seeing is a leak, but if I use a nested component concretely (as opposed to with dynamic composition), I see 2 detached instances of the component (in this case, <nested-component>
) in a heap snapshot. It does not, however, cause the enclosing view to leak. In other words, some-component
and SomeComponent
do not show up in the heap snapshot.
This leaves behind 2 detached instances of the nested component (from some-component.html):
<div class="some-component">
<!-- <au-compose component.bind="currentView"></au-compose> -->
<nested-component></nested-component>
</div>
What’s interesting, though, is that if I switch to dynamic composition using au-compose
, the nested component does not show up at all in the heap snapshot, much less detached, and neither does some-component
or SomeComponent
.
Uncommenting the compose in some-component.html so that we have this:
<div class="some-component">
<au-compose component.bind="currentView"></au-compose>
<!-- <nested-component></nested-component> -->
</div>
where currentView
occurs on the component in the constructor this way:
import { customElement } from 'aurelia';
import template from './some-component.html';
import { NestedComponent } from './nested-component';
@customElement({
name: 'some-component',
template,
dependencies: [NestedComponent],
})
export class SomeComponent {
constructor() {
this.currentView = NestedComponent;
...
}
}
does not leave behind the nested component or the enclosing component in any way in the heap snapshot.
Just a footnote: Switching to local imports in the template (as opposed to defining them at the dependencies
property of @customElement
) does not resolve any of these issues. In fact, if I don’t declare dependencies in @customElement
, nested components aren’t rendered.