窗口并没有定义角度通用第三库



我正在使用ng2-mqtt库,我在我的组件中使用了它,如下所示:

import 'ng2-mqtt/mqttws31.js';
declare var Paho: any;

现在我得到以下错误:

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)

如何解决此问题?

更新

扩展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);
}

只需将PLATFORM_ID注入到服务中,并将其传递给isPlatformBrowserisPlatformServer即可获得布尔值。因此,如果组件依赖于浏览器API,则可以显示/隐藏无法在服务器上呈现的组件。

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

<ng-container *ngIf="isBrowser">
<!-- mqttws31-component -->
<mqttws31-component></mqttws31-component> 
</ng-container>

isBrowser可以从(ng2)导入

import { isBrowser } from 'angular2-universal';

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

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

然后从构造函数注入

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!');
}
}

Angular 6在服务器中使用:

const domino = require('domino');
const fs = require('fs');
const path = require('path');
const template = fs.readFileSync('dist/browser/index.html').toString();
const win = domino.createWindow(template);
global['window'] = win;
global['document'] = win.document;
global['DOMTokenList'] = win.DOMTokenList;
global['Node'] = win.Node;
global['Text'] = win.Text;
global['HTMLElement'] = win.HTMLElement;
global['navigator'] = win.navigator;

window不应该在服务器端的通用应用程序中使用,因为Node.js没有window,并且当前有一个伪global.window会影响Angular检测全局变量的方式。

如果包使用window,则可以在其存储库中打开问题和/或将其分叉并更改为不使用window

由于依赖window的包通常依赖于客户端特定的东西,因此即使解决了这个问题,它们在服务器端也不会像预期的那样工作。

包装说明上写着:

取决于以下库:https://eclipse.org/paho/clients/js/

而库描述说:

Paho JavaScript客户端是一个用JavaScript编写的基于浏览器的MQTT客户端库,它使用WebSockets连接到MQTT Broker。

通常,不应该在服务器端按预期工作的第三方Angular模块应该被存根或嘲笑;在app.server.ts中引入了具有伪指令和服务的伪模块,而不是真实模块。

为我工作ng9+

// app.module.ts
@NgModule({
providers: [
{ provide: 'isBrowser', useValue: true }
]
})

并替换绝对路径(先删除/):

/资产/图像/。。。到资产/图像/。。。

最新更新