从“ node_modules”文件夹中延迟加载功能模块

如果您中有人尝试创建角度库,则他可能会遇到从node_modules延迟加载Feature Module的问题。 让我们更深入地潜入黑暗的水域。


创建库工具


图片


如果您不熟悉问题“如何创建库?” -至少有两个工具可用于创建角度库:


  1. Angular CLI(引擎盖下的ng-packagr)
  2. 直接ng-packagr ;

您可以通过单击上面的链接来获取更多详细信息,所有其他的操作让我们进一步。


惰性模块(功能模块)


图片
因此,如果您已经使用过Angular,则必须了解Angular模块以及您需要它们的目的。


模块通常必须保留一堆组件,指令服务,这些指令代表某种自给自足的功能。 开发人员通常会为功能创建一个单独的模块,直到用户不会进入特定页面,该功能才需要加载到应用程序中。


现在是Feature Store(暂时不涉及)和Feature模块的时间。


如果将延迟加载的模块包含在某些父模块中,它们就不会延迟,因为您将在应用程序中声明它们,并且在编译时将TypeScript插入JavaScript Webpack中会将这些模块的代码添加到主束中,然后应用程序将加载启动时所有这些代码。


在路由中声明惰性模块的唯一正确方法是。


const routes: Routes = [ { path: 'reports', loadChildren: './reports/reports.module#ReportsModule' } ]; 

因此,您提供了实际为“#”的特殊字符串,应用程序将知道此模块必须与主应用程序分开加载。

麻烦开始


图片
如果功能模块是应用程序源代码的一部分,那么一切都会很好,但是如果这是使用npm设置的编译库,该怎么办? -它不能以通常的方式工作。


主要问题是,当您尝试通过常规字符串注册此类功能模块时,您将面临错误。


 const routes: Routes = [ { path: 'reports', // will not work loadChildren: 'my-lib#ReportsModule' } ]; 

由于这种声明导致的原因与编译模块不兼容。


您可以制作一个包装,然后在溃败中声明它。


 import { ReportsModule } from "my-lib"; @NgModule({ imports: [ReportModule], exports: [ReportModule] }) export class ReportsWrapperModule { } const routes: Routes = [ { path: 'reports', loadChildren: './wrapper.module#ReportsWrapperModule' } ]; 

但是,谁有兴趣为15个模块创建15个包装? -我不是!


可能的解决方案


图片


我不会隐藏我没有浪费时间分析为什么由于Webpack或某些Angular CLI而发生这种情况。 我发现了两种可能的解决方案。


解决方案#1。 库已编译,并且功能模块没有嵌套的功能模块


该工作示例的链接。


第一步,定义什么类型的LoadChildren属性


 type LoadChildren = string | LoadChildrenCallback; type LoadChildrenCallback = () => Type<any> | NgModuleFactory<any> | Promise<Type<any>> | Observable<Type<any>>; 

有趣! 因此,从理论上讲,可以使用import()返回带有所需模块的promise。
下一个代码必须没问题。


 const routes: Routes = [ { path: 'reports', loadChildren: () => import('my-lib').then((res) => res.ReportsModule) } ]; 

哦,怎么了? -我们在控制台中看到错误...是的,只需更改tsconfig.json


 { .. "module": "esNext", .. } 

现在必须正常工作。


解决方案#2。 Feature Module具有嵌套的Feature模块(仅针对未编译的库完成)


该工作示例的链接。


  1. 打包为npm package之前不必编译该库;


  2. 由于未编译库的源代码,因此必须将其包含在应用程序的编译过程中。 只需更改tsconfig.app.json ;


     "exclude": [ "test.ts", "**/*.spec.ts", "../node_modules/**/*.spec.ts", "../node_modules/**/test.ts" ], "include": [ "*.ts", "./environments", "./app", "../node_modules/my-lib" ] 

  3. 好消息-无需使用import() ;


     const routes: Routes = [{ path: "reports", loadChildren: "my-lib#ReportsModule" }]; 

    塔达姆!



PS这些解决方案仅在Angular 7上进行了测试。


感谢您的关注,享受。

Source: https://habr.com/ru/post/zh-CN442370/


All Articles