Carga diferida de Feature Module desde la carpeta "node_modules"

Si alguien de ustedes ha intentado crear bibliotecas angulares, puede enfrentar el problema con el módulo de funciones de carga diferida desde node_modules . Vamos a sumergirnos más profundo y pasar por el agua oscura.


Crear herramientas de biblioteca


imagen


Si no está familiarizado con la pregunta "¿Cómo crear la biblioteca?" - Hay al menos dos herramientas para crear una biblioteca angular:


  1. CLI angular (ng-packagr debajo del capó) ;
  2. Directamente el ng-packagr ;

Puede obtener más detalles haciendo clic en los enlaces de arriba, todos los demás avancemos más.


Módulos perezosos (módulos de funciones)


imagen
Entonces, si ya ha trabajado con Angular, debe conocer los módulos de Angular y para qué fines los necesita.


Un módulo generalmente tiene que mantener un grupo de componentes, servicios de directivas que representan una cierta funcionalidad autosuficiente. A menudo, el desarrollador crea un módulo separado para una función que no debe cargarse en la aplicación hasta que un usuario no vaya a una página en particular.


Y ahora es el momento de la tienda de características (no se trata de esto por ahora) y el módulo de características.


Si incluye módulos Lazy Loaded en algún módulo principal, no serían perezosos, porque los declarará en la aplicación y, en el momento de la compilación, TypeScript en el paquete web de JavaScript agregará el código de esos módulos en el grupo principal y la aplicación se cargará todo ese código al inicio.


Solo hay una forma correcta de declarar un módulo diferido en el enrutamiento.


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

Por lo tanto, proporcione la cadena especial que en realidad es "#" y la aplicación sabrá que este módulo debe cargarse por separado de la aplicación principal.

Los problemas comienzan


imagen
Todo va bien si el Módulo de funciones forma parte del código fuente de su aplicación, pero ¿qué sucede si se trata de una biblioteca compilada configurada con npm? - No funciona de la manera habitual.


El principal problema es que cuando intente registrar dicho Módulo de funciones con la cadena habitual, se enfrentará al error.


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

Debido a que este tipo de declaración no es compatible con los módulos compilados.


Puede crear un contenedor y luego declararlo en rutas.


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

PERO, ¿quién está interesado en crear 15 envoltorios para 15 módulos? - No lo estoy!


Posibles soluciones


imagen


No me esconderé, no perdí el tiempo analizando por qué sucede esto debido a Webpack o alguna CLI angular. Encontré dos posibles soluciones.


Solución # 1. Biblioteca compilada y el Módulo de funciones no tiene módulos de funciones anidados


Enlace para el ejemplo de trabajo.


El primer paso define qué tipo de atributo LoadChildren


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

Interesante! Entonces, teóricamente, es posible usar import () para devolver la promesa con el módulo requerido.
El siguiente código tiene que estar bien.


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

Oh que pasa - Vemos errores en la consola ... Sí, solo cambia tsconfig.json


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

Ahora tiene que funcionar bien.


Solución # 2. Los módulos de funciones tienen módulos de funciones anidados (solo para una biblioteca no compilada)


Enlace para el ejemplo de trabajo.


  1. No tiene que compilar la biblioteca antes de empaquetar en el paquete npm;


  2. Como la fuente de la biblioteca no está compilada, debe incluirla en el proceso de compilación de su aplicación. Simplemente cambie 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. Buenas noticias: no es necesario usar import () ;


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

    Tadam!



PD Estas soluciones se probaron solo con Angular 7.


Gracias por la atención, disfruta.

Source: https://habr.com/ru/post/442370/


All Articles