refactor(docs-infra): update loading of custom elements to use dynamic import syntax (#30704)
Removes the usage of `NgModuleFactoryLoader` and string-based imports for lazy loading. PR Close #30704
This commit is contained in:
		
							parent
							
								
									1315d23aa4
								
							
						
					
					
						commit
						fcef39048a
					
				| @ -2,8 +2,8 @@ | |||||||
|   "aio": { |   "aio": { | ||||||
|     "master": { |     "master": { | ||||||
|       "uncompressed": { |       "uncompressed": { | ||||||
|         "runtime-es5": 2980, |         "runtime-es5": 2516, | ||||||
|         "runtime-es2015": 2986, |         "runtime-es2015": 2522, | ||||||
|         "main-es5": 504760, |         "main-es5": 504760, | ||||||
|         "main-es2015": 443497, |         "main-es2015": 443497, | ||||||
|         "polyfills-es5": 128751, |         "polyfills-es5": 128751, | ||||||
|  | |||||||
| @ -2,9 +2,9 @@ import { NgModule, NgModuleFactoryLoader, SystemJsNgModuleLoader } from '@angula | |||||||
| import { ROUTES} from '@angular/router'; | import { ROUTES} from '@angular/router'; | ||||||
| import { ElementsLoader } from './elements-loader'; | import { ElementsLoader } from './elements-loader'; | ||||||
| import { | import { | ||||||
|   ELEMENT_MODULE_PATHS, |   ELEMENT_MODULE_LOAD_CALLBACKS, | ||||||
|   ELEMENT_MODULE_PATHS_AS_ROUTES, |   ELEMENT_MODULE_LOAD_CALLBACKS_AS_ROUTES, | ||||||
|   ELEMENT_MODULE_PATHS_TOKEN |   ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN | ||||||
| } from './element-registry'; | } from './element-registry'; | ||||||
| import { LazyCustomElementComponent } from './lazy-custom-element.component'; | import { LazyCustomElementComponent } from './lazy-custom-element.component'; | ||||||
| 
 | 
 | ||||||
| @ -14,12 +14,12 @@ import { LazyCustomElementComponent } from './lazy-custom-element.component'; | |||||||
|   providers: [ |   providers: [ | ||||||
|     ElementsLoader, |     ElementsLoader, | ||||||
|     { provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader }, |     { provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader }, | ||||||
|     { provide: ELEMENT_MODULE_PATHS_TOKEN, useValue: ELEMENT_MODULE_PATHS }, |     { provide: ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN, useValue: ELEMENT_MODULE_LOAD_CALLBACKS }, | ||||||
| 
 | 
 | ||||||
|     // Providing these routes as a signal to the build system that these modules should be
 |     // Providing these routes as a signal to the build system that these modules should be
 | ||||||
|     // registered as lazy-loadable.
 |     // registered as lazy-loadable.
 | ||||||
|     // TODO(andrewjs): Provide first-class support for providing this.
 |     // TODO(andrewjs): Provide first-class support for providing this.
 | ||||||
|     { provide: ROUTES, useValue: ELEMENT_MODULE_PATHS_AS_ROUTES, multi: true }, |     { provide: ROUTES, useValue: ELEMENT_MODULE_LOAD_CALLBACKS_AS_ROUTES, multi: true }, | ||||||
|   ], |   ], | ||||||
| }) | }) | ||||||
| export class CustomElementsModule { } | export class CustomElementsModule { } | ||||||
|  | |||||||
| @ -1,44 +1,45 @@ | |||||||
| import { InjectionToken, Type } from '@angular/core'; | import { InjectionToken, Type } from '@angular/core'; | ||||||
|  | import { LoadChildrenCallback } from '@angular/router'; | ||||||
| 
 | 
 | ||||||
| // Modules containing custom elements must be set up as lazy-loaded routes (loadChildren)
 | // Modules containing custom elements must be set up as lazy-loaded routes (loadChildren)
 | ||||||
| // TODO(andrewjs): This is a hack, Angular should have first-class support for preparing a module
 | // TODO(andrewjs): This is a hack, Angular should have first-class support for preparing a module
 | ||||||
| // that contains custom elements.
 | // that contains custom elements.
 | ||||||
| export const ELEMENT_MODULE_PATHS_AS_ROUTES = [ | export const ELEMENT_MODULE_LOAD_CALLBACKS_AS_ROUTES = [ | ||||||
|   { |   { | ||||||
|     selector: 'aio-announcement-bar', |     selector: 'aio-announcement-bar', | ||||||
|     loadChildren: './announcement-bar/announcement-bar.module#AnnouncementBarModule' |     loadChildren: () => import('./announcement-bar/announcement-bar.module').then(mod => mod.AnnouncementBarModule) | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     selector: 'aio-api-list', |     selector: 'aio-api-list', | ||||||
|     loadChildren: './api/api-list.module#ApiListModule' |     loadChildren: () => import('./api/api-list.module').then(mod => mod.ApiListModule) | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     selector: 'aio-contributor-list', |     selector: 'aio-contributor-list', | ||||||
|     loadChildren: './contributor/contributor-list.module#ContributorListModule' |     loadChildren: () => import('./contributor/contributor-list.module').then(mod => mod.ContributorListModule) | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     selector: 'aio-file-not-found-search', |     selector: 'aio-file-not-found-search', | ||||||
|     loadChildren: './search/file-not-found-search.module#FileNotFoundSearchModule' |     loadChildren: () => import('./search/file-not-found-search.module').then(mod => mod.FileNotFoundSearchModule) | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     selector: 'aio-resource-list', |     selector: 'aio-resource-list', | ||||||
|     loadChildren: './resource/resource-list.module#ResourceListModule' |     loadChildren: () => import('./resource/resource-list.module').then(mod => mod.ResourceListModule) | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     selector: 'aio-toc', |     selector: 'aio-toc', | ||||||
|     loadChildren: './toc/toc.module#TocModule' |     loadChildren: () => import('./toc/toc.module').then(mod => mod.TocModule) | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     selector: 'code-example', |     selector: 'code-example', | ||||||
|     loadChildren: './code/code-example.module#CodeExampleModule' |     loadChildren: () => import('./code/code-example.module').then(mod => mod.CodeExampleModule) | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     selector: 'code-tabs', |     selector: 'code-tabs', | ||||||
|     loadChildren: './code/code-tabs.module#CodeTabsModule' |     loadChildren: () => import('./code/code-tabs.module').then(mod => mod.CodeTabsModule) | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     selector: 'live-example', |     selector: 'live-example', | ||||||
|     loadChildren: './live-example/live-example.module#LiveExampleModule' |     loadChildren: () => import('./live-example/live-example.module').then(mod => mod.LiveExampleModule) | ||||||
|   } |   } | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
| @ -51,10 +52,10 @@ export interface WithCustomElementComponent { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** Injection token to provide the element path modules. */ | /** Injection token to provide the element path modules. */ | ||||||
| export const ELEMENT_MODULE_PATHS_TOKEN = new InjectionToken('aio/elements-map'); | export const ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN = new InjectionToken<Map<string, LoadChildrenCallback>>('aio/elements-map'); | ||||||
| 
 | 
 | ||||||
| /** Map of possible custom element selectors to their lazy-loadable module paths. */ | /** Map of possible custom element selectors to their lazy-loadable module paths. */ | ||||||
| export const ELEMENT_MODULE_PATHS = new Map<string, string>(); | export const ELEMENT_MODULE_LOAD_CALLBACKS = new Map<string, LoadChildrenCallback>(); | ||||||
| ELEMENT_MODULE_PATHS_AS_ROUTES.forEach(route => { | ELEMENT_MODULE_LOAD_CALLBACKS_AS_ROUTES.forEach(route => { | ||||||
|   ELEMENT_MODULE_PATHS.set(route.selector, route.loadChildren); |   ELEMENT_MODULE_LOAD_CALLBACKS.set(route.selector, route.loadChildren); | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -1,13 +1,13 @@ | |||||||
| import { | import { | ||||||
|   ComponentFactory, |   ComponentFactory, | ||||||
|   ComponentFactoryResolver, ComponentRef, Injector, NgModuleFactory, NgModuleFactoryLoader, |   ComponentFactoryResolver, ComponentRef, Injector, NgModuleFactory, | ||||||
|   NgModuleRef, |   NgModuleRef, | ||||||
|   Type |   Type | ||||||
| } from '@angular/core'; | } from '@angular/core'; | ||||||
| import { TestBed, fakeAsync, flushMicrotasks } from '@angular/core/testing'; | import { TestBed, fakeAsync, flushMicrotasks } from '@angular/core/testing'; | ||||||
| 
 | 
 | ||||||
| import { ElementsLoader } from './elements-loader'; | import { ElementsLoader } from './elements-loader'; | ||||||
| import { ELEMENT_MODULE_PATHS_TOKEN, WithCustomElementComponent } from './element-registry'; | import { ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN, WithCustomElementComponent } from './element-registry'; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| interface Deferred { | interface Deferred { | ||||||
| @ -22,10 +22,9 @@ describe('ElementsLoader', () => { | |||||||
|     const injector = TestBed.configureTestingModule({ |     const injector = TestBed.configureTestingModule({ | ||||||
|       providers: [ |       providers: [ | ||||||
|         ElementsLoader, |         ElementsLoader, | ||||||
|         { provide: NgModuleFactoryLoader, useClass: FakeModuleFactoryLoader }, |         { provide: ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN, useValue: new Map<string, () => Promise<NgModuleFactory<WithCustomElementComponent>>>([ | ||||||
|         { provide: ELEMENT_MODULE_PATHS_TOKEN, useValue: new Map([ |           ['element-a-selector', () => Promise.resolve(new FakeModuleFactory('element-a-module'))], | ||||||
|           ['element-a-selector', 'element-a-module-path'], |           ['element-b-selector', () => Promise.resolve(new FakeModuleFactory('element-b-module'))] | ||||||
|           ['element-b-selector', 'element-b-module-path'] |  | ||||||
|         ])}, |         ])}, | ||||||
|       ] |       ] | ||||||
|     }); |     }); | ||||||
| @ -148,7 +147,7 @@ describe('ElementsLoader', () => { | |||||||
| 
 | 
 | ||||||
|       // Verify the right component was loaded/registered.
 |       // Verify the right component was loaded/registered.
 | ||||||
|       const Ctor = definedSpy.calls.argsFor(0)[1]; |       const Ctor = definedSpy.calls.argsFor(0)[1]; | ||||||
|       expect(Ctor.observedAttributes).toEqual(['element-a-module-path']); |       expect(Ctor.observedAttributes).toEqual(['element-a-module']); | ||||||
|     })); |     })); | ||||||
| 
 | 
 | ||||||
|     it('should wait until the element is defined', fakeAsync(() => { |     it('should wait until the element is defined', fakeAsync(() => { | ||||||
| @ -282,13 +281,6 @@ class FakeModuleFactory extends NgModuleFactory<any> { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class FakeModuleFactoryLoader extends NgModuleFactoryLoader { |  | ||||||
|   load(modulePath: string): Promise<NgModuleFactory<any>> { |  | ||||||
|     const fakeModuleFactory = new FakeModuleFactory(modulePath); |  | ||||||
|     return Promise.resolve(fakeModuleFactory); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function returnPromisesFromSpy(spy: jasmine.Spy): Deferred[] { | function returnPromisesFromSpy(spy: jasmine.Spy): Deferred[] { | ||||||
|   const deferreds: Deferred[] = []; |   const deferreds: Deferred[] = []; | ||||||
|   spy.and.callFake(() => new Promise((resolve, reject) => deferreds.push({resolve, reject}))); |   spy.and.callFake(() => new Promise((resolve, reject) => deferreds.push({resolve, reject}))); | ||||||
|  | |||||||
| @ -1,24 +1,24 @@ | |||||||
| import { | import { | ||||||
|   Inject, |   Inject, | ||||||
|   Injectable, |   Injectable, | ||||||
|   NgModuleFactoryLoader, |   NgModuleFactory, | ||||||
|   NgModuleRef, |   NgModuleRef, | ||||||
| } from '@angular/core'; | } from '@angular/core'; | ||||||
| import { ELEMENT_MODULE_PATHS_TOKEN } from './element-registry'; | import { ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN, WithCustomElementComponent } from './element-registry'; | ||||||
| import { from, Observable, of } from 'rxjs'; | import { from, Observable, of } from 'rxjs'; | ||||||
| import { createCustomElement } from '@angular/elements'; | import { createCustomElement } from '@angular/elements'; | ||||||
|  | import { LoadChildrenCallback } from '@angular/router'; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @Injectable() | @Injectable() | ||||||
| export class ElementsLoader { | export class ElementsLoader { | ||||||
|   /** Map of unregistered custom elements and their respective module paths to load. */ |   /** Map of unregistered custom elements and their respective module paths to load. */ | ||||||
|   private elementsToLoad: Map<string, string>; |   private elementsToLoad: Map<string, LoadChildrenCallback>; | ||||||
|   /** Map of custom elements that are in the process of being loaded and registered. */ |   /** Map of custom elements that are in the process of being loaded and registered. */ | ||||||
|   private elementsLoading = new Map<string, Promise<void>>(); |   private elementsLoading = new Map<string, Promise<void>>(); | ||||||
| 
 | 
 | ||||||
|   constructor(private moduleFactoryLoader: NgModuleFactoryLoader, |   constructor(private moduleRef: NgModuleRef<any>, | ||||||
|               private moduleRef: NgModuleRef<any>, |               @Inject(ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN) elementModulePaths: Map<string, LoadChildrenCallback>) { | ||||||
|               @Inject(ELEMENT_MODULE_PATHS_TOKEN) elementModulePaths: Map<string, string>) { |  | ||||||
|     this.elementsToLoad = new Map(elementModulePaths); |     this.elementsToLoad = new Map(elementModulePaths); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -47,9 +47,8 @@ export class ElementsLoader { | |||||||
| 
 | 
 | ||||||
|     if (this.elementsToLoad.has(selector)) { |     if (this.elementsToLoad.has(selector)) { | ||||||
|       // Load and register the custom element (for the first time).
 |       // Load and register the custom element (for the first time).
 | ||||||
|       const modulePath = this.elementsToLoad.get(selector)!; |       const modulePathLoader = this.elementsToLoad.get(selector)!; | ||||||
|       const loadedAndRegistered = this.moduleFactoryLoader |       const loadedAndRegistered = (modulePathLoader() as Promise<NgModuleFactory<WithCustomElementComponent>>) | ||||||
|           .load(modulePath) |  | ||||||
|           .then(elementModuleFactory => { |           .then(elementModuleFactory => { | ||||||
|             const elementModuleRef = elementModuleFactory.create(this.moduleRef.injector); |             const elementModuleRef = elementModuleFactory.create(this.moduleRef.injector); | ||||||
|             const injector = elementModuleRef.injector; |             const injector = elementModuleRef.injector; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user