## 懒加载模块
默认情况下,模块是急切加载的,这意味着一旦应用程序加载,所有模块也会加载,无论它们是否立即需要。虽然这对大多数应用程序来说都很好,但它可能成为在**无服务器环境**中运行的应用程序/工作人员的瓶颈,其中启动延迟(“冷启动”)至关重要。
延迟加载可以通过仅加载特定无服务器函数调用所需的模块来帮助减少引导时间。此外,您还可以在无服务器功能“热启”后异步加载其他模块,以进一步加快后续调用的引导时间(延迟模块注册)。
> **提示**:如果您熟悉**Angular**框架,您可能以前见过“延迟加载模块”这个术语。请注意,此技术在 Nest 中的**功能有所不同**,因此请将此视为具有相似命名约定的完全不同的功能。
#### 开始[#](#getting-started)
为了按需加载模块,Nest 提供了`LazyModuleLoader`可以以正常方式注入到类中的类:
>cats.service.ts
~~~typescript
@Injectable()
export class CatsService {
constructor(private lazyModuleLoader: LazyModuleLoader) {}
}
~~~
> **提示**:该类`LazyModuleLoader`是从`@nestjs/core`包中导入的。
或者,您可以从应用程序引导文件 (`main.ts` )中获取对提供程序的懒加载`LazyModuleLoader`引用,如下所示:
~~~typescript
// "app" represents a Nest application instance
const lazyModuleLoader = app.get(LazyModuleLoader);
~~~
有了这个,您现在可以使用以下结构加载任何模块:
~~~typescript
const { LazyModule } = await import('./lazy.module');
const moduleRef = await this.lazyModuleLoader.load(() => LazyModule);
~~~
> **提示**“:延迟加载”模块在第一次方法调用时被**缓存。**`LazyModuleLoader#load`这意味着,每次连续的加载尝试`LazyModule`都会**非常快**,并且会返回一个缓存的实例,而不是再次加载模块。
>
> ~~~bash
>
> Load "LazyModule" attempt: 1
> time: 2.379ms
> Load "LazyModule" attempt: 2
> time: 0.294ms
> Load "LazyModule" attempt: 3
> time: 0.303ms
>
> ~~~
>
> 此外,“延迟加载”模块与那些在应用程序引导程序上急切加载的模块以及稍后在您的应用程序中注册的任何其他延迟模块共享相同的模块图。
当`lazy.module.ts`是是一个TypeScript 文件 那可以导出为常规 Nest 模块(无需额外更改)。
该`LazyModuleLoader#load`方法返回[模块引用](https://docs.nestjs.com/fundamentals/module-ref)(of`LazyModule`),它允许您导航提供者的内部列表并使用其注入令牌作为查找键获取对任何提供者的引用。
例如,假设我们有`LazyModule`以下定义:
~~~typescript
@Module({
providers: [LazyService],
exports: [LazyService],
})
export class LazyModule {}
~~~
> **提示**:延迟加载的模块不能注册为**全局模块**,因为它根本没有意义(因为它们是延迟注册的,当所有静态注册的模块都已经实例化时按需注册)。同样,注册的**全局增强器**(守卫/拦截器/等)**也无法正常**工作。
有了这个,我们可以获得对`LazyService`提供者的引用,如下所示:
~~~typescript
const { LazyModule } = await import('./lazy.module');
const moduleRef = await this.lazyModuleLoader.load(() => LazyModule);
const { LazyService } = await import('./lazy.service');
const lazyService = moduleRef.get(LazyService);
~~~
> **警告**:如果您使用**Webpack**,请确保更新您的`tsconfig.json`文件 - 设置`compilerOptions.module`并`"esnext"`添加`compilerOptions.moduleResolution`属性`"node"`作为值:
>
> ~~~json
>
> {
> "compilerOptions": {
> "module": "esnext",
> "moduleResolution": "node",
> ...
> }
> }
>
> ~~~
>
> 设置这些选项后,您将能够利用[代码拆分](https://webpack.js.org/guides/code-splitting/)功能。
#### 延迟加载控制器、网关和解析器[#](#lazy-loading-controllers-gateways-and-resolvers)
由于 Nest 中的控制器(或 GraphQL 应用程序中的解析器)表示一组路由/路径/主题(或查询/突变),因此您**不能**使用`LazyModuleLoader`该类延迟加载它们。
> **警告**在延迟加载模块中注册的控制器、[解析器](https://docs.nestjs.com/graphql/resolvers)和[网关](https://docs.nestjs.com/websockets/gateways)将不会按预期运行。同样,您不能`MiddlewareConsumer`按需注册中间件功能(通过实现接口)。
例如,假设您正在构建一个 REST API(HTTP 应用程序),并在后台使用 Fastify 驱动程序(使用`@nestjs/platform-fastify`包)。Fastify 不允许你在应用程序准备好/成功监听消息后注册路由。这意味着即使我们分析了模块控制器中注册的路由映射,所有延迟加载的路由也无法访问,因为无法在运行时注册它们。
同样,我们作为`@nestjs/microservices`包的一部分提供的一些传输策略(包括 Kafka、gRPC 或 RabbitMQ)需要在建立连接之前订阅/侦听特定主题/通道。一旦您的应用程序开始收听消息,框架将无法订阅/收听新主题。
最后,`@nestjs/graphql`启用代码优先方法的包会根据元数据自动动态生成 GraphQL 模式。这意味着,它需要预先加载所有类。否则,将无法创建适当的有效模式。
#### 常见用例[#](https://docs.nestjs.com/fundamentals/lazy-loading-modules#common-use-cases)
最常见的情况是,当您的 `worker/cron job/lambda & serverless function/webhook`必须根据输入参数(路由路径/日期/查询参数等)触发不同的服务(不同的逻辑)时,您会看到延迟加载的模块。另一方面,延迟加载模块对于单体应用程序可能没有太大意义,在这些应用程序中,启动时间相当无关紧要。
- 介绍
- 概述
- 第一步
- 控制器
- 提供者
- 模块
- 中间件
- 异常过滤器
- 管道
- 守卫
- 拦截器
- 自定义装饰器
- 基础知识
- 自定义提供者
- 异步提供者
- 动态模块
- 注入作用域
- 循环依赖
- 模块参考
- 懒加载模块
- 应用上下文
- 生命周期事件
- 跨平台
- 测试
- 技术
- 数据库
- Mongo
- 配置
- 验证
- 缓存
- 序列化
- 版本控制
- 定时任务
- 队列
- 日志
- Cookies
- 事件
- 压缩
- 文件上传
- 流式处理文件
- HTTP模块
- Session(会话)
- MVC
- 性能(Fastify)
- 服务器端事件发送
- 安全
- 认证(Authentication)
- 授权(Authorization)
- 加密和散列
- Helmet
- CORS(跨域请求)
- CSRF保护
- 限速
- GraphQL
- 快速开始
- 解析器(resolvers)
- 变更(Mutations)
- 订阅(Subscriptions)
- 标量(Scalars)
- 指令(directives)
- 接口(Interfaces)
- 联合类型
- 枚举(Enums)
- 字段中间件
- 映射类型
- 插件
- 复杂性
- 扩展
- CLI插件
- 生成SDL
- 其他功能
- 联合服务
- 迁移指南
- Websocket
- 网关
- 异常过滤器
- 管道
- 守卫
- 拦截器
- 适配器
- 微服务
- 概述
- Redis
- MQTT
- NATS
- RabbitMQ
- Kafka
- gRPC
- 自定义传输器
- 异常过滤器
- 管道
- 守卫
- 拦截器
- 独立应用
- Cli
- 概述
- 工作空间
- 库
- 用法
- 脚本
- Openapi
- 介绍
- 类型和参数
- 操作
- 安全
- 映射类型
- 装饰器
- CLI插件
- 其他特性
- 迁移指南
- 秘籍
- CRUD 生成器
- 热重载
- MikroORM
- TypeORM
- Mongoose
- 序列化
- 路由模块
- Swagger
- 健康检查
- CQRS
- 文档
- Prisma
- 静态服务
- Nest Commander
- 问答
- Serverless
- HTTP 适配器
- 全局路由前缀
- 混合应用
- HTTPS 和多服务器
- 请求生命周期
- 常见错误
- 实例
- 迁移指南
- 发现
- 谁在使用Nest?