## 懶加載模塊
默認情況下,模塊是急切加載的,這意味著一旦應用程序加載,所有模塊也會加載,無論它們是否立即需要。雖然這對大多數應用程序來說都很好,但它可能成為在**無服務器環境**中運行的應用程序/工作人員的瓶頸,其中啟動延遲(“冷啟動”)至關重要。
延遲加載可以通過僅加載特定無服務器函數調用所需的模塊來幫助減少引導時間。此外,您還可以在無服務器功能“熱啟”后異步加載其他模塊,以進一步加快后續調用的引導時間(延遲模塊注冊)。
> **提示**:如果您熟悉**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?