Carregamento lento do módulo de recursos da pasta "node_modules"

Se alguém tentou criar bibliotecas angulares, ele pode enfrentar o problema com o carregamento lento do Feature Module a partir de node_modules . Vamos mergulhar mais fundo e atravessar a água escura.


Criando ferramentas de biblioteca


imagem


Se você não estiver familiarizado com a pergunta "Como criar a biblioteca?" - Existem pelo menos duas ferramentas para criar biblioteca angular:


  1. CLI angular (ng-packagr sob o capô) ;
  2. Diretamente o ng-packagr ;

Você pode obter mais detalhes clicando nos links acima; todos os outros, vamos adiante.


Módulos preguiçosos (módulos de recursos)


imagem
Portanto, se você já trabalhou com o Angular, precisa conhecer os módulos Angular e para que fins os precisa.


Um módulo geralmente precisa manter vários componentes, serviços de diretivas que representam uma certa parte auto-suficiente da funcionalidade. Frequentemente, o desenvolvedor cria um módulo separado para um recurso que não deve ser carregado no aplicativo até que um usuário não vá para uma página específica.


E agora é a hora do Feature Store (não sobre isso por enquanto) e do módulo Feature.


Se você incluir módulos Lazy Loaded em algum módulo pai, eles não seriam preguiçosos, porque você os declarará no aplicativo e, no momento da compilação, o TypeScript no JavaScript Webpack adicionará o código desses módulos ao grupo principal e o aplicativo será carregado todo esse código na inicialização.


Apenas uma maneira correta de declarar um módulo lento no roteamento.


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

Então, você fornece a string especial que realmente "#" e o aplicativo saberão que este módulo deve ser carregado separadamente do aplicativo principal.

Os problemas começam


imagem
Tudo vai bem se o Feature Module fizer parte do código-fonte do seu aplicativo, mas e se for uma biblioteca compilada configurada usando o npm? - Não funciona da maneira usual.


O principal problema é que, ao tentar registrar esse módulo de recursos por uma sequência usual, você enfrentará o erro.


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

Causa devido a esse tipo de declaração não é compatível para módulos compilados.


Você é capaz de criar um invólucro e depois declará-lo em roteadores.


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

MAS, quem está interessado em criar 15 invólucros para 15 módulos? Eu não sou!


Possíveis soluções


imagem


Não vou esconder, não perdi tempo analisando por que isso acontece devido ao Webpack ou a alguma CLI Angular. Encontrei duas soluções possíveis.


Solução 1. Biblioteca compilada e o Feature Module não possui módulos de recurso aninhados


Link para o exemplo de trabalho.


Primeira etapa: defina que tipo de atributo LoadChildren


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

Interessante! Portanto, teoricamente, é possível usar import () para retornar a promessa com o módulo necessário.
O próximo código deve estar bem.


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

Oh, o que acontece? - Vemos erros no console ... Sim, basta alterar tsconfig.json


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

Agora tem que funcionar bem.


Solução # 2. O módulo de recursos possui módulos de recursos aninhados (feitos apenas para uma biblioteca não compilada)


Link para o exemplo de trabalho.


  1. Você não precisa compilar a biblioteca antes de empacotar no pacote npm;


  2. Como a fonte da biblioteca não é compilada, você deve incluí-la no processo de compilação do seu aplicativo. Apenas mude 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. Boas notícias - não há necessidade de usar import () ;


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

    Tadam!



PS Essas soluções foram testadas apenas com o Angular 7.


Obrigado pela atenção, aproveite.

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


All Articles