window未定义angular通用第三库
window is not defined angular universal third library
我正在使用库 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)
我该如何解决这个问题?
window
不应在服务器端的通用应用程序中使用,因为 Node.js 没有 window
,并且有一个虚拟的 global.window
当前会影响Angular 检测全局变量的方式。
如果包使用 window
,可以在其存储库中打开一个问题 and/or 可以分叉并更改为不使用 window
。
由于依赖 window
的包通常依赖于特定于客户端的东西,即使解决了这个问题,它们也不会在服务器端按预期工作。
Depends on the library from: https://eclipse.org/paho/clients/js/
虽然 library description 说:
The Paho JavaScript Client is an MQTT browser-based client library written in Javascript that uses WebSockets to connect to an MQTT Broker.
通常第三方 Angular 模块不应该在服务器端按预期工作应该被存根或模拟;带有虚假指令和服务的虚拟模块被导入 app.server.ts
而不是真正的模块。
避免服务器错误的一种可能方法是不呈现使用 window
的组件(如果它是一个选项)。类似于:
<ng-container *ngIf="isBrowser">
<!-- mqttws31-component -->
<mqttws31-component></mqttws31-component>
</ng-container>
可以从 (ng2) 导入 isBrowser
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 在server.ts中使用:
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;
更新
扩展 Leon Li 的答案,我们可以避免加载无法在服务器端呈现的组件,如果它需要浏览器 API,如位置或 window。
This answer 说明如何使用
import { PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
constructor( @Inject(PLATFORM_ID) platformId: Object) {
this.isBrowser = isPlatformBrowser(platformId);
}
只需将 PLATFORM_ID 注入您的服务,然后将其传递给 isPlatformBrowser
或 isPlatformServer
以获得布尔值。因此,如果依赖于浏览器 API,您可以 show/hide 无法在服务器上呈现的组件。
为我工作ng9+
// app.module.ts
@NgModule({
providers: [
{ provide: 'isBrowser', useValue: true }
]
})
并替换绝对路径(删除第一个/):
/assets/images/...到assets/images/...
我正在使用库 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)
我该如何解决这个问题?
window
不应在服务器端的通用应用程序中使用,因为 Node.js 没有 window
,并且有一个虚拟的 global.window
当前会影响Angular 检测全局变量的方式。
如果包使用 window
,可以在其存储库中打开一个问题 and/or 可以分叉并更改为不使用 window
。
由于依赖 window
的包通常依赖于特定于客户端的东西,即使解决了这个问题,它们也不会在服务器端按预期工作。
Depends on the library from: https://eclipse.org/paho/clients/js/
虽然 library description 说:
The Paho JavaScript Client is an MQTT browser-based client library written in Javascript that uses WebSockets to connect to an MQTT Broker.
通常第三方 Angular 模块不应该在服务器端按预期工作应该被存根或模拟;带有虚假指令和服务的虚拟模块被导入 app.server.ts
而不是真正的模块。
避免服务器错误的一种可能方法是不呈现使用 window
的组件(如果它是一个选项)。类似于:
<ng-container *ngIf="isBrowser">
<!-- mqttws31-component -->
<mqttws31-component></mqttws31-component>
</ng-container>
可以从 (ng2) 导入 isBrowser
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 在server.ts中使用:
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;
更新
扩展 Leon Li 的答案,我们可以避免加载无法在服务器端呈现的组件,如果它需要浏览器 API,如位置或 window。
This answer 说明如何使用
import { PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
constructor( @Inject(PLATFORM_ID) platformId: Object) {
this.isBrowser = isPlatformBrowser(platformId);
}
只需将 PLATFORM_ID 注入您的服务,然后将其传递给 isPlatformBrowser
或 isPlatformServer
以获得布尔值。因此,如果依赖于浏览器 API,您可以 show/hide 无法在服务器上呈现的组件。
为我工作ng9+
// app.module.ts
@NgModule({
providers: [
{ provide: 'isBrowser', useValue: true }
]
})
并替换绝对路径(删除第一个/):
/assets/images/...到assets/images/...