Как вручную лениво загрузить модуль?
Я пытался загрузить модули без использования маршрутизатора SystemJsNgModuleLoader
, но не смог заставить его работать:
this.loader.load(url).then(console.info);
я собираюсь Cannot find module xxx
для любой строки, которую я использую для URL (aboslute/ относительные URL / пути... пробовал много вариантов). Я просмотрел исходный код маршрутизатора и не смог найти ничего, кроме этого SystemJsNgModuleLoader
, Я даже не уверен, что должен использовать это...
Этот вопрос был задан только вчера в ng-europe 2016
конференция - Мишко и Матиас ответили:
Мишко Хевери: Нужно просто завладеть модулем, оттуда вы можете получить фабрику компонентов и динамически загрузить фабрику компонентов в любом месте приложения. Это именно то, что маршрутизатор делает внутри. Так что это довольно прямолинейно и для вас.
Matias Niemelä Единственное, что следует отметить, это то, что в модуле [Ng] есть нечто, называемое
entryComponents
и это идентифицирует компоненты, которые могут быть загружены лениво - это запись в этот набор компонентов. Поэтому, когда у вас есть модули, которые загружаются лениво, пожалуйста, поместите материал вentryComponents
,
... но это не так уж далеко вперед без примеров и плохих документов по теме (;
Кто-нибудь знает, как загрузить модули вручную, не используя Route.loadChildren
? Как заполучить модуль и что именно нужно делать entryComponents
(Я читаю FAQ, но не могу попробовать без фактической загрузки модуля)?
2 ответа
Обновление Angular 6
Смотрите ответ@RomainLT
Предыдущие версии
Кто-нибудь знает, как загружать модули вручную, не используя Route.loadChildren?
Это может выглядеть так:
this.loader.load('./src/test.module#TestModule').then((factory: NgModuleFactory<any>) => {
console.log(factory);
});
TestModule
находится в файле ./src/test.module.ts (абсолютный путь)
Вот еще более сложный пример:
Если вы не загружаете компонент декларативно, как:
<my-comp></my-comp>
затем в вашем шаблоне, если вы хотите использовать этот компонент для динамической загрузки, вам нужно включить этот компонент в entryComponent одним из следующих способов:
entryComponents
массив в вашем @NgModuleentryComponents
массив внутри вашего @ComponentANALYZE_FOR_ENTRY_COMPONENTS
(угловой маршрутизатор использует этот метод https://github.com/angular/angular/blob/2.1.2/modules/%40angular/router/src/router_module.ts#L198)
Компилятор создает такие фабрики:
для каждой записикомпонент - host.factory.js
для каждого компонента component.ngfactory.js
Смотрите также
Пример для Angular-Cli
app.module.ts
providers: [
SystemJsNgModuleLoader,
provideRoutes([
{ loadChildren: 'app/lazy/lazy.module#LazyModule' }
])
],
app.component.ts
export class AppComponent implements OnInit {
title = 'Angular cli Example SystemJsNgModuleLoader.load';
@ViewChild('container', { read: ViewContainerRef }) container: ViewContainerRef;
constructor(private loader: SystemJsNgModuleLoader, private inj: Injector) {}
ngOnInit() {
this.loader.load('app/lazy/lazy.module#LazyModule').then((moduleFactory: NgModuleFactory<any>) => {
const entryComponent = (<any>moduleFactory.moduleType).entry;
const moduleRef = moduleFactory.create(this.inj);
const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent);
this.container.createComponent(compFactory);
});
}
}
Это также будет работать с AOT
Ленивая загрузка с Webpack и AOT
Компиляция с использованием ngc
Инициализация компилятора с использованием следующей фабрики
export function createJitCompiler () {
return new JitCompilerFactory([{useDebug: false, useJit: true}]).createCompiler();
}
[Угловой 6]
Привет,
Я поделюсь своим решением здесь, потому что я не нашел, как lazyload без маршрутизатора на stackru.
Путь Юрзуи работает, но он использует модуль Router для компиляции ленивого модуля, а я не хотел его использовать.
В нашем src/angular.json
файл, который мы можем попросить @angular/cli собрать модуль отдельно.
Для этого мы добавим lazyModules
введите "project" > "your-app-name" > "architect" > "build" > "options".
Как это:
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"lazy-load-app": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"prefix": "app",
"schematics": {},
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/lazy-custom-element-app",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": [],
"lazyModules": [
"src/app/lazy-load/lazy-load.module",
"src/app/another-lazy-load/another-lazy-load.module"
]
тогда мы можем вызвать и загрузить наш скомпилированный модуль.
Как это:
export class LoaderComponent implements OnInit {
// tag where we gonna inject the lazyload module and his default compononent "entry"
@ViewChild('container', { read: ViewContainerRef }) viewRef: ViewContainerRef;
constructor(
private loader: NgModuleFactoryLoader,
private injector: Injector,
private moduleRef: NgModuleRef<any>,) {
}
ngOnInit(): void {
this.loader.load(this.pathModuleTemplate).then((moduleFactory: NgModuleFactory<any>) => {
// our module had a static property 'entry' that references the component that want to load by default with the module
const entryComponent = (<any>moduleFactory.moduleType).entry;
const moduleRef = moduleFactory.create(this.injector);
const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent);
this.viewRef.createComponent(compFactory);
});
}
}
Надеюсь, это может помочь кому-то:)