窗口未定义角度通用第三库

mog*_*gli 3 javascript typescript angular-universal angular

我正在使用库ng2-mqtt,我在我的组件中使用它是这样的:

 import 'ng2-mqtt/mqttws31.js';
declare var Paho: any;
Run Code Online (Sandbox Code Playgroud)

现在我收到以下错误:

ReferenceError: window is not defined
    at Object.<anonymous> (/Users/Picchu/Documents/em3/node_modules/ng2-mqtt/mqttws31.js:2143:4)
    at Module._compile (module.js:556:32)
    at Object.Module._extensions..js (module.js:565:10)
    at Module.load (module.js:473:32)
    at tryModuleLoad (module.js:432:12)
    at Function.Module._load (module.js:424:3)
    at Module.require (module.js:483:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/Users/Picchu/Documents/em3/dist/server.js:18707:18)
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个问题?

LeO*_* Li 6

避免服务器错误的一种可能方法是不渲染使用的组件(如果它是一个选项)window.就像是:

<ng-container *ngIf="isBrowser">
   <!-- mqttws31-component -->
   <mqttws31-component></mqttws31-component> 
</ng-container>
Run Code Online (Sandbox Code Playgroud)

isBrowser可以从(ng2)导入

import { isBrowser } from 'angular2-universal';
Run Code Online (Sandbox Code Playgroud)

或者如果是ng4 +,您也可以在浏览器模块中定义:

// app.browser
@NgModule({
  providers: [
    { provide: 'isBrowser', useValue: true }
  ]
})
Run Code Online (Sandbox Code Playgroud)

然后从构造函数注入

export class SomeComponent implements OnInit {
  constructor(@Inject('isBrowser') private isBrowser: boolean)
  ngOnInit() { 
    // example usage, this could be anywhere in this Component of course
    if (this.isBrowser) { 
      alert('we're in the browser!');
    }
}
Run Code Online (Sandbox Code Playgroud)


Mah*_*esh 6

更新

扩展 Leon Li 的回答,如果需要浏览器 API(如位置或窗口),我们可以避免加载无法在服务器端呈现的组件。

这个答案解释了如何使用

import { PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';

constructor( @Inject(PLATFORM_ID) platformId: Object) {
  this.isBrowser = isPlatformBrowser(platformId);
}
Run Code Online (Sandbox Code Playgroud)

只需将 PLATFORM_ID 注入您的服务,然后将其传递给isPlatformBrowserorisPlatformServer以获取布尔值。因此,您可以显示/隐藏无法在服务器上呈现的组件(如果它们依赖于浏览器 API)。