2016-11-22 1 views
2

조건에 따라 모듈을 가져올 수 있습니까? 각도 2 범용 앱이 브라우저에서는 렌더링되지만 서버에서는 렌더링되지 않는 경우에만 외부 모듈을 가져옵니다.angular universal : 브라우저 전용 동적 가져 오기

이 질문은 브라우저 기능에 의존하는 일부 PrimeNG 모듈과 관련이 있으며 브라우저에서만 렌더링 할 수 있습니다. 그것은 서버 렌더링 원인 캘린더 및 기타 구성 요소에 대한 SEO 정말 중요하지 않습니다 그들을 생략하는 것이 좋을 것입니다.

현재 서버 렌더링을 끄면 Calendar 구성 요소를 렌더링 할 수 있습니다. 그러나 아래 코드를 app.module.ts에 포함시키고 서버 렌더링을 켜면 server.js에서 'ReferenceError : Event is not defined'오류가 발생합니다.

import { CalendarModule } from 'primeng/components/calendar/calendar'; 
 
@NgModule({ 
 
    ... 
 
    imports: [ 
 
     ..., 
 
     CalendarModule 
 
    ] 
 
})

는 각도에 의해 제공된 isBrowser 조건이있다.

import { isBrowser } from 'angular2-universal';
하지만 조건부 수입을 위해 사용하는 방법을 모르겠어요. 실제로 모듈을 사용하는 방법이 있습니까?

답변

4

그래서 PrimeNG 구성 요소를 브라우저에서 렌더링하고 서버 렌더링 중에이를 생략하는 방법이 있습니다. 그 질문은 내가 올바른 방향을 파고 시작 도움 :

angular-cli: Conditional Imports using an environment variable

How can I conditionally import an ES6 module?

서버가 나는 간단한 입력 필드를 렌더링과 같은 선택 'P-캘린더'를 사용하는 모의 구성 요소를 사용하여 렌더링하는 동안. 마지막 코드는 app.module에서 끝났습니다.

...//other imports 
 
import { isBrowser } from 'angular2-universal'; 
 

 
let imports = [ 
 
    ... //your modules here 
 
]; 
 
let declarations = [ 
 
    ... //your declarations here 
 
]; 
 

 
if (isBrowser) { 
 
    let CalendarModule = require('primeng/components/calendar/calendar').CalendarModule; 
 
    imports.push(CalendarModule); 
 
} 
 
else { 
 
    let CalendarMockComponent = require('./components/primeng/calendarmock.component').CalendarMockComponent; 
 
    declarations.push(CalendarMockComponent); 
 
} 
 

 
@NgModule({ 
 
    bootstrap: [AppComponent], 
 
    declarations: declarations, 
 
    providers: [ 
 
     ... //your providers here 
 
    ], 
 
    imports: imports 
 
})

이 모의 구성 요소 지원을 위해 [(ngModel)]이 튜토리얼 사용을 바인딩. http://almerosteyn.com/2016/04/linkup-custom-control-to-ngcontrol-ngmodel

import { Component, forwardRef } from '@angular/core'; 
 
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'; 
 

 
export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = { 
 
    provide: NG_VALUE_ACCESSOR, 
 
    useExisting: forwardRef(() => CalendarMockComponent), 
 
    multi: true 
 
}; 
 

 
@Component({ 
 
    selector: 'p-calendar', 
 
    template: '<input type="text" class="form-control"/>', 
 
    providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR] 
 
}) 
 
export class CalendarMockComponent implements ControlValueAccessor { 
 

 
    private innerValue: any = ''; 
 

 
    private onTouchedCallback:() => void =() => {}; 
 
    private onChangeCallback: (_: any) => void =() => {}; 
 

 
    //From ControlValueAccessor interface 
 
    writeValue(value: any) { 
 
     if (value !== this.innerValue) { 
 
      this.innerValue = value; 
 
     } 
 
    } 
 

 
    registerOnChange(fn: any) { 
 
     this.onChangeCallback = fn; 
 
    } 
 

 
    registerOnTouched(fn: any) { 
 
     this.onTouchedCallback = fn; 
 
    } 
 
}

+0

isBlast 대신 isPlatformBrowser를 사용하여이 작업을 수행하는 방법을 알고 있습니까? –

+0

@RaymondtheDeveloper 유니버셜 "Gotchas"섹션에서 isPlatformBrowser가 [here] (https://www.npmjs.com/package/angular4-aspnetcore-universal)에서 설명한대로 작동해야한다고 생각합니다. 다른 모든 것은 isBrowser와 동일해야합니다. 시도 해봐. – Rodion

+0

문제는 app.module.ts 내부에서 사용하고 싶다는 것입니다. 거기에 PLATFORM_ID를 주입하는 방법을 모르겠습니다.그리고 isPlatformBrowser가 작동하려면 PLATFORM_ID가 필요합니다. –

0

동적 스크립트 로딩을 필요로하지 않는 모듈 수입에 대한 대체 솔루션 : 당신이 서버 - 가져온 모듈을 리디렉션 서버 응용 프로그램의 tsconfig.json 파일에 compilerOptions.paths 옵션을 사용할 수 있습니다 전용 버전 :

{ 
    ... 
    "compilerOptions": { 
     ... 
     "paths": { 
      "path/to/browser/module": "path/to/server/module" 
     } 
    } 
} 

서버 응용 프로그램이 빌드되면 컴파일러는 브라우저 모듈 대신 서버 모듈을 가져옵니다.