Lazy loading with Angular Dart
A little known fact: Angular Dart has supported lazy loading since 1.0.
What does lazy loading (called deferred loading in Dart) do for you?
- You can break up your application into small, dependent parts
- It works on every browser — automatically without polyfills
- Use fully typed Dart code — even your deferred libraries are typed
Don’t worry — you don’t need any extra plugins, loaders, build steps, or dependencies of any kind. It’s completely built in (albeit, I admit relatively undocumented — we’re working on that).
This tutorial expects you to already be familiar with Dart and Angular Dart.
Getting started
I use a mix of both IntelliJ and Visual Studio code with the Dart plugin. Both are fine for following this tutorial — they use the Dart analysis server to provide static warnings, auto-complete, and more — or you can use your favorite text editor.
Creating a new project
I could start from a totally empty folder, but I’m lazy — let’s use stagehand to auto-generate the scaffolding for a new Dart project. We’ll get a nice file structure setup in seconds:
If you want to copy-paste the commands I used:
$ pub global activate stagehand
$ mkdir angular2_lazy_example
$ cd angular2_lazy_example
$ stagehand web-angular
Let’s get all our dependencies too:
$ pub get
I then opened angular2_lazy_example
in IntelliJ:
And to preview my application, I run pub serve
:
OK, but this is supposed to about deferred loading…
Yes, yes it is. And it’s just as easy as the steps above. Let’s add a new component, ReleaseListComponent
— it’s going to download a list of the most recent Angular Dart releases, and display them for us.
Creating our new component
Let’s write release_list_component.dart
in our lib/
folder:
import 'dart:html';
import 'dart:convert';
import 'package:angular2/angular2.dart';
@Component(
selector: 'release-list',
templateUrl: 'release_list_component.html',
styleUrls: const ['release_list_component.css'],
)
class ReleaseListComponent implements OnInit {
static const _apiUrl =
'https://api.github.com/repos/dart-lang/angular2/tags';
List<GithubTag> releases = const [];
@override
ngOnInit() async {
final tags = JSON.decode(await HttpRequest.getString(_apiUrl));
releases = (tags as List<Map>)
.map((t) => new GithubTag(t['name'], t['commit']['url']))
.toList();
}
}
class GithubTag {
final String name;
final String url;
GithubTag(this.name, this.url);
}
And let’s add a release_list_component.html
:
<ul>
<li *ngFor="let release of releases">
<a [href]="release.url">{{release.name}}</a>
</li>
</ul>
And a release_list_component.css
:
ul {
margin: 0;
padding: 0;
}
ul li {
color: #1e90ff;
}
Finally, let’s display the component. Modify app_component.dart
:
import 'package:angular2/core.dart';
import 'release_list_component.dart';
@Component(
selector: 'my-app',
styleUrls: const ['app_component.css'],
templateUrl: 'app_component.html',
directives: const [ReleaseListComponent],
)
class AppComponent {}
And app_component.html
:
<h1>My First Angular 2 App</h1>
<release-list></release-list>
Nothing is deferred loaded — yet. Let’s look at our Chrome timeline:
Splitting out release list
What if we only wanted to load release list after our initial page load? Easy!
Let’s modify our app_component.dart
to use DynamicComponentLoader
— which allows us to asynchronously load a component by it’s class
type.
import 'package:angular2/core.dart';
import 'release_list_component.dart';
@Component(
selector: 'my-app',
styleUrls: const ['app_component.css'],
templateUrl: 'app_component.html',
)
class AppComponent implements OnInit {
final DynamicComponentLoader _loader;
final ViewContainerRef _location;
AppComponent(this._loader, this._location);
@override
ngOnInit() async {
_loader.loadNextToLocation(ReleaseListComponent, _location);
}
}
(I’ve also removed <releases-list>
from app_component.html
)
Finally, let’s make it actually defer loaded. This is the fun part!
import 'release_list_component.dart' deferred as release_list;@override
ngOnInit() async {
await release_list.loadLibrary();
_loader.loadNextToLocation(
release_list.ReleaseListComponent, _location);
}
In just a few minutes, we’ve deferred/lazy loaded our Dart code, HTML template (pre-compiled to Dart code), and related CSS — everything, with a couple lines of code.
Going from here
You’ve seen the most basic example of deferred/lazy loading in Dart. Of course, this also works without Angular Dart, for your own frameworks and projects.
Let me know in the comments or elsewhere if you’d like more information.
Edit: Final code at https://github.com/matanlurey/angular2_lazy_example