How can I use a class that use conditional export in Angular's app.module?

青春壹個敷衍的年華 提交于 2020-06-16 17:47:01

问题


This question is the beggining of the story if you want to understand it deeper.

I'm trying to use this class in app.module:

import { Injectable } from '@angular/core';
import { KeycloakService } from 'keycloak-angular';
import { environment } from '../../../environments/environment';

@Injectable({ providedIn: 'root' })
export class MockKeycloakService { 

    init(ign: any) {
        console.log('[KEYCLOAK] Mocked Keycloak call');
        return Promise.resolve(true);
    }

    getKeycloakInstance() {
        return {
            loadUserInfo: () => {
                let callback;
                Promise.resolve().then(() => {
                    callback({
                    username: '111111111-11',
                    name: 'Whatever Something de Paula',
                    email: 'whatever@gmail.com',
                  });
                });
                return { success: (fn) => callback = fn };
            }
        } as any;
    }    
    login() {}      
    logout() {}
}

const exportKeycloak = 
    environment.production ? KeycloakService : MockKeycloakService;    
export default exportKeycloak; 

This conditional export fakes keycloak call to use in local development and returns the real class in production.

This is the app.module I used:

<...>
import { KeycloakAngularModule } from 'keycloak-angular';
import KeycloakService from './shared/services/keycloak-mock.service';
import { initializer } from './app-init';
<...>

    imports: [
        KeycloakAngularModule,
         <...>  
    ],
    providers: [
        <...>,
        {
            provide: APP_INITIALIZER,
            useFactory: initializer,
            multi: true,
            deps: [KeycloakService, <...>]
        },
        <...>
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

related app-init:

import KeycloakService from './shared/services/keycloak.mock.service';
import { KeycloakUser } from './shared/models/keycloakUser';

import { environment } from '../environments/environment';
<...>

export function initializer(
    keycloak: any,
    <...>
): () => Promise<any> {
    return (): Promise<any> => {
        return new Promise(async (res, rej) => {
            <...>    
            await keycloak.init({
                 <...>
            }).then((authenticated: boolean) => {
                if (!authenticated) return;
                keycloak
                    .getKeycloakInstance()
                    .loadUserInfo()
                    .success(async (user: KeycloakUser) => {
                        <...>
                    })    
            }).catch((err: any) => rej(err));
            res();
        });
    };

All works fine in the development mode. I can use the mocked call, and if I enable production in environment.config it makes the real call. But when I try to build it to publish in production server I get the following error:

ERROR in Can't resolve all parameters for ɵ1 in /vagrant/frontend/src/app/app.module.ts: (?, [object Object], [object Object]).

My guess is that the builder task can't understand the conditional export in the mocked class to use in app.module.

So this forced me to use both classes in the app-init and other class I use it and check for the environment mode in every one. I think it would be a much better solution if I could use only one class to treat this and just import it in all places I need.

this is my build command:

ng build --prod=true --configuration=production --delete-output-path --output-path=dist/

How can I overcome this error in the build ? Also... why on earth all works well in dev mode and the build behaves differently ?


回答1:


I guess you're using Angular 8 or less.

AOT compiler in those versions doesn't support resolving reference to default export.

So you should be more specific:

keycloak-mock.service.ts

const KeycloakServiceImpl =
  environment.production ? KeycloakService : MockKeycloakService;
export { KeycloakServiceImpl };

app.module.ts

import { KeycloakServiceImpl } from './keycloak-mock.service';

...
deps: [KeycloakServiceImpl]

Tip:

ng build --prod is an equivalent of ng build --prod=true --configuration=production



来源:https://stackoverflow.com/questions/62029756/how-can-i-use-a-class-that-use-conditional-export-in-angulars-app-module

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!