You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

非Route模块的Lazy Load:如何懒加载被其他Component/Module引用的模块

非路由模块(LibModule)的懒加载实现方案

针对你提到的场景——LibModule包含仅被其他模块组件调用的自定义组件,无需通过路由直接访问,我们可以通过动态导入+Angular模块/组件动态创建的方式实现懒加载,具体分为以下几个步骤:

1. 配置LibModule,避免提前加载

首先确保LibModule不会被任何模块的imports数组直接引用(否则会被打包进主chunk,失去懒加载意义),同时导出需要使用的组件:

// lib.module.ts
import { NgModule } from '@angular/core';
import { GridComponent } from './grid/grid.component';
import { ButtonComponent } from './button/button.component';

@NgModule({
  declarations: [GridComponent, ButtonComponent],
  exports: [GridComponent, ButtonComponent] // 导出组件,方便加载后实例化
})
export class LibModule { }

2. 方式一:在组件中动态加载并使用LibModule的组件

如果只是在某个组件(比如HomeComponent)中按需使用LibModule的组件,可以通过动态导入模块+创建组件实例的方式实现:

步骤2.1:在组件模板中预留挂载容器

<!-- home.component.html -->
<!-- 预留动态组件的挂载容器 -->
<div #libComponentHost></div>
<button (click)="loadGridComponent()">加载Grid组件</button>

步骤2.2:在组件类中实现动态加载逻辑

利用Angular的ViewContainerRef、Injector和动态导入语法import(),按需加载LibModule并创建组件:

// home.component.ts
import { Component, ViewChild, ViewContainerRef, Injector } from '@angular/core';
import { createNgModule } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html'
})
export class HomeComponent {
  // 获取挂载容器的引用
  @ViewChild('libComponentHost', { read: ViewContainerRef, static: false }) 
  componentHost!: ViewContainerRef;

  constructor(private injector: Injector) { }

  async loadGridComponent() {
    // 清空容器(可选,避免重复创建)
    this.componentHost.clear();

    // 1. 动态加载LibModule
    const { LibModule } = await import('../lib/lib.module');
    // 2. 创建LibModule的引用
    const moduleRef = await createNgModule(LibModule, this.injector);
    // 3. 动态加载需要的组件
    const { GridComponent } = await import('../lib/grid/grid.component');
    // 4. 创建组件实例并挂载到容器中
    const componentRef = this.componentHost.createComponent(GridComponent, {
      injector: moduleRef.injector
    });

    // 如果需要给组件传值,可以通过componentRef.instance设置
    // componentRef.instance.someInput = 'Hello';
  }
}

3. 方式二:封装懒加载服务,复用模块加载逻辑

如果多个组件/模块都需要使用LibModule的组件,建议封装一个服务来管理模块的加载,避免重复加载:

步骤3.1:创建Lib加载服务

// lib-loader.service.ts
import { Injectable, Injector, NgModuleRef } from '@angular/core';
import { LibModule } from '../lib/lib.module';

@Injectable({ providedIn: 'root' })
export class LibLoaderService {
  private libModuleRef: NgModuleRef<LibModule> | null = null;

  constructor(private injector: Injector) { }

  // 确保模块只被加载一次
  async getLibModuleRef(): Promise<NgModuleRef<LibModule>> {
    if (this.libModuleRef) {
      return this.libModuleRef;
    }
    const { LibModule } = await import('../lib/lib.module');
    this.libModuleRef = await createNgModule(LibModule, this.injector);
    return this.libModuleRef;
  }
}

步骤3.2:在组件中使用服务加载组件

// home.component.ts
import { Component, ViewChild, ViewContainerRef } from '@angular/core';
import { LibLoaderService } from './lib-loader.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html'
})
export class HomeComponent {
  @ViewChild('libComponentHost', { read: ViewContainerRef, static: false }) 
  componentHost!: ViewContainerRef;

  constructor(private libLoader: LibLoaderService) { }

  async loadButtonComponent() {
    this.componentHost.clear();
    // 获取已加载的模块引用
    const moduleRef = await this.libLoader.getLibModuleRef();
    // 动态加载Button组件
    const { ButtonComponent } = await import('../lib/button/button.component');
    // 创建组件实例
    this.componentHost.createComponent(ButtonComponent, {
      injector: moduleRef.injector
    });
  }
}

4. 确保代码分割生效

Angular CLI默认会对import()语法的模块进行代码分割,将LibModule打包为独立的chunk。你可以通过ng build --prod后查看dist目录下的文件,会发现类似lib-lib-module.js的独立chunk文件,说明懒加载配置成功。

注意事项

  • 不要在任何模块的imports数组中直接引入LibModule,否则会被提前打包。
  • 如果LibModule中包含服务,若服务是providedIn: 'root'则全局可用;若服务是providedIn: LibModule,则服务的实例会绑定到LibModule的injector中,只有通过模块引用的injector才能获取。
  • Angular 9+使用Ivy编译器后,无需手动配置entryComponents,组件会被自动识别。

内容的提问来源于stack exchange,提问作者Vijay Chauhan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:28:30