Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

Erro Lazy Loading

Eu tentei fazer o lazy loading mas o modulo e as rotas que eu criei não estão sendo carregadas...

Não dá nenhum erro na hora de testar pelo ng serve. Todas as outras rotas continuam funcionando normalmente, porém as rotas que foram para o novo rounting.ts não funcionam. Ao clicar, o browser simula uma mudança de rota mas não conclui.

Eu criei o admin.module.ts abaixo:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { AdminRoutingModule } from './admin.routing.module';
// imports de todos os components

@NgModule({
  declarations: [
    //todos os components do admin que foram importados,
  ],
  imports: [
    CommonModule,
    RouterModule,
    AdminRoutingModule,
  ]
})
export class AdminModule { }

E criei o admin.routing.module.ts:

import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { RestrictedGuardService } from ".././restricted-guard.service";
//imports dos components responsáveis pelas rotas

const routes: Routes = [ { 
    {
        path: "usuario",
        component: AdminUsuariosComponent,
        canActivate: [RestrictedGuardService],
        data: { perfil: ["ROLE_ADMIN"] }
    },
    //todos demais paths...

} ]

@NgModule({
    imports: [RouterModule.forChild(routes)],
    exports: [RouterModule]
})
export class AdminRoutingModule { }

E no app-routing.module eu inclui o path

   {
        path: 'admin',
        loadChildren: './admin/admin.module#AdminModule',
        canActivate: [RestrictedGuardService],
        data: { perfil: ["ROLE_ADMIN"] }    
},

Eu acesso com o usuário admin que antes de ter feito o split as rotas funcionavam normalmente, mas depois de ter feito o split e o lazy load,não carregam mais. Eu testei retirando o canActivate e o data mas deu na mesma.

Ao clicar no dev tools aparece o erro abaixo como se o modulo do admin não estivesse sendo encontrado (e eu conferi o caminho 30x, tentei fazer o caminho completo a partir do src que vi em alguns foruns ou só com a "/" sem o ponto inicial, mas nada deu certo..)

ERROR Error: Uncaught (in promise): Error: Cannot find module './admin/admin.module'
Error: Cannot find module './admin/admin.module'
    at $_lazy_route_resource lazy namespace object:5
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:388)

Tem alguma ideia de por qual motivo ele pode não estar encontrando esse novo modulo criado?!

5 respostas

Fala ai Enzo, tudo bem? Falando assim é bem complicado sem ver a estrutura do projeto, os códigos completos e simulando o problema.

Pelo erro que tu mandou, parece que não existe uma pasta admin com o arquivo admin.module.ts dentro da pasta onde encontra-se a definição da sua rota, talvez faltou tu sair para a pasta anterior ../ ou algo do tipo.

Espero ter ajudado.

Putz, imagino. Sem simular fica difícil pra alguém ajudar mesmo.

Pior que eu conferi 30x e não é o caminho. O caminho está correto.

Eu tentei ver algumas soluções no stackoverflow mas nenhuma deu certo. Eu postei lá tb mas creio que deve ser difícil alguém ajudar sem colocar a mão no projeto.

Uma orientação que me deram foi fazer o lazy loading na forma mais atual:

        path: 'admin',
        loadChildren: () => import('./admin/admin.module').then(, => m.AdminModule),

O problema é que esse modo suporta apenas o Angular 8 e no meu caso eu tenho o Angular 7.

Eu tomei coragem e tentei atualizar pois li que teriam poucas coisas a ajustar. E realmente deu certo fazendo com o lazy loading desse jeito. Mas em compensação um monte de coisa começou a quebrar, kk! Porque sempre precisa atualizar todas as libs e várias funções deixam de existir e precisam ser ajustas na mão né ?

Uma coisa que até deve ser simples mas eu estou quebrando a cabeça é que em uma das classes eu estava importando o Renderer. Mas no angular 8 parou de compilar e agora tenho que colocar o Renderer2.

Antes estava assim:

//imports

export class CardDirective implements OnInit {

    private nativeElement: Node;
    private loaderElement: Node;

    constructor(private renderer: Renderer, private element: ElementRef) {
        this.nativeElement = element.nativeElement;
    }

    ngOnInit() {
        if (this.loader) {
            this.initLoader();
        }

    showLoading() {
        const divElement = this.renderer.createElement(this.nativeElement, 'div');
        this.renderer.setElementClass(divElement, 'card-loading', true);
        this.renderer.setElementStyle(divElement, 'display', 'block');
        this.loaderElement = divElement;
        const nextElem = this.element.nativeElement.nextElementSibling;
        const parent = this.element.nativeElement.parentNode;

// restante da classe

O método setElementClass virou AddClass com apenas 2 parâmetros. E o setElementStyle virou setStyle. Até ai ok. O problema é o creatElement que pelo visto tem o mesmo nome mas no rendered2 ele não aceita mais fazer dessa forma e eu to quebrando um pouco a cabeça pra entender como deveria ficar.

Fala Enzo, fico feliz que o lazy loading tenha dado certo e é como tu mesmo falou, sem a gente ver o problema e analisá-lo com calma é bem complicado (tanto aqui quanto no Stackoverflow).

Sobre utilizar o novo formato de importação através de dynamic import é muito bom, recomendo também, o Angular tinha alguns problemas antigamente (o que pode ser o seu caso).

Referente a atualização da versão, isso é bem chato de fazer kkkk normalmente como tu mesmo disse e está passando, várias coisas quebra e precisam ser ajustadas também.

Como tu fez a atualização? Tem um comando no Angular que pode lhe ajudar, acho que é ng update e também temo guias de atualização na própria documentação do Angular.

Espero ter ajudado.

Boa, acho que eu consegui ajustar algumas cosias. Essa atualização do renderer para o renderer2 que eu acho que estou errando em algum lugar.

A única documentação que achei para atualizar foi a https://angular.io/guide/migration-renderer mas para mim está confuso...

Você olhando o código vê algum erro grosso no segundo modo ou não tem como saber só de ver ??

Antes (com renderer)

//imports

export class CardDirective implements OnInit {

    private nativeElement: Node;
    private loaderElement: Node;

    constructor(private renderer: Renderer, private element: ElementRef) {
        this.nativeElement = element.nativeElement;
    }

    ngOnInit() {
        if (this.loader) {
            this.initLoader();
        }

    showLoading() {
        const divElement = this.renderer.createElement(this.nativeElement, 'div');
        this.renderer.setElementClass(divElement, 'card-loading', true);
        this.renderer.setElementStyle(divElement, 'display', 'block');
        this.loaderElement = divElement;
        const nextElem = this.element.nativeElement.nextElementSibling;
        const parent = this.element.nativeElement.parentNode;
        parent.insertBefore(divElement, nextElem);

// restante da classe

Depois com renderer2

import { OnInit, Directive, Input, Renderer2, ElementRef } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Response } from '@angular/http';
import { Loader } from './loader';

@Directive({
    selector: '[asCardLoader]'
})
export class CardLoaderDirective implements OnInit {

    private nativeElement: Node;
    private loaderElement: Node;

    @Input()
    private loader: Loader;

    constructor(private renderer: Renderer2, private element: ElementRef) {
        this.nativeElement = element.nativeElement;
    }

    ngOnInit() {
        if (this.loader) {
            this.initLoader();
        }
    }

    tryAgain() {
        document.getElementsByClassName('try-again').item(0).remove();
        this.ngOnInit();
    }

    showLoading() {
        const divElement = this.renderer.createElement('div');
        this.renderer.appendChild(this.nativeElement, divElement);
        this.renderer.addClass(divElement, 'card-loading');
        this.renderer.setStyle(divElement, 'display', 'block');
        this.loaderElement = divElement;
        const nextElem = this.element.nativeElement.nextElementSibling;
        const parent = this.element.nativeElement.parentNode;

        parent.insertBefore(divElement, nextElem);
    }
solução!

Fala Enzo, olhando os códigos eu não vejo nada errado, claro que posso estar deixando passar alguns detalhes e ajustes, mas, me parece bom.

Espero ter ajudado.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software