Используйте фабрику маршрутов (для использования DI)

import { ROUTES } from '@angular/router';

providers: [
  {
    provide: ROUTES,
    useFactory: () => {
      const myService = inject(MyService);
      
      return getRoutes(myService); // using your service variables to manipulate routes
    }
  }
]

Изменять loadComponent или loadChildren

getRoutes = (myService) => 
[
  {
    path: 'samples',
    loadComponent: () => 
        myService.mode === 'v1' 
          ? import('./samples-v1.module') // module having default export
          : import('./samples-v2.module') // module having default export
  }
]

или изменить matcher

getRoutes = (myService) => 
[
  {
    matcher: (urlSegment: UrlSegment[]) => {
          return myService.mode === 'v1' && url[0].path === 'samples'
            ? { consumed: url }
            : null;
        },
    loadComponent: () => import('./samples-v1.module')
  },
  {
    matcher: (urlSegment: UrlSegment[]) => {
          return myService.mode === 'v2' && url[0].path === 'samples'
            ? { consumed: url }
            : null;
        },
    loadComponent: () => import('./samples-v2.module')
  }
]

В качестве альтернативы вы можете использовать карту вместо условий if-else.

componentsMap = {
  v1: () => import('./samples-v1.module'), // module having default export
  v2: () => import('./samples-v2.module').then(m => m.SampleV2Component) // not default export
}

export class UtilService {
  loadComponent(version) {
    return componentsMap[version]();
  }
}

или Загрузите свой компонент в распознаватель

// Route
{
  path: 'samples',
  component: SamplesContainerComponent
  resolve: {
          componentToBeInstantiated: resolveComponentFn,
  },
}


// resolveComponentFn
const resolveComponentFn: ResolveFn<unknown> = (route) => {
  const myService = inject(MyService);
  const utilSerive = inject(UtilService);

  return lastValueFrom(
            myService.getVersion(route.queryParamMap.get('platform'))
         ).then(v => {
            return utilService.loadComponent(v);
         })
}

Использование разрешенного компонента в компоненте-оболочке

<-- SamplesContainerComponent template -->
<section>
   <ng-container
          *ngComponentOutlet="
            componentToBeInstantiated;
            content: [[footer]]
          ">
   </ng-container>
</section>
<footer #footer>Content inside footer</footer>

или Создание вашего ленивого компонента через router-outlet

@Component({
  template: `<router-outlet></router-outlet>`
})
export class SamplesContainerComponent implements OnInit {
  @ViewChild(RouterOutlet) routerOutlet: RouterOutlet;
  private readonly myService = inject(MyService);

  ngOnInit(): void {
    this.myService.getRequiredComponent().pipe(untilDestroyed(this))
      .subscribe((compClass) => {
        this.routerOutlet.attach(
          this.viewContainerRef.createComponent(compClass),
          this.route
        );
      });
  }
}

Используйте свой ленивый «автономный» компонент в диалоговом окне

openDialog(v) {
  this.utilService.loadComponent(v).then(m => {
    this.matDialog.open(m.MyComponent, {
      id: 'call',
      disableClose: true,
      data: {type: 'video'}
    });
  });
}

Вы можете использовать те же стратегии даже для загрузки удаленных компонентов или модулей с помощью подключаемого модуля объединения модулей.

Спасибо, что были с вами, поаплодируйте 👏, если вам понравился контент, и следите за обновлениями, чтобы узнать больше о таком контенте.