angulardart / angular

Fast and productive web framework provided by Dart
https://pub.dev/packages/angular
MIT License
1.83k stars 230 forks source link

AsyncRoute causes "No precompiled component X found" #606

Closed eredo closed 7 years ago

eredo commented 7 years ago

In angular 4.0.0-beta deferred routes are no longer working. Whenever an AsyncRoute is called the following exception is thrown:

VM64:1 EXCEPTION: No precompiled component DeferredRouteComponent found
STACKTRACE: 
#0      ReflectorComponentResolver.resolveComponentSync (package:angular/src/core/linker/component_resolver.dart:35:7)
#1      getComponentAnnotations (package:angular_router/src/utils.dart:41:26)
#2      RouteRegistry.configFromComponent (package:angular_router/src/route_registry.dart:127:23)
#3      normalizeRouteConfig.loader (package:angular_router/src/route_config/route_config_normalizer.dart:12:16)
<asynchronous suspension>
#4      AsyncRouteHandler.resolveComponentType (package:angular_router/src/rules/route_handlers/async_route_handler.dart:18:43)
#5      RouteRegistry._generate.<anonymous closure> (package:angular_router/src/route_registry.dart:390:42)
#6      UnresolvedInstruction.resolveComponent (package:angular_router/src/instruction.dart:237:46)
<asynchronous suspension>
#7      Router._settleInstruction (package:angular_router/src/router.dart:209:24)
#8      Router._navigate (package:angular_router/src/router.dart:227:10)
#9      Router.navigateByInstruction.<anonymous closure> (package:angular_router/src/router.dart:204:16)
#10     _rootRunUnary (dart:async/zone.dart:1128)
#11     _ZoneDelegate.runUnary (dart:async/zone.dart:685)
#12     NgZone._runUnary (package:angular/src/core/zone/ng_zone.dart:184:21)
#13     _CustomZone.runUnary (dart:async/zone.dart:1012)
#14     _FutureListener.handleValue (dart:async/future_impl.dart:129)
#15     _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:636)
#16     _Future._propagateToListeners (dart:async/future_impl.dart:665)
#17     _Future._addListener.<anonymous closure> (dart:async/future_impl.dart:343)
#18     NgZone._scheduleMicrotask.<anonymous closure> (package:angular/src/core/zone/ng_zone.dart:161:11)
#19     _rootRun (dart:async/zone.dart:1120)
#20     _ZoneDelegate.run (dart:async/zone.dart:675)
#21     NgZone._run (package:angular/src/core/zone/ng_zone.dart:175:21)
#22     _CustomZone.run (dart:async/zone.dart:1001)
#23     _CustomZone.runGuarded (dart:async/zone.dart:901)
#24     _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:926)
#25     _microtaskLoop (dart:async/schedule_microtask.dart:41)
#26     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50)
#27     _ScheduleImmediateHelper._handleMutation (dart:html:53852)

ORIGINAL EXCEPTION: No precompiled component DeferredRouteComponent found

Here an example implementation:

pubspec.yaml

name: angular4_router
environment:
  sdk: '>=1.24.0 <2.0.0-dev.infinity'
dependencies:
  angular: 4.0.0-beta
  angular_router: ^1.0.1
  browser: ^0.10.0
  dart_to_js_script_rewriter: ^1.0.1
dev_dependencies:
  webdriver: ^1.2.1
transformers:
- angular:
    entry_points: web/main.dart
- $dart2js:
    commandLineOptions: [--trust-type-annotations, --trust-primitives, --show-package-warnings, --dump-info]
- dart_to_js_script_rewriter

main.dart

import 'package:angular/angular.dart';

import 'package:angular4_router/app_component.dart';

main() {
  bootstrap(AppComponent);
}

app_component.dart

import 'dart:async';

import 'package:angular/angular.dart';
import 'package:angular_router/angular_router.dart';

import 'deferred_route_component.dart' deferred as def;

Future<dynamic> loader() => def.loadLibrary().then((_) => def.DeferredRouteComponent);

@RouteConfig(const [
  const Route(
    path: '/',
    name: 'Init',
    useAsDefault: true,
    component: AppInitComponent,
  ),
  const AsyncRoute(
    path: 'doit/...',
    name: 'DoIt',
    loader: loader,
  ),
])
@Component(
  selector: 'route-app',
  template: '''<a [routerLink]="['DoIt/Done']">test</a><router-outlet></router-outlet>''',
  directives: const [Router, RouterLink],
  providers: const [ROUTER_PROVIDERS],
)
class AppComponent {}

@Component(
  selector: 'route-init',
  template: 'Init...',
)
class AppInitComponent {}

deferred_route_component.dart

import 'package:angular/angular.dart';
import 'package:angular_router/angular_router.dart';

@RouteConfig(const [
  const Route(
    name: 'Done',
    path: 'done',
    useAsDefault: true,
    component: DeferredRouteSubComponent,
  )
])
@Component(
  selector: 'deferred-route',
  template: '''<router-outlet></router-outlet>''',
  directives: const [Router],
)
class DeferredRouteComponent {}

@Component(
  selector: 'deferred-sub',
  template: 'Hello World',
)
class DeferredRouteSubComponent {}

I'm not sure if this appeared in previous alpha versions as well, because we tried to migrate from 3.1.0 to 4.0.0-beta.

matanlurey commented 7 years ago

@eredo Unfortunately you'll need to also invoke initReflector:

Future<dynamic> loader() => def.loadLibrary().then((_) {
  def.initReflector();
  return def.DeferredRouteComponent;
});
eredo commented 7 years ago

Thanks, is this documented anywhere?

matanlurey commented 7 years ago

I thought it was in https://github.com/dart-lang/angular/blob/master/doc/component_loading.md, but I see that it is not. I'll make a small update to the docs.