Как я могу использовать класс, который использует условный экспорт в app.module Angular? - PullRequest
1 голос
/ 26 мая 2020

Этот вопрос является началом истории, если вы хотите понять его глубже.

Я пытаюсь использовать этот класс в 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; 

Этот условный экспорт подделывает вызов keycloak для использования в локальной разработке и возвращает реальный класс в производстве.

Это модуль app.module, который я использовал:

<...>
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();
        });
    };

Все отлично работает в режиме разработки. Я могу использовать фиктивный вызов, и если я включу производство в environment.config, он сделает настоящий вызов. Но когда я пытаюсь собрать его для publi sh на производственном сервере, я получаю следующую ошибку:

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

Я предполагаю, что задача сборщика не может понять условный экспорт в имитируемом классе для использования в app.module.

Итак, это заставило меня использовать оба класса в app-init и другом классе, который я использую, и проверять режим среды в каждом из них. Я думаю, что было бы намного лучше, если бы я мог использовать только один класс для лечения этого и просто импортировать его во все места, которые мне нужны.

это моя команда сборки:

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

Как мне исправить эту ошибку при сборке? Кроме того ... почему, черт возьми, все работает хорошо в режиме разработки, а сборка ведёт себя по-другому?

1 Ответ

1 голос
/ 28 мая 2020

Я думаю, вы используете Angular 8 или меньше.

Компилятор AOT в этих версиях не поддерживает разрешение ссылки на экспорт по умолчанию.

Итак вы должны быть более конкретными c:

keycloak-mock.service.ts

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

app.module.ts

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

...
deps: [KeycloakServiceImpl]

Совет:

ng build --prod эквивалентно ng build --prod=true --configuration=production

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...