UNPKG

3.41 kBPlain TextView Raw
1import { ComponentResolver, Injectable, Inject, OpaqueToken } from '@angular/core';
2import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
3import { RuntimeCompiler } from '@angular/compiler';
4import { Observable } from 'rxjs/Observable';
5import 'rxjs/add/observable/fromPromise';
6
7export const AC_WEBPACK_ASYNC_MAP = new OpaqueToken('AC_WEBPACK_ASYNC_MAP');
8
9
10export function composeRoutes(...routes) {
11 return (<any>Object).assign(...routes);
12}
13
14
15@Injectable()
16export class WebpackAsyncModules {
17 constructor(
18 @Inject(AC_WEBPACK_ASYNC_MAP) private _asyncModules: any) {
19
20 }
21 fetch(moduleName: string, exportName?: string) {
22 return this._asyncModules[moduleName]();
23 }
24 hasModule(moduleName: string) {
25 return !!this._asyncModules[moduleName];
26 }
27}
28
29@Injectable()
30export class WebpackComponentResolver {
31 constructor(
32 private _resolver: ComponentResolver,
33 private _webpackAsyncModules: WebpackAsyncModules) {
34
35 }
36
37 resolveComponent(componentType: any) {
38 if (typeof componentType === 'string' && this._webpackAsyncModules.hasModule(componentType)) {
39 return this._webpackAsyncModules.fetch(componentType)
40 .then(cmpFile => {
41 let component = this._resolveExports(cmpFile, componentType);
42 return this._resolver.resolveComponent(component);
43 });
44 }
45 return this._resolver.resolveComponent(componentType);
46 }
47
48 clearCache(): void {}
49
50 private _resolveExports(cmpFile, componentType) {
51 return cmpFile[componentType] || cmpFile.default || cmpFile;
52 }
53}
54
55@Injectable()
56export class WebpackAsyncRoute {
57 constructor(public router: Router, public webpackAsyncModules: WebpackAsyncModules) {
58 }
59 canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
60 let commponentString: string = (<any>route).component;
61 if (typeof commponentString !== 'string') { return true; }
62
63 let routeConfig = (<any>this).router.config;
64 return Observable.fromPromise<boolean>(new Promise(resolve => {
65 this.webpackAsyncModules.fetch(commponentString)
66 .then((asyncModule) => {
67 let currentRouteConfig = routeConfig;
68 let newRoutes = currentRouteConfig
69 .map(_route => {
70 if (_route.path === asyncModule.routes.path) {
71 let newRoute = composeRoutes(_route, asyncModule.routes);
72 newRoute.canActivate = newRoute.canActivate.filter(active => active !== WebpackAsyncRoute);
73 return newRoute;
74 }
75 return _route;
76 });
77 this.router.resetConfig(newRoutes);
78 resolve(true);
79 return asyncModule;
80 });
81 }));
82 }
83
84}
85
86export const ANGULARCLASS_WEBPACK_RUNTIME_PROVIDERS = [
87 WebpackAsyncModules,
88 {
89 provide: WebpackAsyncRoute,
90 useFactory: (router, webpackAsyncModules) => {
91 return new WebpackAsyncRoute(router, webpackAsyncModules);
92 },
93 deps: [Router, WebpackAsyncModules]
94 },
95 {
96 provide: ComponentResolver,
97 useFactory: (resolver, webpackAsyncModules) => {
98 return new WebpackComponentResolver(resolver, webpackAsyncModules);
99 },
100 deps: [RuntimeCompiler, WebpackAsyncModules]
101 }
102];
103
104export function provideWebpack(asyncModules) {
105 return [
106 { provide: AC_WEBPACK_ASYNC_MAP, useValue: asyncModules },
107 ...ANGULARCLASS_WEBPACK_RUNTIME_PROVIDERS,
108 ];
109}