如何手动延迟加载模块? [英] How to manually lazy load a module?

查看:93
本文介绍了如何手动延迟加载模块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用 SystemJsNgModuleLoader ,但无法正常工作:

this.loader.load(url).then(console.info);

无论我使用什么字符串作为URL(粗俗/相对url/路径...尝试了许多选项),我都得到Cannot find module xxx.我查看了路由器的源代码,但找不到此SystemJsNgModuleLoader以外的任何内容.我什至不确定我应该使用这个...


这个问题是昨天在ng-europe 2016会议上提出的-Miško& Matias回答:

MiškoHevery: 只需掌握模块,即可从那里获取组件工厂,并可以在应用程序中任何需要的地方动态加载组件工厂.这正是路由器在内部执行的操作.因此,您也可以这样做.

MatiasNiemelä 唯一需要特别注意的是,在[Ng] Module上有一个名为entryComponents的东西,它标识可以延迟加载的组件-这是该组件集中的条目.因此,当您有延迟加载的模块时,请将东西放入entryComponents.

...但是如果没有关于该主题的示例和差劲的文档,这并不是那么困难(;

任何人都知道如何在不使用Route.loadChildren的情况下手动加载模块吗?如何掌握模块以及应放入entryComponents的东西到底是什么(我读了解决方案

任何人都知道如何手动加载模块,而无需使用 Route.loadChildren?

您可以使用SystemJsNgModuleLoader来获取模块的工厂:

 this.loader.load('./src/lazy.module#TestModule').then((factory: NgModuleFactory<any>) => {
  console.log(factory);
});
 

有关Angular 8的信息,请参见 角度为8的延迟加载模块

这是它的样子:

lazy.module.ts

 @Component({
  selector: 'test',
  template: `I'm lazy module`,
})
export class Test {}

@NgModule({
  imports: [CommonModule],
  declarations: [Test],
  entryComponents: [Test]
})
export class LazyModule {
  static entry = Test;
}
 

app.ts

 import {
  Component, NgModule, ViewContainerRef,
  SystemJsNgModuleLoader, NgModuleFactory,
  Injector} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

@Component({
  selector: 'my-app',
  template: `<h2>Test lazy loading module</h2>`,
})
export class AppComponent {
  constructor(
    private loader: SystemJsNgModuleLoader, 
    private inj: Injector, 
    private vcRef: ViewContainerRef) {}

  ngOnInit() {
     this.loader.load('./src/lazy.module#LazyModule')
       .then((moduleFactory: NgModuleFactory<any>) => {
         const moduleRef = moduleFactory.create(this.inj);
         const entryComponent = (<any>moduleFactory.moduleType).entry;
         const compFactory = 
               moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent);
         this.vcRef.createComponent(compFactory);
      });
  }
} 

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ AppComponent ],
  providers: [SystemJsNgModuleLoader],
  bootstrap: [ AppComponent ]
})
export class AppModule {} 
 

 this.loader.load('./src/test.module#TestModule').then((factory: NgModuleFactory<any>) => {
  console.log(factory);
});
 

柱塞示例

AOT 有两个选项预编译模块:

1)Angular CLI lazyModules选项(自Angular 6起)

使用angular/cli内置功能

 {
  "projects": {
    "app": {
      "architect": {
        "build": {
          "options": {
            "lazyModules": [  <====== add here all your lazy modules
              "src/path-to.module"
            ]
          }
        }
      }
    }
  }
} 
 

请参见

2)使用来自RouterModule的ProvideRoutes

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);
        });
    }
}
 

Github存储库angular-cli-lazy


通过webpack和AOT延迟加载

使用ngc进行编译

使用以下工厂的初始化编译器

 export function createJitCompiler () {
    return new JitCompilerFactory([{useDebug: false, useJit: true}]).createCompiler();
}
 

Github存储库

I've tried loading modules without router using SystemJsNgModuleLoader, but couldn't get it to work:

this.loader.load(url).then(console.info);

I'm getting Cannot find module xxx for whatever string I use for URL (aboslute/relative urls/paths... tried many options). I looked through Router source code and couldn't find anything other then this SystemJsNgModuleLoader. I'm not even sure I should be using this...


This question was asked just yesterday at ng-europe 2016 conference - Miško & Matias answered:

Miško Hevery: One just has to get hold of the module, from there you can get the hold of component factory and you can dynamically load component factory anywhere you want in the application. This is exactly what the router does internally. So it's quite strait forward for you to do that as well.

Matias Niemelä The only special thing to note is that on the [Ng]Module there's something called entryComponents and that identifies components that could be lazy loaded - that's the entry into that component set. So when you have modules that are lazy loaded, please put the stuff into entryComponents.

...but it's not that strait forward without examples and poor docs on the subject (;

Anyone knows how to load modules manually, without using Route.loadChildren? How to get hold of the module and what exactly is the stuff that should go into entryComponents (I read FAQ, but can't try without actually loading module)?

解决方案

Anyone knows how to load modules manually, without using Route.loadChildren?

You can use SystemJsNgModuleLoader to get module's factory:

this.loader.load('./src/lazy.module#TestModule').then((factory: NgModuleFactory<any>) => {
  console.log(factory);
});

For Angular 8 see Lazy load module in angular 8

Here is how it can look like:

lazy.module.ts

@Component({
  selector: 'test',
  template: `I'm lazy module`,
})
export class Test {}

@NgModule({
  imports: [CommonModule],
  declarations: [Test],
  entryComponents: [Test]
})
export class LazyModule {
  static entry = Test;
}

app.ts

import {
  Component, NgModule, ViewContainerRef,
  SystemJsNgModuleLoader, NgModuleFactory,
  Injector} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

@Component({
  selector: 'my-app',
  template: `<h2>Test lazy loading module</h2>`,
})
export class AppComponent {
  constructor(
    private loader: SystemJsNgModuleLoader, 
    private inj: Injector, 
    private vcRef: ViewContainerRef) {}

  ngOnInit() {
     this.loader.load('./src/lazy.module#LazyModule')
       .then((moduleFactory: NgModuleFactory<any>) => {
         const moduleRef = moduleFactory.create(this.inj);
         const entryComponent = (<any>moduleFactory.moduleType).entry;
         const compFactory = 
               moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent);
         this.vcRef.createComponent(compFactory);
      });
  }
} 

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ AppComponent ],
  providers: [SystemJsNgModuleLoader],
  bootstrap: [ AppComponent ]
})
export class AppModule {} 

this.loader.load('./src/test.module#TestModule').then((factory: NgModuleFactory<any>) => {
  console.log(factory);
});

Plunker Example

There are two options to precompile module for AOT:

1) Angular CLI lazyModules options (since Angular 6)

Use angular/cli build-in feature:

{
  "projects": {
    "app": {
      "architect": {
        "build": {
          "options": {
            "lazyModules": [  <====== add here all your lazy modules
              "src/path-to.module"
            ]
          }
        }
      }
    }
  }
} 

See

2) Using provideRoutes from RouterModule

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);
        });
    }
}

Github repo angular-cli-lazy


Lazy loading with webpack and AOT

Compilation using ngc

Initialization Compiler by using the following factory

export function createJitCompiler () {
    return new JitCompilerFactory([{useDebug: false, useJit: true}]).createCompiler();
}

Github repo

这篇关于如何手动延迟加载模块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆