Skip to content
This repository has been archived by the owner on Sep 16, 2022. It is now read-only.

Simplified deferred loading for components #406

Closed
matanlurey opened this issue May 24, 2017 · 17 comments
Closed

Simplified deferred loading for components #406

matanlurey opened this issue May 24, 2017 · 17 comments
Milestone

Comments

@matanlurey
Copy link
Contributor

matanlurey commented May 24, 2017

Surprise! We have an experimental feature currently being validated, and we're ready to commit to landing it formally in 4.0.0. We've heard a lot of feedback that users wish deferred/lazy-loading was easier, even when not using a router.

As of an upcoming release, we've introduced a new "compile-time" directive:

<comp !deferred></comp>

What !deferred means is that the component that is annotated will not be loaded eagerly, rather, we will load that component's library using Dart's deferred loading, and it will be loaded and initialized asynchronously after initial load.

Example use

import 'package:angular2/angular2.dart';
import 'expensive_comp.dart' show ExpensiveComp;

@Component(
  selector: 'my-comp',
  directives: const [ExpensiveComp],
  template: r'''
    <expensive-comp !deferred></expensive-comp>
  ''',
)
class MyComp {}

Caveats

  • You can only annotate a component, not an HTML element or a directive.
  • Because !deferred is a built-in directive, it won't go in your directives: [ ... ] list.
  • It can't be used in conjunction with a structural directive (i.e. *ngIf) but you can do this:
<!-- When a panel is expanded, lazy load and show <expensive-comp> -->
<template [ngIf]="isPanelExpanded">
  <expensive-comp !deferred></expensive-comp>
</template>

Some of this functionality works already, but we aren't committing it formally with documentation and an exact contract or better error messages until 4.0

@matanlurey matanlurey added this to the V4 Beta milestone May 24, 2017
@jodinathan
Copy link

Awesome!
Seriously, this is excellent news

@jakemac53
Copy link
Contributor

nit: !deferred to me reads as "not deferred", which is the opposite of what you are actually doing. Maybe in angular context it makes sense though idk :D.

@matanlurey
Copy link
Contributor Author

nit: !deferred to me reads as "not deferred", which is the opposite of what you are actually doing. Maybe in angular context it makes sense though idk :D.

Fair enough. We haven't committed to this exact prefix (though that's what we have parsed so far). Open to reasonable suggestions/alternatives.

@jakemac53
Copy link
Contributor

Fair enough. We haven't committed to this exact prefix (though that's what we have parsed so far). Open to reasonable suggestions/alternatives.

What about ngDeferred?

@matanlurey
Copy link
Contributor Author

Fair enough. We haven't committed to this exact prefix (though that's what we have parsed so far). Open to reasonable suggestions/alternatives.

What about ngDeferred?

One confusing bit is this isn't a directive, so we want to differentiate the syntax somehow to make this clear.

@jakemac53
Copy link
Contributor

:deferred, or #deferred?

@jonahwilliams
Copy link
Contributor

I'm okay with !deferred. You could probably pick any number of symbols which aren't already used by the template syntax though.

Some more ideas:

@deferred, $deferred,

#deferred would be a template reference however, so I don't think that is a good choice.

@jodinathan
Copy link

jodinathan commented May 24, 2017 via email

@chalin
Copy link
Collaborator

chalin commented May 25, 2017

... this isn't a directive, so we want to differentiate the syntax somehow to make this clear.

@matanlurey, do we really need to have different syntax? E.g. <template> isn't a normal element but it doesn't have special syntax.

@skybrian
Copy link

I like @deferred.

@matanlurey
Copy link
Contributor Author

@chalin:

... this isn't a directive, so we want to differentiate the syntax somehow to make this clear.

@matanlurey, do we really need to have different syntax? E.g. <template> isn't a normal element but it doesn't have special syntax.

Sure, we could just do <div deferred>, but is that obvious enough to folks?

@skybrian:

@deferred is an option.

@matanlurey
Copy link
Contributor Author

The community wins, we are renaming to @deferred. 🎆

matanlurey added a commit that referenced this issue May 30, 2017
* Add a series of unit tests to cover various cases.
* Fix a bug that caused prefixes to emit like deflib0.deflib0.
* Fix a bug where change detection never occurred on deferred components.

Closes #406.

# Only run our own test suite.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=157527765
@wangyizhuo
Copy link

How do I control when this deferred component is loaded? E.g. I want to start loading a deferred component as soon as my main page is rendered.

@matanlurey
Copy link
Contributor Author

The component is loaded ~immediately after first render.

You can always wrap with an *ngIf to have your own precise load:

<template [ngIf]="loadComponent">
  <expensive-comp @deferred></expensive-comp>
</template>

@wangyizhuo
Copy link

Looks like:

<expensive-comp [ngIf]="loadComponent"
                               @deferred></expensive-comp>

will always be loaded and ngIf is ignored.

If

<template [ngIf]="loadComponent">
  <expensive-comp @deferred></expensive-comp>
</template>
```
is used, will deferred chunk still start downloading ~immediately after first render, or after ngIf is true?

@wangyizhuo
Copy link

Ignore my question, found it in caveat: "It can't be used in conjunction with a structural directive".

Does this mean the deferred component cannot have any input?

@leonsenft
Copy link
Contributor

@wangyizhuo Caveat aside, there's a mistake in your first example. Structural directives manipulate the DOM and only work on <template> elements, so your first example wouldn't work anyways. For convenience, the asterisk * notation can be used on structural directives so they can be placed on arbitrary elements, which then desugars into the <template> syntax.

<expensive-comp *ngIf="loadComponent" @deferred></expensive-comp>

This is unrelated to inputs, which are supported for deferred components.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants